@@ -95,8 +95,33 @@ public Q_SLOTS:
9595
9696private:
9797 interfaces::Node& m_node;
98+ bool executeConsoleHelpConsole (const std::vector<std::string>& parsed_command, const WalletModel* wallet_model, const bool exec_help = false );
99+ bool executeConsoleOnlyCommand (const std::string& command, const WalletModel* wallet_model);
100+ // std::map mapping strings to methods member of RPCExecutor class
101+ // Keys must be strings with commands and (optionally) parameters in "canonical" form (separated by single space)
102+ // Keys should match the beggining of user input commands (user commands can have more parameters than the key)
103+ std::map<std::string, bool (RPCExecutor::*)(const std::vector<std::string>&, const WalletModel*, const bool )> m_method_map{
104+ {" help-console" , &RPCExecutor::executeConsoleHelpConsole}};
98105};
99106
107+ /* *
108+ * Small and fast parser supporting console command syntax, with limited functionality.
109+ * Splits a command line string into a vector with command at position 0, and parameters after
110+ *
111+ * @param[in] strCommand Command line to parse
112+ *
113+ * @return a vector of strings with command and parameters
114+ */
115+ std::vector<std::string> parseHelper (const std::string& strCommand)
116+ {
117+ // Split while recognizing the several characters that can be used as separators in the GUI console
118+ std::vector<std::string> vec{SplitString (strCommand, " ()," )};
119+ // Remove empty strings produced by consecutive separators
120+ auto should_remove{[](const std::string& str) { return str.empty (); }};
121+ vec.erase (std::remove_if (vec.begin (), vec.end (), should_remove), vec.end ());
122+ return vec;
123+ }
124+
100125/* * Class for handling RPC timers
101126 * (used for e.g. re-locking the wallet after a timeout)
102127 */
@@ -414,35 +439,15 @@ void RPCExecutor::request(const QString &command, const WalletModel* wallet_mode
414439 std::string result;
415440 std::string executableCommand = command.toStdString () + " \n " ;
416441
417- // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
418- if (executableCommand == " help-console\n " ) {
419- Q_EMIT reply (RPCConsole::CMD_REPLY, QString ((" \n "
420- " This console accepts RPC commands using the standard syntax.\n "
421- " example: getblockhash 0\n\n "
422-
423- " This console can also accept RPC commands using the parenthesized syntax.\n "
424- " example: getblockhash(0)\n\n "
425-
426- " Commands may be nested when specified with the parenthesized syntax.\n "
427- " example: getblock(getblockhash(0) 1)\n\n "
428-
429- " A space or a comma can be used to delimit arguments for either syntax.\n "
430- " example: getblockhash 0\n "
431- " getblockhash,0\n\n "
432-
433- " Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n "
434- " example: getblock(getblockhash(0) 1)[tx]\n\n "
435-
436- " Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n "
437- " example: getblock(getblockhash(0),1)[tx][0]\n\n " )));
438- return ;
439- }
440- if (!RPCConsole::RPCExecuteCommandLine (m_node, result, executableCommand, nullptr , wallet_model)) {
441- Q_EMIT reply (RPCConsole::CMD_ERROR, QString (" Parse error: unbalanced ' or \" " ));
442- return ;
442+ // Attempt to execute console-only commands
443+ if (!RPCExecutor::executeConsoleOnlyCommand (command.toStdString (), wallet_model)) {
444+ // Send to the RPC command parser if not console-only
445+ if (!RPCConsole::RPCExecuteCommandLine (m_node, result, executableCommand, nullptr , wallet_model)) {
446+ Q_EMIT reply (RPCConsole::CMD_ERROR, QString (" Parse error: unbalanced ' or \" " ));
447+ return ;
448+ }
449+ Q_EMIT reply (RPCConsole::CMD_REPLY, QString::fromStdString (result));
443450 }
444-
445- Q_EMIT reply (RPCConsole::CMD_REPLY, QString::fromStdString (result));
446451 }
447452 catch (UniValue& objError)
448453 {
@@ -463,6 +468,59 @@ void RPCExecutor::request(const QString &command, const WalletModel* wallet_mode
463468 }
464469}
465470
471+ /* *
472+ * @brief Executes the console-only command "help-console".
473+ * @param parsed_command A vector of strings with command and parameters, usually generated by RPCExecutor::parseHelper
474+ * @param wallet_model WalletModel to use for the command
475+ * @return True if the command was executed, false otherwise.
476+ */
477+ bool RPCExecutor::executeConsoleHelpConsole (const std::vector<std::string>& parsed_command, const WalletModel* wallet_model, const bool exec_help)
478+ {
479+ // Reply with help text as-if a RPC reply.
480+ Q_EMIT reply (RPCConsole::CMD_REPLY,
481+ QString (" \n "
482+ " This console accepts RPC commands using the standard syntax.\n "
483+ " example: getblockhash 0\n\n "
484+ " This console can also accept RPC commands using the parenthesized syntax.\n "
485+ " example: getblockhash(0)\n\n "
486+ " Commands may be nested when specified with the parenthesized syntax.\n "
487+ " example: getblock(getblockhash(0) 1)\n\n "
488+ " A space or a comma can be used to delimit arguments for either syntax.\n "
489+ " example: getblockhash 0\n "
490+ " getblockhash,0\n\n "
491+ " Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n "
492+ " example: getblock(getblockhash(0) 1)[tx]\n\n "
493+ " Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n "
494+ " example: getblock(getblockhash(0),1)[tx][0]\n\n " ));
495+ return true ;
496+ }
497+
498+ /* *
499+ * Catches console-only command before a RPC call is executed
500+ *
501+ * @param[in] command Command line to execute
502+ * @param[in] wallet_model Wallet model to use
503+ * @return true if command was handled by this method (even on errors), false otherwise
504+ *
505+ */
506+ bool RPCExecutor::executeConsoleOnlyCommand (const std::string& command, const WalletModel* wallet_model)
507+ {
508+ // Parse command line into a vector of strings
509+ const std::vector<std::string> parsed_command{parseHelper (command)};
510+
511+ if (parsed_command.empty ()) return false ;
512+
513+ std::string method = parsed_command[0 ];
514+ bool exec_help = false ;
515+ if (method == " help" && parsed_command.size () > 1 ) {
516+ exec_help = true ;
517+ method = parsed_command[1 ];
518+ }
519+ auto it_method = m_method_map.find (method);
520+ if (it_method == m_method_map.end ()) return false ; // method not found
521+ return (this ->*(it_method->second ))(parsed_command, wallet_model, exec_help);
522+ }
523+
466524RPCConsole::RPCConsole (interfaces::Node& node, const PlatformStyle *_platformStyle, QWidget *parent) :
467525 QWidget(parent),
468526 m_node(node),
0 commit comments