openMSX
Command.hh
Go to the documentation of this file.
1 #ifndef COMMAND_HH
2 #define COMMAND_HH
3 
4 #include "Completer.hh"
5 #include "span.hh"
6 #include "strCat.hh"
7 #include "CommandException.hh"
8 #include <string_view>
9 #include <vector>
10 
11 namespace openmsx {
12 
13 class CommandController;
14 class GlobalCommandController;
15 class Interpreter;
16 class TclObject;
17 class CliComm;
18 
20 {
21 public:
22  CommandCompleter(const CommandCompleter&) = delete;
24 
25  CommandController& getCommandController() const { return commandController; }
26  Interpreter& getInterpreter() const final;
27 
28 protected:
29  CommandCompleter(CommandController& controller, std::string_view name);
31 
33  CliComm& getCliComm() const;
34 
35 private:
36  CommandController& commandController;
37 };
38 
39 
40 class Command : public CommandCompleter
41 {
42  struct UnknownSubCommand {};
43 
44 public:
53  virtual void execute(span<const TclObject> tokens, TclObject& result) = 0;
54 
61  void tabCompletion(std::vector<std::string>& tokens) const override;
62 
63  // see comments in MSXMotherBoard::loadMachineCommand
64  void setAllowedInEmptyMachine(bool value) { allowInEmptyMachine = value; }
65  bool isAllowedInEmptyMachine() const { return allowInEmptyMachine; }
66 
67  // used by Interpreter::(un)registerCommand()
68  void setToken(void* token_) { assert(!token); token = token_; }
69  void* getToken() const { return token; }
70 
71  // helper to delegate to a subcommand
72  template<typename... Args>
73  void executeSubCommand(std::string_view subcmd, Args&&... args) {
74  try {
75  executeSubCommandImpl(subcmd, std::forward<Args>(args)...);
76  } catch (UnknownSubCommand) {
77  unknownSubCommand(subcmd, std::forward<Args>(args)...);
78  }
79  }
80 
81 protected:
82  Command(CommandController& controller, std::string_view name);
83  ~Command();
84 
85 private:
86  template<typename Func, typename... Args>
87  void executeSubCommandImpl(std::string_view subcmd, std::string_view candidate, Func func, Args&&... args) {
88  if (subcmd == candidate) {
89  func();
90  } else {
91  executeSubCommandImpl(subcmd, std::forward<Args>(args)...);
92  }
93  }
94  void executeSubCommandImpl(std::string_view /*subcmd*/) {
95  throw UnknownSubCommand{}; // exhausted all possible candidates
96  }
97 
98  template<typename Func, typename... Args>
99  void unknownSubCommand(std::string_view subcmd, std::string_view firstCandidate, Func /*func*/, Args&&... args) {
100  unknownSubCommandImpl(strCat("Unknown subcommand '", subcmd, "'. Must be one of '", firstCandidate, '\''),
101  std::forward<Args>(args)...);
102  }
103  template<typename Func, typename... Args>
104  void unknownSubCommandImpl(std::string message, std::string_view candidate, Func /*func*/, Args&&... args) {
105  strAppend(message, ", '", candidate, '\'');
106  unknownSubCommandImpl(message, std::forward<Args>(args)...);
107  throw SyntaxError();
108  }
109  template<typename Func>
110  void unknownSubCommandImpl(std::string message, std::string_view lastCandidate, Func /*func*/) {
111  strAppend(message, " or '", lastCandidate, "'.");
112  throw CommandException(message);
113  }
114 
115 private:
116  bool allowInEmptyMachine;
117  void* token;
118 };
119 
120 } // namespace openmsx
121 
122 #endif
GlobalCommandController & getGlobalCommandController() const
Definition: Command.cc:30
virtual void tabCompletion(std::vector< std::string > &tokens) const =0
Attempt tab completion for this command.
Definition: span.hh:34
CommandCompleter(const CommandCompleter &)=delete
void strAppend(std::string &result, Ts &&...ts)
Definition: strCat.hh:644
bool isAllowedInEmptyMachine() const
Definition: Command.hh:65
void setAllowedInEmptyMachine(bool value)
Definition: Command.hh:64
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
CommandController & getCommandController() const
Definition: Command.hh:25
Interpreter & getInterpreter() const final
Definition: Command.cc:41
CommandCompleter & operator=(const CommandCompleter &)=delete
CliComm & getCliComm() const
Definition: Command.cc:46
void setToken(void *token_)
Definition: Command.hh:68
void * getToken() const
Definition: Command.hh:69
std::string strCat(Ts &&...ts)
Definition: strCat.hh:573
void executeSubCommand(std::string_view subcmd, Args &&... args)
Definition: Command.hh:73