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