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