25 void start(std::string_view tag);
26 void attribute(std::string_view name, std::string_view value);
27 void text(std::string_view txt);
29 void doctype(std::string_view txt);
67 : commandController(globalCommandController)
68 , saveSettingsCommand(commandController)
69 , loadSettingsCommand(commandController)
70 , settingsManager(globalCommandController)
77 if (mustSaveSettings) {
82 "Auto-saving of settings failed: ",
e.getMessage());
89 string resolved =
context.resolve(filename);
99 throw MSXException(
"Failed to read settings file '", filename,
100 "': ",
e.getMessage());
103 rapidsax::parse<0>(parser, buf.
data());
104 if (parser.
systemID !=
"settings.dtd") {
106 "Failed to parser settings file '", filename,
107 "': systemID doesn't match (expected 'settings.dtd' got '",
109 "You're probably using an old incompatible file format.");
112 settingValues.
clear();
114 for (
const auto& [name, value] : parser.
settings) {
115 settingValues.
emplace(name, value);
119 for (
const auto& [key, cmd,
repeat, event] : parser.
binds) {
122 for (
const auto& key : parser.
unbinds) {
134 saveName =
context.resolveCreate(filename);
154 if (filename.empty()) filename = saveName;
155 if (filename.empty())
return;
157 struct SettingsWriter {
158 SettingsWriter(std::string filename)
161 std::string_view header =
162 "<!DOCTYPE settings SYSTEM 'settings.dtd'>\n";
166 void write(std::span<const char> buf) {
169 void write1(
char c) {
170 file.write(std::span{&c, 1});
172 void check(
bool condition)
const {
173 assert(condition); (void)condition;
180 SettingsWriter writer(std::move(filename));
182 xml.
begin(
"settings");
184 xml.
begin(
"settings");
185 for (
const auto& [name, value] : settingValues) {
186 xml.
begin(
"setting");
202SettingsConfig::SaveSettingsCommand::SaveSettingsCommand(
204 :
Command(commandController_,
"save_settings")
208void SettingsConfig::SaveSettingsCommand::execute(
209 std::span<const TclObject> tokens, TclObject& )
211 checkNumArgs(tokens, Between{1, 2}, Prefix{1},
"?filename?");
212 auto& settingsConfig =
OUTER(SettingsConfig, saveSettingsCommand);
214 switch (tokens.size()) {
216 settingsConfig.saveSetting();
220 string(tokens[1].getString())));
223 }
catch (FileException&
e) {
224 throw CommandException(std::move(
e).getMessage());
228string SettingsConfig::SaveSettingsCommand::help(std::span<const TclObject> )
const
230 return "Save the current settings.";
233void SettingsConfig::SaveSettingsCommand::tabCompletion(std::vector<string>& tokens)
const
235 if (tokens.size() == 2) {
243SettingsConfig::LoadSettingsCommand::LoadSettingsCommand(
244 CommandController& commandController_)
245 : Command(commandController_,
"load_settings")
249void SettingsConfig::LoadSettingsCommand::execute(
250 std::span<const TclObject> tokens, TclObject& )
252 checkNumArgs(tokens, 2,
"filename");
253 auto& settingsConfig =
OUTER(SettingsConfig, loadSettingsCommand);
257string SettingsConfig::LoadSettingsCommand::help(std::span<const TclObject> )
const
259 return "Load settings from given file.";
262void SettingsConfig::LoadSettingsCommand::tabCompletion(std::vector<string>& tokens)
const
264 if (tokens.size() == 2) {
278 if (tag ==
"settings") {
284 if (tag ==
"settings") {
287 }
else if (tag ==
"bindings") {
293 if (tag ==
"setting") {
304 }
else if (tag ==
"unbind") {
336 }
else if (name ==
"repeat") {
338 }
else if (name ==
"event") {
413 auto pos1 = txt.find(
" SYSTEM ");
414 if (pos1 == std::string_view::npos)
return;
415 if ((pos1 + 8) >= txt.size())
return;
416 char q = txt[pos1 + 8];
417 if (q !=
one_of(
'"',
'\''))
return;
418 auto t = txt.substr(pos1 + 9);
419 auto pos2 =
t.find(q);
420 if (pos2 == std::string_view::npos)
return;
'XMLOutputStream' is a helper to write an XML file in a streaming way.
void attribute(std::string_view name, std::string_view value)
void begin(std::string_view tag)
void end(std::string_view tag)
void data(std::string_view value)
std::pair< iterator, bool > insert_or_assign(K &&key, V &&value)
std::pair< iterator, bool > emplace(Args &&... args)
void reserve(unsigned count)
void printWarning(std::string_view message)
virtual CliComm & getCliComm()=0
void read(std::span< uint8_t > buffer)
Read from file.
size_t getSize()
Returns the size of this file.
void loadUnbind(std::string_view key)
void saveBindings(XmlStream &xml) const
void loadBind(std::string_view key, std::string_view cmd, bool repeat, bool event)
void resize(size_t size)
Grow or shrink the memory block.
const T * data() const
Returns pointer to the start of the memory buffer.
SettingsConfig(GlobalCommandController &globalCommandController, HotKey &hotKey)
void saveSetting(std::string filename={})
void loadSetting(const FileContext &context, std::string_view filename)
SettingsManager & getSettingsManager()
void setSaveFilename(const FileContext &context, std::string_view filename)
void removeValueForSetting(std::string_view setting)
void setValueForSetting(std::string_view setting, std::string_view value)
const std::string * getValueForSetting(std::string_view setting) const
void loadSettings(const SettingsConfig &config)
const Value * lookup(const hash_map< Key, Value, Hasher, Equal > &map, const Key2 &key)
bool stringToBool(string_view str)
std::optional< Context > context
string expandTilde(string path)
Expand the '~' character to the users home directory.
This file implemented 3 utility functions:
const FileContext & systemFileContext()
constexpr size_t EXTRA_BUFFER_SPACE
size_t size(std::string_view utf8)
#define OUTER(type, member)
std::vector< Bind > binds
void start(std::string_view tag)
std::string_view systemID
enum openmsx::SettingsParser::State state
std::vector< Setting > settings
void attribute(std::string_view name, std::string_view value)
std::vector< std::string_view > unbinds
void text(std::string_view txt)
void doctype(std::string_view txt)
std::string_view currentUnbind
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.