openMSX
SettingsManager.cc
Go to the documentation of this file.
1#include "SettingsManager.hh"
2
3#include "CommandException.hh"
5#include "MSXException.hh"
6#include "SettingsConfig.hh"
7#include "TclObject.hh"
8
9#include "outer.hh"
10#include "view.hh"
11
12#include <cassert>
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 return findSetting(tmpStrCat(prefix, baseName));
66}
67
68// Helper functions for setting commands
69
70BaseSetting& SettingsManager::getByName(std::string_view cmd, std::string_view name) const
71{
72 if (auto* setting = findSetting(name)) {
73 return *setting;
74 }
75 throw CommandException(cmd, ": ", name, ": no such setting");
76}
77
78std::vector<std::string> SettingsManager::getTabSettingNames() const
79{
80 std::vector<std::string> result;
81 result.reserve(size_t(settings.size()) * 2);
82 for (const auto* s : settings) {
83 std::string_view name = s->getFullName();
84 result.emplace_back(name);
85 if (name.starts_with("::")) {
86 result.emplace_back(name.substr(2));
87 } else {
88 result.push_back(strCat("::", name));
89 }
90 }
91 return result;
92}
93
95{
96 // restore default values or load new values
97 for (auto* s : settings) {
98 if (!s->needLoadSave()) continue;
99
100 if (const auto* savedValue = config.getValueForSetting(s->getBaseName())) {
101 try {
102 s->setValue(TclObject(*savedValue));
103 } catch (MSXException&) {
104 // ignore error, instead set default value
105 s->setValue(s->getDefaultValue());
106 }
107 } else {
108 s->setValue(s->getDefaultValue());
109 }
110 }
111}
112
113
114// class SettingInfo
115
116SettingsManager::SettingInfo::SettingInfo(InfoCommand& openMSXInfoCommand)
117 : InfoTopic(openMSXInfoCommand, "setting")
118{
119}
120
121void SettingsManager::SettingInfo::execute(
122 std::span<const TclObject> tokens, TclObject& result) const
123{
124 auto& manager = OUTER(SettingsManager, settingInfo);
125 switch (tokens.size()) {
126 case 2:
127 result.addListElements(view::transform(
128 manager.settings,
129 [](auto* p) { return p->getFullNameObj(); }));
130 break;
131 case 3: {
132 const auto& settingName = tokens[2].getString();
133 const auto* setting = manager.findSetting(settingName);
134 if (!setting) {
135 throw CommandException("No such setting: ", settingName);
136 }
137 try {
138 setting->info(result);
139 } catch (MSXException& e) {
140 throw CommandException(e.getMessage());
141
142 }
143 break;
144 }
145 default:
146 throw CommandException("Too many parameters.");
147 }
148}
149
150std::string SettingsManager::SettingInfo::help(std::span<const TclObject> /*tokens*/) const
151{
152 return "openmsx_info setting : "
153 "returns list of all settings\n"
154 "openmsx_info setting <name> : "
155 "returns info on a specific setting\n";
156}
157
158void SettingsManager::SettingInfo::tabCompletion(std::vector<std::string>& tokens) const
159{
160 if (tokens.size() == 3) {
161 // complete setting name
162 const auto& manager = OUTER(SettingsManager, settingInfo);
163 completeString(tokens, manager.getTabSettingNames());
164 }
165}
166
167
168// class SetCompleter
169
170SettingsManager::SetCompleter::SetCompleter(
171 CommandController& commandController_)
172 : CommandCompleter(commandController_, "set")
173{
174}
175
176std::string SettingsManager::SetCompleter::help(std::span<const TclObject> tokens) const
177{
178 if (tokens.size() == 2) {
179 const auto& manager = OUTER(SettingsManager, setCompleter);
180 return std::string(manager.getByName("set", tokens[1].getString()).getDescription());
181 }
182 return "Set or query the value of a openMSX setting or Tcl variable\n"
183 " set <setting> shows current value\n"
184 " set <setting> <value> set a new value\n"
185 "Use 'help set <setting>' to get more info on a specific\n"
186 "openMSX setting.\n";
187}
188
189void SettingsManager::SetCompleter::tabCompletion(std::vector<std::string>& tokens) const
190{
191 const auto& manager = OUTER(SettingsManager, setCompleter);
192 switch (tokens.size()) {
193 case 2: {
194 // complete setting name
195 completeString(tokens, manager.getTabSettingNames(), false); // case insensitive
196 break;
197 }
198 case 3:
199 // complete setting value
200 if (const auto* setting = manager.findSetting(tokens[1])) {
201 setting->tabCompletion(tokens);
202 }
203 break;
204 }
205}
206
207
208// class SettingCompleter
209
210SettingsManager::SettingCompleter::SettingCompleter(
211 CommandController& commandController_, SettingsManager& manager_,
212 const std::string& name_)
213 : CommandCompleter(commandController_, name_)
214 , manager(manager_)
215{
216}
217
218std::string SettingsManager::SettingCompleter::help(std::span<const TclObject> /*tokens*/) const
219{
220 return {}; // TODO
221}
222
223void SettingsManager::SettingCompleter::tabCompletion(std::vector<std::string>& tokens) const
224{
225 if (tokens.size() == 2) {
226 // complete setting name
227 completeString(tokens, manager.getTabSettingNames());
228 }
229}
230
231} // 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.
void loadSettings(const SettingsConfig &config) const
void unregisterSetting(BaseSetting &setting)
SettingsManager(GlobalCommandController &commandController)
void registerSetting(BaseSetting &setting)
constexpr double e
Definition Math.hh:21
This file implemented 3 utility functions:
Definition Autofire.cc:11
constexpr auto transform(Range &&range, UnaryOp op)
Definition view.hh:520
#define OUTER(type, member)
Definition outer.hh:42
std::string strCat()
Definition strCat.hh:703
TemporaryString tmpStrCat(Ts &&... ts)
Definition strCat.hh:742
constexpr auto end(const zstring_view &x)