openMSX
InfoCommand.cc
Go to the documentation of this file.
1 #include "InfoCommand.hh"
2 #include "TclObject.hh"
3 #include "CommandException.hh"
4 #include "unreachable.hh"
5 #include "view.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() << '\n';
31  }
32 #endif
33  infoTopics.insert_noDuplicateCheck(&topic);
34 }
35 
37 {
38  if (!infoTopics.contains(topic.getName())) {
39  std::cerr << "INTERNAL ERROR: can't unregister topic with name "
40  << topic.getName() << ", not found!\n";
42  }
43  infoTopics.erase(topic.getName());
44 }
45 
46 // Command
47 
48 void InfoCommand::execute(span<const TclObject> tokens,
49  TclObject& result)
50 {
51  switch (tokens.size()) {
52  case 1:
53  // list topics
55  infoTopics, [](auto* t) { return t->getName(); }));
56  break;
57  default:
58  // show info about topic
59  assert(tokens.size() >= 2);
60  const auto& topic = tokens[1].getString();
61  auto it = infoTopics.find(topic);
62  if (it == end(infoTopics)) {
63  throw CommandException("No info on: ", topic);
64  }
65  (*it)->execute(tokens, result);
66  break;
67  }
68 }
69 
70 string InfoCommand::help(const vector<string>& tokens) const
71 {
72  string result;
73  switch (tokens.size()) {
74  case 1:
75  // show help on info cmd
76  result = "Show info on a certain topic\n"
77  " info [topic] [...]\n";
78  break;
79  default:
80  // show help on a certain topic
81  assert(tokens.size() >= 2);
82  auto it = infoTopics.find(tokens[1]);
83  if (it == end(infoTopics)) {
84  throw CommandException("No info on: ", tokens[1]);
85  }
86  result = (*it)->help(tokens);
87  break;
88  }
89  return result;
90 }
91 
92 void InfoCommand::tabCompletion(vector<string>& tokens) const
93 {
94  switch (tokens.size()) {
95  case 2: {
96  // complete topic
97  auto topics = to_vector(view::transform(
98  infoTopics, [](auto* t) { return t->getName(); }));
99  completeString(tokens, topics);
100  break;
101  }
102  default:
103  // show help on a certain topic
104  assert(tokens.size() >= 3);
105  auto it = infoTopics.find(tokens[1]);
106  if (it != end(infoTopics)) {
107  (*it)->tabCompletion(tokens);
108  }
109  break;
110  }
111 }
112 
113 } // namespace openmsx
void registerTopic(InfoTopic &topic)
Definition: InfoCommand.cc:24
auto transform(Range &&range, UnaryOp op)
Definition: view.hh:306
InfoCommand(CommandController &commandController, const std::string &name)
Definition: InfoCommand.cc:14
Definition: span.hh:34
const std::string & getName() const
Definition: Completer.hh:20
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:125
void addListElements(ITER first, ITER last)
Definition: TclObject.hh:122
TclObject t
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))>>
Definition: stl.hh:311
void unregisterTopic(InfoTopic &topic)
Definition: InfoCommand.cc:36
#define UNREACHABLE
Definition: unreachable.hh:38