openMSX
GlobalCommandController.cc
Go to the documentation of this file.
2 #include "Reactor.hh"
3 #include "Setting.hh"
4 #include "ProxyCommand.hh"
5 #include "ProxySetting.hh"
6 #include "LocalFileReference.hh"
7 #include "GlobalCliComm.hh"
8 #include "CliConnection.hh"
9 #include "CommandException.hh"
10 #include "SettingsManager.hh"
11 #include "TclObject.hh"
12 #include "Version.hh"
13 #include "ScopedAssign.hh"
14 #include "join.hh"
15 #include "outer.hh"
16 #include "ranges.hh"
17 #include "stl.hh"
18 #include "StringOp.hh"
19 #include "view.hh"
20 #include "xrange.hh"
21 #include "build-info.hh"
22 #include <cassert>
23 #include <memory>
24 
25 using std::string;
26 using std::string_view;
27 using std::vector;
28 
29 namespace openmsx {
30 
32  EventDistributor& eventDistributor,
33  GlobalCliComm& cliComm_, Reactor& reactor_)
34  : cliComm(cliComm_)
35  , connection(nullptr)
36  , reactor(reactor_)
37  , openMSXInfoCommand(*this, "openmsx_info")
38  , hotKey(reactor.getRTScheduler(), *this, eventDistributor)
39  , settingsConfig(*this, hotKey)
40  , helpCmd(*this)
41  , tabCompletionCmd(*this)
42  , updateCmd(*this)
43  , platformInfo(getOpenMSXInfoCommand())
44  , versionInfo (getOpenMSXInfoCommand())
45  , romInfoTopic(getOpenMSXInfoCommand())
46 {
47 }
48 
50 
52 {
53  // GlobalCommandController destructor must have run before
54  // we can check this.
55 #ifdef DEBUG
56  assert(commands.empty());
57 #endif
58  assert(commandCompleters.empty());
59 }
60 
62 {
63  auto it = proxyCommandMap.find(name);
64  if (it == end(proxyCommandMap)) {
65  it = proxyCommandMap.emplace_noDuplicateCheck(
66  0, std::make_unique<ProxyCmd>(reactor, name));
67  }
68  ++it->first;
69 }
70 
72 {
73  auto it = proxyCommandMap.find(name);
74  assert(it != end(proxyCommandMap));
75  assert(it->first > 0);
76  --it->first;
77  if (it->first == 0) {
78  proxyCommandMap.erase(it);
79  }
80 }
81 
82 GlobalCommandController::ProxySettings::iterator
83 GlobalCommandController::findProxySetting(string_view name)
84 {
85  return ranges::find_if(proxySettings, [&](auto& v) {
86  return v.first->getFullName() == name;
87  });
88 }
89 
91 {
92  const auto& name = setting.getBaseNameObj();
93  auto it = findProxySetting(name.getString());
94  if (it == end(proxySettings)) {
95  // first occurrence
96  auto proxy = std::make_unique<ProxySetting>(reactor, name);
99  proxySettings.emplace_back(std::move(proxy), 1);
100  } else {
101  // was already registered
102  ++(it->second);
103  }
104 }
105 
107 {
108  auto it = findProxySetting(setting.getBaseName());
109  assert(it != end(proxySettings));
110  assert(it->second);
111  --(it->second);
112  if (it->second == 0) {
113  auto& proxy = *it->first;
116  move_pop_back(proxySettings, it);
117  }
118 }
119 
121 {
122  return cliComm;
123 }
124 
126 {
127  return interpreter;
128 }
129 
131  Command& command, zstring_view str)
132 {
133 #ifdef DEBUG
134  assert(!commands.contains(str));
135  commands.emplace_noDuplicateCheck(str, &command);
136 #endif
137  interpreter.registerCommand(str, command);
138 }
139 
141  Command& command, string_view str)
142 {
143  (void)str;
144 #ifdef DEBUG
145  assert(commands.contains(str));
146  assert(commands[str] == &command);
147  commands.erase(str);
148 #endif
149  interpreter.unregisterCommand(command);
150 }
151 
153  CommandCompleter& completer, string_view str)
154 {
155  if (StringOp::startsWith(str, "::")) str.remove_prefix(2); // drop leading ::
156  assert(!commandCompleters.contains(str));
157  commandCompleters.emplace_noDuplicateCheck(str, &completer);
158 }
159 
161  CommandCompleter& completer, string_view str)
162 {
163  if (StringOp::startsWith(str, "::")) str.remove_prefix(2); // drop leading ::
164  assert(commandCompleters.contains(str));
165  assert(commandCompleters[str] == &completer); (void)completer;
166  commandCompleters.erase(str);
167 }
168 
170 {
172  interpreter.registerSetting(setting);
173 }
174 
176 {
177  interpreter.unregisterSetting(setting);
179 }
180 
181 static vector<string> split(string_view str, const char delimiter)
182 {
183  vector<string> tokens;
184 
185  enum ParseState {Alpha, BackSlash, Quote};
186  ParseState state = Alpha;
187 
188  for (auto chr : str) {
189  switch (state) {
190  case Alpha:
191  if (tokens.empty()) {
192  tokens.emplace_back();
193  }
194  if (chr == delimiter) {
195  // token done, start new token
196  tokens.emplace_back();
197  } else {
198  tokens.back() += chr;
199  if (chr == '\\') {
200  state = BackSlash;
201  } else if (chr == '"') {
202  state = Quote;
203  }
204  }
205  break;
206  case Quote:
207  tokens.back() += chr;
208  if (chr == '"') {
209  state = Alpha;
210  }
211  break;
212  case BackSlash:
213  tokens.back() += chr;
214  state = Alpha;
215  break;
216  }
217  }
218  return tokens;
219 }
220 
221 static string removeEscaping(const string& str)
222 {
223  enum ParseState {Alpha, BackSlash, Quote};
224  ParseState state = Alpha;
225 
226  string result;
227  for (auto chr : str) {
228  switch (state) {
229  case Alpha:
230  if (chr == '\\') {
231  state = BackSlash;
232  } else if (chr == '"') {
233  state = Quote;
234  } else {
235  result += chr;
236  }
237  break;
238  case Quote:
239  if (chr == '"') {
240  state = Alpha;
241  } else {
242  result += chr;
243  }
244  break;
245  case BackSlash:
246  result += chr;
247  state = Alpha;
248  break;
249  }
250  }
251  return result;
252 }
253 
254 static vector<string> removeEscaping(const vector<string>& input, bool keepLastIfEmpty)
255 {
256  vector<string> result;
257  for (const auto& s : input) {
258  if (!s.empty()) {
259  result.push_back(removeEscaping(s));
260  }
261  }
262  if (keepLastIfEmpty && (input.empty() || input.back().empty())) {
263  result.emplace_back();
264  }
265  return result;
266 }
267 
268 static string escapeChars(const string& str, string_view chars)
269 {
270  string result;
271  for (auto chr : str) {
272  if (chars.find(chr) != string::npos) {
273  result += '\\';
274  }
275  result += chr;
276 
277  }
278  return result;
279 }
280 
281 static string addEscaping(const string& str, bool quote, bool finished)
282 {
283  if (str.empty() && finished) {
284  quote = true;
285  }
286  string result = escapeChars(str, "$[]");
287  if (quote) {
288  result.insert(result.begin(), '"');
289  if (finished) {
290  result += '"';
291  }
292  } else {
293  result = escapeChars(result, " ");
294  }
295  return result;
296 }
297 
299 {
300  return interpreter.isComplete(command);
301 }
302 
304  zstring_view command, CliConnection* connection_)
305 {
306  ScopedAssign sa(connection, connection_);
307  return interpreter.execute(command);
308 }
309 
310 void GlobalCommandController::source(const string& script)
311 {
312  try {
313  LocalFileReference file(script);
314  interpreter.executeFile(file.getFilename());
315  } catch (CommandException& e) {
317  "While executing ", script, ": ", e.getMessage());
318  }
319 }
320 
321 string GlobalCommandController::tabCompletion(string_view command)
322 {
323  // split on 'active' command (the command that should actually be
324  // completed). Some examples:
325  // if {[debug rea<tab> <-- should complete the 'debug' command
326  // instead of the 'if' command
327  // bind F6 { cycl<tab> <-- should complete 'cycle' instead of 'bind'
328  TclParser parser = interpreter.parse(command);
329  int last = parser.getLast();
330  string_view pre = command.substr(0, last);
331  string_view post = command.substr(last);
332 
333  // split command string in tokens
334  vector<string> originalTokens = split(post, ' ');
335  if (originalTokens.empty()) {
336  originalTokens.emplace_back();
337  }
338 
339  // complete last token
340  auto tokens = removeEscaping(originalTokens, true);
341  auto oldNum = tokens.size();
342  tabCompletion(tokens);
343  auto newNum = tokens.size();
344  bool tokenFinished = oldNum != newNum;
345 
346  // replace last token
347  string& original = originalTokens.back();
348  string& completed = tokens[oldNum - 1];
349  if (!completed.empty()) {
350  bool quote = !original.empty() && (original[0] == '"');
351  original = addEscaping(completed, quote, tokenFinished);
352  }
353  if (tokenFinished) {
354  assert(newNum == (oldNum + 1));
355  assert(tokens.back().empty());
356  originalTokens.emplace_back();
357  }
358 
359  // rebuild command string
360  return strCat(pre, join(originalTokens, ' '));
361 }
362 
363 void GlobalCommandController::tabCompletion(vector<string>& tokens)
364 {
365  if (tokens.empty()) {
366  // nothing typed yet
367  return;
368  }
369  if (tokens.size() == 1) {
370  string_view cmd = tokens[0];
371  string_view leadingNs;
372  // remove leading ::
373  if (StringOp::startsWith(cmd, "::")) {
374  cmd.remove_prefix(2);
375  leadingNs = "::";
376  }
377  // get current (typed) namespace
378  auto p1 = cmd.rfind("::");
379  string_view ns = (p1 == string_view::npos) ? cmd : cmd.substr(0, p1 + 2);
380 
381  // build a list of all command strings
382  TclObject names = interpreter.getCommandNames();
383  vector<string> names2;
384  names2.reserve(names.size());
385  for (string_view n1 : names) {
386  // remove leading ::
387  if (StringOp::startsWith(n1, "::")) n1.remove_prefix(2);
388  // initial namespace part must match
389  if (!StringOp::startsWith(n1, ns)) continue;
390  // the part following the initial namespace
391  string_view n2 = n1.substr(ns.size());
392  // only keep upto the next namespace portion,
393  auto p2 = n2.find("::");
394  auto n3 = (p2 == string_view::npos) ? n1 : n1.substr(0, ns.size() + p2 + 2);
395  // don't care about adding the same string multiple times
396  names2.push_back(strCat(leadingNs, n3));
397  }
398  Completer::completeString(tokens, names2);
399  } else {
400  string_view cmd = tokens.front();
401  if (StringOp::startsWith(cmd, "::")) cmd.remove_prefix(2); // drop leading ::
402 
403  if (auto* v = lookup(commandCompleters, cmd)) {
404  (*v)->tabCompletion(tokens);
405  } else {
406  TclObject command = makeTclList("openmsx::tabcompletion");
407  command.addListElements(tokens);
408  try {
409  TclObject list = command.executeCommand(interpreter);
410  bool sensitive = true;
411  auto begin = list.begin();
412  auto end = list.end();
413  if (begin != end) {
414  auto it2 = end; --it2;
415  auto back = *it2;
416  if (back == "false") {
417  end = it2;
418  sensitive = false;
419  } else if (back == "true") {
420  end = it2;
421  sensitive = true;
422  }
423  }
424  Completer::completeString(tokens, begin, end, sensitive);
425  } catch (CommandException& e) {
426  cliComm.printWarning(
427  "Error while executing tab-completion "
428  "proc: ", e.getMessage());
429  }
430  }
431  }
432 }
433 
434 
435 // Help Command
436 
437 GlobalCommandController::HelpCmd::HelpCmd(GlobalCommandController& controller_)
438  : Command(controller_, "help")
439 {
440 }
441 
442 void GlobalCommandController::HelpCmd::execute(
443  span<const TclObject> tokens, TclObject& result)
444 {
445  auto& controller = OUTER(GlobalCommandController, helpCmd);
446  switch (tokens.size()) {
447  case 1: {
448  string text =
449  "Use 'help [command]' to get help for a specific command\n"
450  "The following commands exist:\n";
451  auto cmds = concat<string_view>(
452  view::keys(controller.commandCompleters),
453  getInterpreter().execute("openmsx::all_command_names_with_help"));
454  cmds.erase(ranges::remove_if(cmds, [](const auto& c) {
455  return c.find("::") != std::string_view::npos; }),
456  cmds.end());
457  ranges::sort(cmds);
458  for (auto& line : formatListInColumns(cmds)) {
459  strAppend(text, line, '\n');
460  }
461  result = text;
462  break;
463  }
464  default: {
465  if (const auto* v = lookup(controller.commandCompleters, tokens[1].getString())) {
466  auto tokens2 = to_vector(view::transform(
467  view::drop(tokens, 1),
468  [](auto& t) { return string(t.getString()); }));
469  result = (*v)->help(tokens2);
470  } else {
471  TclObject command = makeTclList("openmsx::help");
472  command.addListElements(view::drop(tokens, 1));
473  result = command.executeCommand(getInterpreter());
474  }
475  break;
476  }
477  }
478 }
479 
480 string GlobalCommandController::HelpCmd::help(const vector<string>& /*tokens*/) const
481 {
482  return "prints help information for commands\n";
483 }
484 
485 void GlobalCommandController::HelpCmd::tabCompletion(vector<string>& tokens) const
486 {
487  string front = std::move(tokens.front());
488  tokens.erase(begin(tokens));
489  auto& controller = OUTER(GlobalCommandController, helpCmd);
490  controller.tabCompletion(tokens);
491  tokens.insert(begin(tokens), std::move(front));
492 }
493 
494 
495 // TabCompletionCmd Command
496 
497 GlobalCommandController::TabCompletionCmd::TabCompletionCmd(
498  GlobalCommandController& controller_)
499  : Command(controller_, "tabcompletion")
500 {
501 }
502 
503 void GlobalCommandController::TabCompletionCmd::execute(
504  span<const TclObject> tokens, TclObject& result)
505 {
506  checkNumArgs(tokens, 2, "commandstring");
507  // TODO this prints list of possible completions in the console
508  auto& controller = OUTER(GlobalCommandController, tabCompletionCmd);
509  result = controller.tabCompletion(tokens[1].getString());
510 }
511 
512 string GlobalCommandController::TabCompletionCmd::help(const vector<string>& /*tokens*/) const
513 {
514  return "!!! This command will change in the future !!!\n"
515  "Tries to completes the given argument as if it were typed in "
516  "the console. This command is only useful to provide "
517  "tabcompletion to external console interfaces.";
518 }
519 
520 
521 // class UpdateCmd
522 
523 GlobalCommandController::UpdateCmd::UpdateCmd(CommandController& commandController_)
524  : Command(commandController_, "openmsx_update")
525 {
526 }
527 
528 static GlobalCliComm::UpdateType getType(const TclObject& name)
529 {
530  auto updateStr = CliComm::getUpdateStrings();
531  for (auto i : xrange(updateStr.size())) {
532  if (updateStr[i] == name) {
533  return static_cast<CliComm::UpdateType>(i);
534  }
535  }
536  throw CommandException("No such update type: ", name.getString());
537 }
538 
539 CliConnection& GlobalCommandController::UpdateCmd::getConnection()
540 {
541  auto& controller = OUTER(GlobalCommandController, updateCmd);
542  if (auto* c = controller.getConnection()) {
543  return *c;
544  }
545  throw CommandException("This command only makes sense when "
546  "it's used from an external application.");
547 }
548 
549 void GlobalCommandController::UpdateCmd::execute(
550  span<const TclObject> tokens, TclObject& /*result*/)
551 {
552  checkNumArgs(tokens, 3, Prefix{1}, "enable|disable type");
553  if (tokens[1] == "enable") {
554  getConnection().setUpdateEnable(getType(tokens[2]), true);
555  } else if (tokens[1] == "disable") {
556  getConnection().setUpdateEnable(getType(tokens[2]), false);
557  } else {
558  throw SyntaxError();
559  }
560 }
561 
562 string GlobalCommandController::UpdateCmd::help(const vector<string>& /*tokens*/) const
563 {
564  static const string helpText = "Enable or disable update events for external applications. See doc/openmsx-control-xml.txt.";
565  return helpText;
566 }
567 
568 void GlobalCommandController::UpdateCmd::tabCompletion(vector<string>& tokens) const
569 {
570  switch (tokens.size()) {
571  case 2: {
572  static constexpr const char* const ops[] = { "enable", "disable" };
573  completeString(tokens, ops);
574  break;
575  }
576  case 3:
577  completeString(tokens, CliComm::getUpdateStrings());
578  break;
579  }
580 }
581 
582 
583 // Platform info
584 
585 GlobalCommandController::PlatformInfo::PlatformInfo(InfoCommand& openMSXInfoCommand_)
586  : InfoTopic(openMSXInfoCommand_, "platform")
587 {
588 }
589 
590 void GlobalCommandController::PlatformInfo::execute(
591  span<const TclObject> /*tokens*/, TclObject& result) const
592 {
593  result = TARGET_PLATFORM;
594 }
595 
596 string GlobalCommandController::PlatformInfo::help(const vector<string>& /*tokens*/) const
597 {
598  return "Prints openMSX platform.";
599 }
600 
601 // Version info
602 
603 GlobalCommandController::VersionInfo::VersionInfo(InfoCommand& openMSXInfoCommand_)
604  : InfoTopic(openMSXInfoCommand_, "version")
605 {
606 }
607 
608 void GlobalCommandController::VersionInfo::execute(
609  span<const TclObject> /*tokens*/, TclObject& result) const
610 {
611  result = Version::full();
612 }
613 
614 string GlobalCommandController::VersionInfo::help(const vector<string>& /*tokens*/) const
615 {
616  return "Prints openMSX version.";
617 }
618 
619 } // namespace openmsx
openmsx::CommandException
Definition: CommandException.hh:9
openmsx::GlobalCommandController::unregisterCompleter
void unregisterCompleter(CommandCompleter &completer, std::string_view str) override
Definition: GlobalCommandController.cc:160
n3
mat3 n3(vec3(1, 0, 3), vec3(4, 5, 6), vec3(7, 8, 9))
openmsx::GlobalCommandController::unregisterProxyCommand
void unregisterProxyCommand(std::string_view name)
Definition: GlobalCommandController.cc:71
TclParser
Definition: TclParser.hh:12
openmsx::Interpreter::execute
TclObject execute(zstring_view command)
Definition: Interpreter.cc:213
openmsx::GlobalCommandController::getSettingsManager
SettingsManager & getSettingsManager()
Definition: GlobalCommandController.hh:90
openmsx::GlobalCommandController::getInterpreter
Interpreter & getInterpreter() override
Definition: GlobalCommandController.cc:125
StringOp::startsWith
bool startsWith(string_view total, string_view part)
Definition: StringOp.cc:33
openmsx::LocalFileReference
Helper class to use files in APIs other than openmsx::File.
Definition: LocalFileReference.hh:31
openmsx::Interpreter::parse
TclParser parse(std::string_view command)
Definition: Interpreter.cc:453
lookup
const Value * lookup(const hash_map< Key, Value, Hasher, Equal > &map, const Key2 &key)
Definition: hash_map.hh:91
openmsx::Interpreter::registerCommand
void registerCommand(zstring_view name, Command &command)
Definition: Interpreter.cc:152
openmsx::GlobalCommandController::unregisterCommand
void unregisterCommand(Command &command, std::string_view str) override
Definition: GlobalCommandController.cc:140
ScopedAssign
Assign new value to some variable and restore the original value when this object goes out of scope.
Definition: ScopedAssign.hh:8
xrange
constexpr auto xrange(T e)
Definition: xrange.hh:155
ranges::sort
void sort(RandomAccessRange &&range)
Definition: ranges.hh:35
openmsx::SettingsManager::registerSetting
void registerSetting(BaseSetting &setting)
Definition: SettingsManager.cc:34
Setting.hh
openmsx::GlobalCommandController::getCliComm
CliComm & getCliComm() override
Definition: GlobalCommandController.cc:120
TclObject.hh
openmsx::CliComm::UpdateType
UpdateType
Definition: CliComm.hh:20
openmsx::BaseSetting::getBaseName
std::string_view getBaseName() const
Definition: Setting.hh:38
openmsx::GlobalCommandController::~GlobalCommandController
~GlobalCommandController()
openmsx::GlobalCommandControllerBase::~GlobalCommandControllerBase
~GlobalCommandControllerBase()
Definition: GlobalCommandController.cc:51
openmsx::LocalFileReference::getFilename
const std::string & getFilename() const
Returns path to a local uncompressed version of this file.
Definition: LocalFileReference.cc:98
openmsx::Interpreter::getCommandNames
TclObject getCommandNames()
Definition: Interpreter.cc:203
openmsx::Interpreter::isComplete
bool isComplete(zstring_view command) const
Definition: Interpreter.cc:208
zstring_view
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
Definition: zstring_view.hh:21
TclParser::getLast
int getLast() const
Get Start of the last subcommand.
Definition: TclParser.hh:32
openmsx::GlobalCommandController::tabCompletion
std::string tabCompletion(std::string_view command)
Complete the given command.
Definition: GlobalCommandController.cc:321
openmsx::GlobalCommandController::source
void source(const std::string &script)
Executes all defined auto commands.
Definition: GlobalCommandController.cc:310
t
TclObject t
Definition: TclObject_test.cc:264
openmsx::SettingsManager::unregisterSetting
void unregisterSetting(BaseSetting &setting)
Definition: SettingsManager.cc:40
openmsx::Interpreter::unregisterCommand
void unregisterCommand(Command &command)
Definition: Interpreter.cc:160
ranges.hh
end
auto end(const zstring_view &x)
Definition: zstring_view.hh:83
join.hh
GlobalCliComm.hh
openmsx::Interpreter::executeFile
TclObject executeFile(zstring_view filename)
Definition: Interpreter.cc:222
LocalFileReference.hh
strAppend
void strAppend(std::string &result, Ts &&...ts)
Definition: strCat.hh:669
openmsx::Setting
Definition: Setting.hh:127
openmsx::EventDistributor
Definition: EventDistributor.hh:17
openmsx::CliConnection
Definition: CliConnection.hh:20
openmsx::GlobalCommandController::unregisterSetting
void unregisterSetting(Setting &setting) override
Definition: GlobalCommandController.cc:175
openmsx::GlobalCommandController::executeCommand
TclObject executeCommand(zstring_view command, CliConnection *connection=nullptr) override
Execute the given command.
Definition: GlobalCommandController.cc:303
openmsx::Interpreter::unregisterSetting
void unregisterSetting(BaseSetting &variable)
Definition: Interpreter.cc:319
ScopedAssign.hh
openmsx::GlobalCliComm
Definition: GlobalCliComm.hh:16
openmsx::GlobalCommandController::GlobalCommandController
GlobalCommandController(const GlobalCommandController &)=delete
Version.hh
span
Definition: span.hh:126
openmsx::Reactor
Contains the main loop of openMSX.
Definition: Reactor.hh:67
openmsx::GlobalCommandController::registerCommand
void registerCommand(Command &command, zstring_view str) override
(Un)register a command
Definition: GlobalCommandController.cc:130
openmsx::Completer::completeString
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
Definition: Completer.hh:125
Reactor.hh
openmsx::GlobalCommandController::isComplete
bool isComplete(zstring_view command)
Returns true iff the command is complete (all braces, quotes etc.
Definition: GlobalCommandController.cc:298
OUTER
#define OUTER(type, member)
Definition: outer.hh:41
move_pop_back
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
Definition: stl.hh:182
view::drop
auto drop(Range &&range, size_t n)
Definition: view.hh:288
view::transform
auto transform(Range &&range, UnaryOp op)
Definition: view.hh:306
openmsx::CliComm::printWarning
void printWarning(std::string_view message)
Definition: CliComm.cc:10
ProxyCommand.hh
openmsx::CommandCompleter
Definition: Command.hh:20
begin
auto begin(const zstring_view &x)
Definition: zstring_view.hh:82
openmsx::Interpreter::registerSetting
void registerSetting(BaseSetting &variable)
Definition: Interpreter.cc:267
openmsx::GlobalCommandController::registerSetting
void registerSetting(Setting &setting) override
TODO.
Definition: GlobalCommandController.cc:169
openmsx::CliComm::getUpdateStrings
static span< const char *const > getUpdateStrings()
Definition: CliComm.hh:88
view::keys
auto keys(Map &&map)
Definition: view.hh:311
build-info.hh
view.hh
openmsx::GlobalCommandController::registerProxyCommand
void registerProxyCommand(std::string_view name)
Definition: GlobalCommandController.cc:61
outer.hh
span::size
constexpr index_type size() const noexcept
Definition: span.hh:296
StringOp.hh
GlobalCommandController.hh
openmsx::makeTclList
TclObject makeTclList(Args &&... args)
Definition: TclObject.hh:290
openmsx::Command
Definition: Command.hh:41
openmsx::CliComm
Definition: CliComm.hh:11
openmsx::Version::full
static std::string full()
Definition: Version.cc:8
stl.hh
SettingsManager.hh
openmsx::TclObject
Definition: TclObject.hh:24
openmsx::GlobalCommandControllerBase::commandCompleters
hash_map< std::string, CommandCompleter *, XXHasher > commandCompleters
Definition: GlobalCommandController.hh:34
join
detail::Joiner< Collection, Separator > join(Collection &&col, Separator &&sep)
Definition: join.hh:60
ranges::find_if
auto find_if(InputRange &&range, UnaryPredicate pred)
Definition: ranges.hh:113
openmsx::BaseSetting::getBaseNameObj
const TclObject & getBaseNameObj() const
Definition: Setting.hh:36
openmsx::GlobalCommandController::unregisterProxySetting
void unregisterProxySetting(Setting &setting)
Definition: GlobalCommandController.cc:106
CliConnection.hh
ProxySetting.hh
openmsx::MSXException::getMessage
const std::string & getMessage() const &
Definition: MSXException.hh:23
ranges::remove_if
auto remove_if(ForwardRange &&range, UnaryPredicate pred)
Definition: ranges.hh:179
strCat
std::string strCat(Ts &&...ts)
Definition: strCat.hh:591
openmsx::Interpreter
Definition: Interpreter.hh:19
CommandException.hh
openmsx::GlobalCommandController::registerCompleter
void registerCompleter(CommandCompleter &completer, std::string_view str) override
(Un)register a command completer, used to complete build-in Tcl cmds
Definition: GlobalCommandController.cc:152
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
to_vector
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))>>
Definition: stl.hh:316
xrange.hh
openmsx::GlobalCommandController::registerProxySetting
void registerProxySetting(Setting &setting)
Definition: GlobalCommandController.cc:90
openmsx::TclObject::getString
zstring_view getString() const
Definition: TclObject.cc:111