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 if (const auto* savedValue = config.getValueForSetting(s->getBaseName())) {
105 try {
106 s->setValue(TclObject(*savedValue));
107 } catch (MSXException&) {
108 // ignore error, instead set default value
109 s->setValue(s->getDefaultValue());
110 }
111 } else {
112 s->setValue(s->getDefaultValue());
113 }
114 }
115}
116
117
118// class SettingInfo
119
120SettingsManager::SettingInfo::SettingInfo(InfoCommand& openMSXInfoCommand)
121 : InfoTopic(openMSXInfoCommand, "setting")
122{
123}
124
125void SettingsManager::SettingInfo::execute(
126 std::span<const TclObject> tokens, TclObject& result) const
127{
128 auto& manager = OUTER(SettingsManager, settingInfo);
129 switch (tokens.size()) {
130 case 2:
131 result.addListElements(view::transform(
132 manager.settings,
133 [](auto* p) { return p->getFullNameObj(); }));
134 break;
135 case 3: {
136 const auto& settingName = tokens[2].getString();
137 auto* setting = manager.findSetting(settingName);
138 if (!setting) {
139 throw CommandException("No such setting: ", settingName);
140 }
141 try {
142 setting->info(result);
143 } catch (MSXException& e) {
144 throw CommandException(e.getMessage());
145
146 }
147 break;
148 }
149 default:
150 throw CommandException("Too many parameters.");
151 }
152}
153
154string SettingsManager::SettingInfo::help(std::span<const TclObject> /*tokens*/) const
155{
156 return "openmsx_info setting : "
157 "returns list of all settings\n"
158 "openmsx_info setting <name> : "
159 "returns info on a specific setting\n";
160}
161
162void SettingsManager::SettingInfo::tabCompletion(std::vector<string>& tokens) const
163{
164 if (tokens.size() == 3) {
165 // complete setting name
166 auto& manager = OUTER(SettingsManager, settingInfo);
167 completeString(tokens, manager.getTabSettingNames());
168 }
169}
170
171
172// class SetCompleter
173
174SettingsManager::SetCompleter::SetCompleter(
175 CommandController& commandController_)
176 : CommandCompleter(commandController_, "set")
177{
178}
179
180string SettingsManager::SetCompleter::help(std::span<const TclObject> tokens) const
181{
182 if (tokens.size() == 2) {
183 auto& manager = OUTER(SettingsManager, setCompleter);
184 return string(manager.getByName("set", tokens[1].getString()).getDescription());
185 }
186 return "Set or query the value of a openMSX setting or Tcl variable\n"
187 " set <setting> shows current value\n"
188 " set <setting> <value> set a new value\n"
189 "Use 'help set <setting>' to get more info on a specific\n"
190 "openMSX setting.\n";
191}
192
193void SettingsManager::SetCompleter::tabCompletion(std::vector<string>& tokens) const
194{
195 auto& manager = OUTER(SettingsManager, setCompleter);
196 switch (tokens.size()) {
197 case 2: {
198 // complete setting name
199 completeString(tokens, manager.getTabSettingNames(), false); // case insensitive
200 break;
201 }
202 case 3:
203 // complete setting value
204 if (auto* setting = manager.findSetting(tokens[1])) {
205 setting->tabCompletion(tokens);
206 }
207 break;
208 }
209}
210
211
212// class SettingCompleter
213
214SettingsManager::SettingCompleter::SettingCompleter(
215 CommandController& commandController_, SettingsManager& manager_,
216 const string& name_)
217 : CommandCompleter(commandController_, name_)
218 , manager(manager_)
219{
220}
221
222string SettingsManager::SettingCompleter::help(std::span<const TclObject> /*tokens*/) const
223{
224 return {}; // TODO
225}
226
227void SettingsManager::SettingCompleter::tabCompletion(std::vector<string>& tokens) const
228{
229 if (tokens.size() == 2) {
230 // complete setting name
231 completeString(tokens, manager.getTabSettingNames());
232 }
233}
234
235} // namespace openmsx
BaseSetting * setting
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:250
constexpr auto transform(Range &&range, UnaryOp op)
Definition view.hh:520
#define OUTER(type, member)
Definition outer.hh:41
std::string strCat()
Definition strCat.hh:703
TemporaryString tmpStrCat(Ts &&... ts)
Definition strCat.hh:742
#define VLA(TYPE, NAME, LENGTH)
Definition vla.hh:12
constexpr auto end(const zstring_view &x)