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);
96 file.
read(std::span{buf.
data(), size});
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) {
124 "Couldn't restore key-binding: ", e.getMessage());
127 for (
const auto& key : parser.
unbinds) {
132 "Couldn't restore key-binding: ", e.getMessage());
144 saveName = context.resolveCreate(filename);
164 if (filename.empty()) filename = saveName;
165 if (filename.empty())
return;
167 struct SettingsWriter {
168 SettingsWriter(std::string filename)
169 : file(std::move(filename), File::TRUNCATE)
171 std::string_view header =
172 "<!DOCTYPE settings SYSTEM 'settings.dtd'>\n";
176 void write(std::span<const char> buf) {
179 void write1(
char c) {
180 file.write(std::span{&c, 1});
182 void check(
bool condition)
const {
183 assert(condition); (void)condition;
190 SettingsWriter writer(std::move(filename));
192 xml.
begin(
"settings");
194 xml.
begin(
"settings");
195 for (
const auto& [name, value] : settingValues) {
196 xml.
begin(
"setting");
212SettingsConfig::SaveSettingsCommand::SaveSettingsCommand(
214 :
Command(commandController_,
"save_settings")
218void SettingsConfig::SaveSettingsCommand::execute(
219 std::span<const TclObject> tokens, TclObject& )
221 checkNumArgs(tokens, Between{1, 2}, Prefix{1},
"?filename?");
222 auto& settingsConfig =
OUTER(SettingsConfig, saveSettingsCommand);
224 switch (tokens.size()) {
226 settingsConfig.saveSetting();
230 string(tokens[1].getString())));
233 }
catch (FileException& e) {
234 throw CommandException(std::move(e).getMessage());
238string SettingsConfig::SaveSettingsCommand::help(std::span<const TclObject> )
const
240 return "Save the current settings.";
243void SettingsConfig::SaveSettingsCommand::tabCompletion(std::vector<string>& tokens)
const
245 if (tokens.size() == 2) {
253SettingsConfig::LoadSettingsCommand::LoadSettingsCommand(
254 CommandController& commandController_)
255 : Command(commandController_,
"load_settings")
259void SettingsConfig::LoadSettingsCommand::execute(
260 std::span<const TclObject> tokens, TclObject& )
262 checkNumArgs(tokens, 2,
"filename");
263 auto& settingsConfig =
OUTER(SettingsConfig, loadSettingsCommand);
267string SettingsConfig::LoadSettingsCommand::help(std::span<const TclObject> )
const
269 return "Load settings from given file.";
272void SettingsConfig::LoadSettingsCommand::tabCompletion(std::vector<string>& tokens)
const
274 if (tokens.size() == 2) {
288 if (tag ==
"settings") {
294 if (tag ==
"settings") {
297 }
else if (tag ==
"bindings") {
303 if (tag ==
"setting") {
314 }
else if (tag ==
"unbind") {
346 }
else if (name ==
"repeat") {
348 }
else if (name ==
"event") {
423 auto pos1 = txt.find(
" SYSTEM ");
424 if (pos1 == std::string_view::npos)
return;
425 if ((pos1 + 8) >= txt.size())
return;
426 char q = txt[pos1 + 8];
427 if (q !=
one_of(
'"',
'\''))
return;
428 auto t = txt.substr(pos1 + 9);
429 auto pos2 =
t.find(q);
430 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)
This class manages the lifetime of a block of memory.
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)
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
#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.