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