Option can be declared with a checker function.

The checker function may throw if to be set option value is invalid.
Implemented with the completers option.
This commit is contained in:
Maxime Coste 2013-05-06 13:52:41 +02:00
parent c1615b5c15
commit 3a49e05832
2 changed files with 26 additions and 9 deletions

View File

@ -119,7 +119,14 @@ GlobalOptions::GlobalOptions()
declare_option<String>("filetype", ""); declare_option<String>("filetype", "");
declare_option<std::vector<String>>("completions", {}); declare_option<std::vector<String>>("completions", {});
declare_option<std::vector<String>>("path", { "./", "/usr/include" }); declare_option<std::vector<String>>("path", { "./", "/usr/include" });
declare_option<std::unordered_set<String>>("completers", {"option", "word"}); declare_option<std::unordered_set<String>>("completers", {"option", "word"},
[](const std::unordered_set<String>& s) {
for (auto& v : s)
{
if (v != "option" and v != "word")
throw runtime_error(v + " is not a recognised value for completers");
}
});
declare_option<bool>("insert_hide_sel", false); declare_option<bool>("insert_hide_sel", false);
} }

View File

@ -81,18 +81,24 @@ private:
std::vector<OptionManagerWatcher*> m_watchers; std::vector<OptionManagerWatcher*> m_watchers;
}; };
template<typename T> using OptionChecker = std::function<void (const T&)>;
template<typename T> template<typename T>
class TypedOption : public Option class TypedOption : public Option
{ {
public: public:
TypedOption(OptionManager& manager, String name, const T& value) TypedOption(OptionManager& manager, String name, const T& value,
: Option(manager, std::move(name)), m_value(value) {} OptionChecker<T> checker)
: Option(manager, std::move(name)), m_value(value),
m_checker(std::move(checker)) {}
void set(const T& value) void set(T value)
{ {
if (m_value != value) if (m_value != value)
{ {
m_value = value; if (m_checker)
m_checker(value);
m_value = std::move(value);
m_manager.on_option_changed(*this); m_manager.on_option_changed(*this);
} }
} }
@ -106,22 +112,25 @@ public:
{ {
T val; T val;
option_from_string(str, val); option_from_string(str, val);
set(val); set(std::move(val));
} }
void add_from_string(const String& str) override void add_from_string(const String& str) override
{ {
T val; T val;
option_from_string(str, val); option_from_string(str, val);
if (m_checker)
m_checker(val);
if (option_add(m_value, val)) if (option_add(m_value, val))
m_manager.on_option_changed(*this); m_manager.on_option_changed(*this);
} }
Option* clone(OptionManager& manager) const override Option* clone(OptionManager& manager) const override
{ {
return new TypedOption{manager, name(), m_value}; return new TypedOption{manager, name(), m_value, m_checker};
} }
private: private:
T m_value; T m_value;
OptionChecker<T> m_checker;
}; };
template<typename T> const T& Option::get() const template<typename T> const T& Option::get() const
@ -159,7 +168,8 @@ public:
GlobalOptions(); GlobalOptions();
template<typename T> template<typename T>
Option& declare_option(const String& name, const T& value) Option& declare_option(const String& name, const T& value,
OptionChecker<T> checker = OptionChecker<T>{})
{ {
auto it = find_option(m_options, name); auto it = find_option(m_options, name);
if (it != m_options.end()) if (it != m_options.end())
@ -168,7 +178,7 @@ public:
return **it; return **it;
throw runtime_error("option " + name + " already declared with different type"); throw runtime_error("option " + name + " already declared with different type");
} }
m_options.emplace_back(new TypedOption<T>{*this, name, value}); m_options.emplace_back(new TypedOption<T>{*this, name, value, std::move(checker)});
return *m_options.back(); return *m_options.back();
} }
}; };