openMSX
SettingsManager.cc
Go to the documentation of this file.
1 #include "SettingsManager.hh"
3 #include "TclObject.hh"
4 #include "Setting.hh"
5 #include "CommandException.hh"
6 #include "XMLElement.hh"
7 #include "KeyRange.hh"
8 #include "outer.hh"
9 #include <cassert>
10 
11 using std::string;
12 using std::vector;
13 
14 namespace openmsx {
15 
16 // SettingsManager implementation:
17 
19  : settingInfo (commandController.getOpenMSXInfoCommand())
20  , setCompleter (commandController)
21  , incrCompleter (commandController, *this, "incr")
22  , unsetCompleter(commandController, *this, "unset")
23 {
24 }
25 
27 {
28  assert(settingsMap.empty());
29 }
30 
32 {
33  assert(settingsMap.find(name) == end(settingsMap));
34  settingsMap[name] = &setting;
35 }
36 
38 {
39  assert(settingsMap.find(name) != end(settingsMap));
40  settingsMap.erase(name);
41 }
42 
44 {
45  auto it = settingsMap.find(name);
46  return (it != end(settingsMap)) ? it->second : nullptr;
47 }
48 
49 // Helper functions for setting commands
50 
51 BaseSetting& SettingsManager::getByName(string_ref cmd, string_ref name) const
52 {
53  if (auto* setting = findSetting(name)) {
54  return *setting;
55  }
56  throw CommandException(cmd + ": " + name + ": no such setting");
57 }
58 
60 {
61  // restore default values
62  for (auto* s : values(settingsMap)) {
63  if (s->needLoadSave()) {
64  s->setValue(s->getRestoreValue());
65  }
66  }
67 
68  // load new values
69  auto* settings = config.findChild("settings");
70  if (!settings) return;
71  for (auto& p : settingsMap) {
72  auto name = p.first();
73  auto& setting = *p.second;
74  if (!setting.needLoadSave()) continue;
75  if (auto* elem = settings->findChildWithAttribute(
76  "setting", "id", name)) {
77  try {
78  setting.setValue(TclObject(elem->getData()));
79  } catch (MSXException&) {
80  // ignore, keep default value
81  }
82  }
83  }
84 }
85 
86 
87 // class SettingInfo
88 
89 SettingsManager::SettingInfo::SettingInfo(InfoCommand& openMSXInfoCommand)
90  : InfoTopic(openMSXInfoCommand, "setting")
91 {
92 }
93 
94 void SettingsManager::SettingInfo::execute(
95  array_ref<TclObject> tokens, TclObject& result) const
96 {
97  auto& manager = OUTER(SettingsManager, settingInfo);
98  auto& settingsMap = manager.settingsMap;
99  switch (tokens.size()) {
100  case 2:
101  for (auto& p : settingsMap) {
102  result.addListElement(p.first());
103  }
104  break;
105  case 3: {
106  const auto& name = tokens[2].getString();
107  auto it = settingsMap.find(name);
108  if (it == end(settingsMap)) {
109  throw CommandException("No such setting: " + name);
110  }
111  it->second->info(result);
112  break;
113  }
114  default:
115  throw CommandException("Too many parameters.");
116  }
117 }
118 
119 string SettingsManager::SettingInfo::help(const vector<string>& /*tokens*/) const
120 {
121  return "openmsx_info setting : "
122  "returns list of all settings\n"
123  "openmsx_info setting <name> : "
124  "returns info on a specific setting\n";
125 }
126 
127 void SettingsManager::SettingInfo::tabCompletion(vector<string>& tokens) const
128 {
129  if (tokens.size() == 3) {
130  // complete setting name
131  auto& manager = OUTER(SettingsManager, settingInfo);
132  completeString(tokens, keys(manager.settingsMap));
133  }
134 }
135 
136 
137 // class SetCompleter
138 
139 SettingsManager::SetCompleter::SetCompleter(
140  CommandController& commandController)
141  : CommandCompleter(commandController, "set")
142 {
143 }
144 
145 string SettingsManager::SetCompleter::help(const vector<string>& tokens) const
146 {
147  if (tokens.size() == 2) {
148  auto& manager = OUTER(SettingsManager, setCompleter);
149  return manager.getByName("set", tokens[1]).getDescription().str();
150  }
151  return "Set or query the value of a openMSX setting or Tcl variable\n"
152  " set <setting> shows current value\n"
153  " set <setting> <value> set a new value\n"
154  "Use 'help set <setting>' to get more info on a specific\n"
155  "openMSX setting.\n";
156 }
157 
158 void SettingsManager::SetCompleter::tabCompletion(vector<string>& tokens) const
159 {
160  auto& manager = OUTER(SettingsManager, setCompleter);
161  switch (tokens.size()) {
162  case 2:
163  // complete setting name
164  completeString(tokens, keys(manager.settingsMap), false); // case insensitive
165  break;
166  case 3: {
167  // complete setting value
168  auto it = manager.settingsMap.find(tokens[1]);
169  if (it != end(manager.settingsMap)) {
170  it->second->tabCompletion(tokens);
171  }
172  break;
173  }
174  }
175 }
176 
177 
178 // class SettingCompleter
179 
180 SettingsManager::SettingCompleter::SettingCompleter(
181  CommandController& commandController, SettingsManager& manager_,
182  const string& name)
183  : CommandCompleter(commandController, name)
184  , manager(manager_)
185 {
186 }
187 
188 string SettingsManager::SettingCompleter::help(const vector<string>& /*tokens*/) const
189 {
190  return ""; // TODO
191 }
192 
193 void SettingsManager::SettingCompleter::tabCompletion(vector<string>& tokens) const
194 {
195  if (tokens.size() == 2) {
196  // complete setting name
197  completeString(tokens, keys(manager.settingsMap));
198  }
199 }
200 
201 } // namespace openmsx
detail::KeyRange< MAP, 1 > values(const MAP &map)
Definition: KeyRange.hh:101
string_ref::const_iterator end(const string_ref &x)
Definition: string_ref.hh:167
size_type size() const
Definition: array_ref.hh:61
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)
void unregisterSetting(BaseSetting &setting, string_ref name)
void registerSetting(BaseSetting &setting, string_ref name)
const XMLElement * findChild(string_ref name) const
Definition: XMLElement.cc:117
This class implements a subset of the proposal for std::array_ref (proposed for the next c++ standard...
Definition: array_ref.hh:19
BaseSetting * findSetting(string_ref name) const
Find the setting with given name.
SettingsManager(GlobalCommandController &commandController)
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
#define OUTER(type, member)
Definition: outer.hh:38
detail::KeyRange< MAP, 0 > keys(const MAP &map)
Definition: KeyRange.hh:96