openMSX
SettingsManager.cc
Go to the documentation of this file.
1 #include "SettingsManager.hh"
3 #include "Command.hh"
4 #include "InfoTopic.hh"
5 #include "TclObject.hh"
6 #include "Setting.hh"
7 #include "CommandException.hh"
8 #include "XMLElement.hh"
9 #include "KeyRange.hh"
10 #include "memory.hh"
11 #include <cassert>
12 
13 using std::string;
14 using std::vector;
15 
16 namespace openmsx {
17 
18 // SettingsManager implementation:
19 
20 class SettingInfo : public InfoTopic
21 {
22 public:
23  SettingInfo(InfoCommand& openMSXInfoCommand, SettingsManager& manager);
24  virtual void execute(const vector<TclObject>& tokens,
25  TclObject& result) const;
26  virtual string help(const vector<string>& tokens) const;
27  virtual void tabCompletion(vector<string>& tokens) const;
28 private:
29  SettingsManager& manager;
30 };
31 
33 {
34 public:
35  SetCompleter(CommandController& commandController,
36  SettingsManager& manager);
37  virtual string help(const vector<string>& tokens) const;
38  virtual void tabCompletion(vector<string>& tokens) const;
39 private:
40  SettingsManager& manager;
41 };
42 
44 {
45 public:
46  SettingCompleter(CommandController& commandController,
47  SettingsManager& manager,
48  const string& name);
49  virtual string help(const vector<string>& tokens) const;
50  virtual void tabCompletion(vector<string>& tokens) const;
51 private:
52  SettingsManager& manager;
53 };
54 
55 
57  : settingInfo(make_unique<SettingInfo>(
58  commandController.getOpenMSXInfoCommand(), *this))
59  , setCompleter(make_unique<SetCompleter>(
60  commandController, *this))
61  , incrCompleter(make_unique<SettingCompleter>(
62  commandController, *this, "incr"))
63  , unsetCompleter(make_unique<SettingCompleter>(
64  commandController, *this, "unset"))
65 {
66 }
67 
69 {
70  assert(settingsMap.empty());
71 }
72 
74 {
75  assert(settingsMap.find(name) == settingsMap.end());
76  settingsMap[name] = &setting;
77 }
78 
80 {
81  assert(settingsMap.find(name) != settingsMap.end());
82  settingsMap.erase(name);
83 }
84 
86 {
87  auto it = settingsMap.find(name);
88  return (it != settingsMap.end()) ? it->second : nullptr;
89 }
90 
91 // Helper functions for setting commands
92 
93 BaseSetting& SettingsManager::getByName(string_ref cmd, string_ref name) const
94 {
95  if (auto* setting = findSetting(name)) {
96  return *setting;
97  }
98  throw CommandException(cmd + ": " + name + ": no such setting");
99 }
100 
102 {
103  // restore default values
104  for (auto& p : settingsMap) {
105  auto& setting = *p.second;
106  if (setting.needLoadSave()) {
107  setting.setString(setting.getRestoreValue());
108  }
109  }
110 
111  // load new values
112  auto* settings = config.findChild("settings");
113  if (!settings) return;
114  for (auto& p : settingsMap) {
115  auto name = p.first();
116  auto& setting = *p.second;
117  if (!setting.needLoadSave()) continue;
118  if (auto* elem = settings->findChildWithAttribute(
119  "setting", "id", name)) {
120  try {
121  setting.setString(elem->getData());
122  } catch (MSXException&) {
123  // ignore, keep default value
124  }
125  }
126  }
127 }
128 
129 
130 // class SettingInfo
131 
133  SettingsManager& manager_)
134  : InfoTopic(openMSXInfoCommand, "setting")
135  , manager(manager_)
136 {
137 }
138 
140  const vector<TclObject>& tokens, TclObject& result) const
141 {
142  auto& settingsMap = manager.settingsMap;
143  switch (tokens.size()) {
144  case 2:
145  for (auto& p : settingsMap) {
146  result.addListElement(p.first());
147  }
148  break;
149  case 3: {
150  const auto& name = tokens[2].getString();
151  auto it = settingsMap.find(name);
152  if (it == settingsMap.end()) {
153  throw CommandException("No such setting: " + name);
154  }
155  it->second->info(result);
156  break;
157  }
158  default:
159  throw CommandException("Too many parameters.");
160  }
161 }
162 
163 string SettingInfo::help(const vector<string>& /*tokens*/) const
164 {
165  return "openmsx_info setting : "
166  "returns list of all settings\n"
167  "openmsx_info setting <name> : "
168  "returns info on a specific setting\n";
169 }
170 
171 void SettingInfo::tabCompletion(vector<string>& tokens) const
172 {
173  if (tokens.size() == 3) {
174  // complete setting name
175  completeString(tokens, keys(manager.settingsMap));
176  }
177 }
178 
179 
180 // class SetCompleter
181 
183  SettingsManager& manager_)
184  : CommandCompleter(commandController, "set"), manager(manager_)
185 {
186 }
187 
188 string SetCompleter::help(const vector<string>& tokens) const
189 {
190  if (tokens.size() == 2) {
191  return manager.getByName("set", tokens[1]).getDescription();
192  }
193  return "Set or query the value of a openMSX setting or Tcl variable\n"
194  " set <setting> shows current value\n"
195  " set <setting> <value> set a new value\n"
196  "Use 'help set <setting>' to get more info on a specific\n"
197  "openMSX setting.\n";
198 }
199 
200 void SetCompleter::tabCompletion(vector<string>& tokens) const
201 {
202  switch (tokens.size()) {
203  case 2:
204  // complete setting name
205  completeString(tokens, keys(manager.settingsMap), false); // case insensitive
206  break;
207  case 3: {
208  // complete setting value
209  auto it = manager.settingsMap.find(tokens[1]);
210  if (it != manager.settingsMap.end()) {
211  it->second->tabCompletion(tokens);
212  }
213  break;
214  }
215  }
216 }
217 
218 
219 // class SettingCompleter
220 
222  CommandController& commandController, SettingsManager& manager_,
223  const string& name)
224  : CommandCompleter(commandController, name)
225  , manager(manager_)
226 {
227 }
228 
229 string SettingCompleter::help(const vector<string>& /*tokens*/) const
230 {
231  return ""; // TODO
232 }
233 
234 void SettingCompleter::tabCompletion(vector<string>& tokens) const
235 {
236  if (tokens.size() == 2) {
237  // complete setting name
238  completeString(tokens, keys(manager.settingsMap));
239  }
240 }
241 
242 } // namespace openmsx
virtual std::string getDescription() const =0
pure virtual methods ///
virtual string help(const vector< string > &tokens) const
Print help for this topic.
This class implements a subset of the proposal for std::string_ref (proposed for the next c++ standar...
Definition: string_ref.hh:18
void loadSettings(const XMLElement &config)
KeyRange< MAP > keys(const MAP &map)
Definition: KeyRange.hh:56
void unregisterSetting(BaseSetting &setting, string_ref name)
void registerSetting(BaseSetting &setting, string_ref name)
const XMLElement * findChild(string_ref name) const
Definition: XMLElement.cc:135
virtual string help(const vector< string > &tokens) const
Print help for this command.
virtual string help(const vector< string > &tokens) const
Print help for this command.
Manages all settings.
virtual void tabCompletion(vector< string > &tokens) const
Attempt tab completion for this topic.
SettingCompleter(CommandController &commandController, SettingsManager &manager, const string &name)
BaseSetting * findSetting(string_ref name) const
Find the setting with given name.
SettingsManager(GlobalCommandController &commandController)
SetCompleter(CommandController &commandController, SettingsManager &manager)
virtual void tabCompletion(vector< string > &tokens) const
Attempt tab completion for this command.
virtual void tabCompletion(vector< string > &tokens) const
Attempt tab completion for this command.
virtual void execute(const vector< TclObject > &tokens, TclObject &result) const
Show info on this topic.
void addListElement(string_ref element)
Definition: TclObject.cc:154
static void completeString(std::vector< std::string > &tokens, const RANGE &possibleValues, bool caseSensitive=true)
Definition: Completer.hh:88
SettingInfo(InfoCommand &openMSXInfoCommand, SettingsManager &manager)
std::unique_ptr< T > make_unique()
Definition: memory.hh:27