openMSX
InfoCommand.cc
Go to the documentation of this file.
1 #include "InfoCommand.hh"
2 #include "TclObject.hh"
3 #include "CommandException.hh"
4 #include "KeyRange.hh"
5 #include "unreachable.hh"
6 #include <iostream>
7 #include <cassert>
8 
9 using std::string;
10 using std::vector;
11 
12 namespace openmsx {
13 
14 InfoCommand::InfoCommand(CommandController& commandController, const string& name)
15  : Command(commandController, name)
16 {
17 }
18 
20 {
21  assert(infoTopics.empty());
22 }
23 
25 {
26 #ifndef NDEBUG
27  if (infoTopics.contains(topic.getName())) {
28  std::cerr << "INTERNAL ERROR: already have an info topic with "
29  "name " << topic.getName() << std::endl;
31  }
32 #endif
33  infoTopics.insert_noDuplicateCheck(&topic);
34 }
35 
37 {
38  (void)topic;
39  if (!infoTopics.contains(topic.getName())) {
40  std::cerr << "INTERNAL ERROR: can't unregister topic with name "
41  << topic.getName() << ", not found!" << std::endl;
43  }
44  infoTopics.erase(topic.getName());
45 }
46 
47 // Command
48 
49 void InfoCommand::execute(array_ref<TclObject> tokens,
50  TclObject& result)
51 {
52  switch (tokens.size()) {
53  case 1:
54  // list topics
55  for (auto* t : infoTopics) {
56  result.addListElement(t->getName());
57  }
58  break;
59  default:
60  // show info about topic
61  assert(tokens.size() >= 2);
62  const auto& topic = tokens[1].getString();
63  auto it = infoTopics.find(topic);
64  if (it == end(infoTopics)) {
65  throw CommandException("No info on: " + topic);
66  }
67  (*it)->execute(tokens, result);
68  break;
69  }
70 }
71 
72 string InfoCommand::help(const vector<string>& tokens) const
73 {
74  string result;
75  switch (tokens.size()) {
76  case 1:
77  // show help on info cmd
78  result = "Show info on a certain topic\n"
79  " info [topic] [...]\n";
80  break;
81  default:
82  // show help on a certain topic
83  assert(tokens.size() >= 2);
84  auto it = infoTopics.find(tokens[1]);
85  if (it == end(infoTopics)) {
86  throw CommandException("No info on: " + tokens[1]);
87  }
88  result = (*it)->help(tokens);
89  break;
90  }
91  return result;
92 }
93 
94 void InfoCommand::tabCompletion(vector<string>& tokens) const
95 {
96  switch (tokens.size()) {
97  case 2: {
98  // complete topic
99  vector<string_ref> topics;
100  for (auto* t : infoTopics) {
101  topics.push_back(t->getName());
102  }
103  completeString(tokens, topics);
104  break;
105  }
106  default:
107  // show help on a certain topic
108  assert(tokens.size() >= 3);
109  auto it = infoTopics.find(tokens[1]);
110  if (it != end(infoTopics)) {
111  (*it)->tabCompletion(tokens);
112  }
113  break;
114  }
115 }
116 
117 } // namespace openmsx
void registerTopic(InfoTopic &topic)
Definition: InfoCommand.cc:24
string_ref::const_iterator end(const string_ref &x)
Definition: string_ref.hh:167
size_type size() const
Definition: array_ref.hh:61
const std::string & getName() const
Definition: Completer.hh:17
InfoCommand(CommandController &commandController, const std::string &name)
Definition: InfoCommand.cc:14
This class implements a subset of the proposal for std::array_ref (proposed for the next c++ standard...
Definition: array_ref.hh:19
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
Definition: Completer.hh:106
void addListElement(string_ref element)
Definition: TclObject.cc:69
void unregisterTopic(InfoTopic &topic)
Definition: InfoCommand.cc:36
#define UNREACHABLE
Definition: unreachable.hh:35