openMSX
SettingsManager.cc
Go to the documentation of this file.
1#include "SettingsManager.hh"
2#include "SettingsConfig.hh"
4#include "MSXException.hh"
5#include "TclObject.hh"
6#include "CommandException.hh"
7#include "outer.hh"
8#include "view.hh"
9#include "vla.hh"
10#include <cassert>
11
12using std::string;
13
14namespace 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(settings.empty());
29}
30
32{
33 assert(!settings.contains(setting.getFullNameObj()));
34 settings.emplace_noDuplicateCheck(&setting);
35}
36
38{
39 const auto& name = setting.getFullNameObj();
40 assert(settings.contains(name));
41 settings.erase(name);
42}
43
44BaseSetting* SettingsManager::findSetting(std::string_view name) const
45{
46 if (auto it = settings.find(name); it != end(settings)) {
47 return *it;
48 }
49 if (name.starts_with("::")) {
50 // try without leading ::
51 if (auto it = settings.find(name.substr(2)); it != end(settings)) {
52 return *it;
53 }
54 } else {
55 // try adding ::
56 if (auto it = settings.find(tmpStrCat("::", name)); it != end(settings)) {
57 return *it;
58 }
59 }
60 return nullptr;
61}
62
63BaseSetting* SettingsManager::findSetting(std::string_view prefix, std::string_view baseName) const
64{
65 auto size = prefix.size() + baseName.size();
66 VLA(char, fullname, size);
67 ranges::copy(prefix, fullname);
68 ranges::copy(baseName, fullname.subspan(prefix.size()));
69 return findSetting(std::string_view(fullname.data(), size)); // TODO simplify in c++23
70}
71
72// Helper functions for setting commands
73
74BaseSetting& SettingsManager::getByName(std::string_view cmd, std::string_view name) const
75{
76 if (auto* setting = findSetting(name)) {
77 return *setting;
78 }
79 throw CommandException(cmd, ": ", name, ": no such setting");
80}
81
82std::vector<string> SettingsManager::getTabSettingNames() const
83{
84 std::vector<string> result;
85 result.reserve(settings.size() * 2);
86 for (auto* s : settings) {
87 std::string_view name = s->getFullName();
88 result.emplace_back(name);
89 if (name.starts_with("::")) {
90 result.emplace_back(name.substr(2));
91 } else {
92 result.push_back(strCat("::", name));
93 }
94 }
95 return result;
96}
97
99{
100 // restore default values or load new values
101 for (auto* s : settings) {
102 if (!s->needLoadSave()) continue;
103
104 s->setValue(s->getRestoreValue());
105
106 if (const auto* savedValue = config.getValueForSetting(s->getFullName())) {
107 try {
108 s->setValue(TclObject(*savedValue));
109 } catch (MSXException&) {
110 // ignore, keep default value
111 }
112 }
113 }
114}
115
116
117// class SettingInfo
118
119SettingsManager::SettingInfo::SettingInfo(InfoCommand& openMSXInfoCommand)
120 : InfoTopic(openMSXInfoCommand, "setting")
121{
122}
123
124void SettingsManager::SettingInfo::execute(
125 std::span<const TclObject> tokens, TclObject& result) const
126{
127 auto& manager = OUTER(SettingsManager, settingInfo);
128 switch (tokens.size()) {
129 case 2:
130 result.addListElements(view::transform(
131 manager.settings,
132 [](auto* p) { return p->getFullNameObj(); }));
133 break;
134 case 3: {
135 const auto& settingName = tokens[2].getString();
136 auto* setting = manager.findSetting(settingName);
137 if (!setting) {
138 throw CommandException("No such setting: ", settingName);
139 }
140 try {
141 setting->info(result);
142 } catch (MSXException& e) {
143 throw CommandException(e.getMessage());
144
145 }
146 break;
147 }
148 default:
149 throw CommandException("Too many parameters.");
150 }
151}
152
153string SettingsManager::SettingInfo::help(std::span<const TclObject> /*tokens*/) const
154{
155 return "openmsx_info setting : "
156 "returns list of all settings\n"
157 "openmsx_info setting <name> : "
158 "returns info on a specific setting\n";
159}
160
161void SettingsManager::SettingInfo::tabCompletion(std::vector<string>& tokens) const
162{
163 if (tokens.size() == 3) {
164 // complete setting name
165 auto& manager = OUTER(SettingsManager, settingInfo);
166 completeString(tokens, manager.getTabSettingNames());
167 }
168}
169
170
171// class SetCompleter
172
173SettingsManager::SetCompleter::SetCompleter(
174 CommandController& commandController_)
175 : CommandCompleter(commandController_, "set")
176{
177}
178
179string SettingsManager::SetCompleter::help(std::span<const TclObject> tokens) const
180{
181 if (tokens.size() == 2) {
182 auto& manager = OUTER(SettingsManager, setCompleter);
183 return string(manager.getByName("set", tokens[1].getString()).getDescription());
184 }
185 return "Set or query the value of a openMSX setting or Tcl variable\n"
186 " set <setting> shows current value\n"
187 " set <setting> <value> set a new value\n"
188 "Use 'help set <setting>' to get more info on a specific\n"
189 "openMSX setting.\n";
190}
191
192void SettingsManager::SetCompleter::tabCompletion(std::vector<string>& tokens) const
193{
194 auto& manager = OUTER(SettingsManager, setCompleter);
195 switch (tokens.size()) {
196 case 2: {
197 // complete setting name
198 completeString(tokens, manager.getTabSettingNames(), false); // case insensitive
199 break;
200 }
201 case 3:
202 // complete setting value
203 if (auto* setting = manager.findSetting(tokens[1])) {
204 setting->tabCompletion(tokens);
205 }
206 break;
207 }
208}
209
210
211// class SettingCompleter
212
213SettingsManager::SettingCompleter::SettingCompleter(
214 CommandController& commandController_, SettingsManager& manager_,
215 const string& name_)
216 : CommandCompleter(commandController_, name_)
217 , manager(manager_)
218{
219}
220
221string SettingsManager::SettingCompleter::help(std::span<const TclObject> /*tokens*/) const
222{
223 return {}; // TODO
224}
225
226void SettingsManager::SettingCompleter::tabCompletion(std::vector<string>& tokens) const
227{
228 if (tokens.size() == 2) {
229 // complete setting name
230 completeString(tokens, manager.getTabSettingNames());
231 }
232}
233
234} // namespace openmsx
BaseSetting * setting
Definition: Interpreter.cc:28
void info(TclObject &result) const
For SettingInfo.
Definition: Setting.cc:27
virtual void tabCompletion(std::vector< std::string > &tokens) const =0
Complete a partly typed value.
const std::string * getValueForSetting(std::string_view setting) const
BaseSetting * findSetting(std::string_view name) const
Find the setting with given name.
SettingsManager(const SettingsManager &)=delete
void unregisterSetting(BaseSetting &setting)
void loadSettings(const SettingsConfig &config)
void registerSetting(BaseSetting &setting)
constexpr double e
Definition: Math.hh:21
This file implemented 3 utility functions:
Definition: Autofire.cc:9
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:232
size_t size(std::string_view utf8)
constexpr auto transform(Range &&range, UnaryOp op)
Definition: view.hh:458
#define OUTER(type, member)
Definition: outer.hh:41
TemporaryString tmpStrCat(Ts &&... ts)
Definition: strCat.hh:610
std::string strCat(Ts &&...ts)
Definition: strCat.hh:542
#define VLA(TYPE, NAME, LENGTH)
Definition: vla.hh:12
constexpr auto end(const zstring_view &x)