diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2016-02-11 22:07:18 +0000 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2016-02-11 22:07:18 +0000 |
| commit | 986c91a8356bc0fb3dcff97479b167a4c8326d80 (patch) | |
| tree | 69c99cbd07faab01caa96b9e9242bb1354a0f6ae /src | |
| parent | 9cdfa4a81c9eee18a08bfef1bba43839fbc716f3 (diff) | |
Support validating some options values before setting them
Fixes #583
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 2 | ||||
| -rw-r--r-- | src/main.cc | 22 | ||||
| -rw-r--r-- | src/option_manager.hh | 24 |
3 files changed, 35 insertions, 13 deletions
diff --git a/src/Makefile b/src/Makefile index 382a7a6e..7ed136e2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -60,7 +60,7 @@ endif # Picking the right name is done in the system detection switch above A2X ?= a2x -CXXFLAGS += -std=gnu++11 -g -Wall -Wno-reorder -Wno-sign-compare +CXXFLAGS += -std=gnu++11 -g -Wall -Wno-reorder -Wno-sign-compare -Wno-address kak : $(objects) $(CXX) $(LDFLAGS) $(CXXFLAGS) $(objects) $(LIBS) -o $@ diff --git a/src/main.cc b/src/main.cc index 9414da30..e846dfbc 100644 --- a/src/main.cc +++ b/src/main.cc @@ -178,15 +178,27 @@ void register_registers() register_manager.add_register('_', make_unique<NullRegister>()); } +static void check_positive(const int& val) +{ + if (val < 1) + throw runtime_error{"value should be strictly positive"}; +} + +static void check_scrolloff(const CharCoord& so) +{ + if (so.line < 0 or so.column < 0) + throw runtime_error{"scroll offset must be positive or zero"}; +} + void register_options() { OptionsRegistry& reg = GlobalScope::instance().option_registry(); - reg.declare_option("tabstop", "size of a tab character", 8); - reg.declare_option("indentwidth", "indentation width", 4); - reg.declare_option("scrolloff", - "number of lines and columns to keep visible main cursor when scrolling", - CharCoord{0,0}); + reg.declare_option<int, check_positive>("tabstop", "size of a tab character", 8); + reg.declare_option<int, check_positive>("indentwidth", "indentation width", 4); + reg.declare_option<CharCoord, check_scrolloff>( + "scrolloff", "number of lines and columns to keep visible main cursor when scrolling", + {0,0}); reg.declare_option("eolformat", "end of line format: crlf or lf", EolFormat::Lf); reg.declare_option("BOM", "insert a byte order mark when writing buffer (none or utf8)", ByteOrderMark::None); diff --git a/src/option_manager.hh b/src/option_manager.hh index 6c4dce18..5cc39e92 100644 --- a/src/option_manager.hh +++ b/src/option_manager.hh @@ -115,6 +115,7 @@ public: void set(T value, bool notify = true) { + validate(value); if (m_value != value) { m_value = std::move(value); @@ -141,11 +142,6 @@ public: m_manager.on_option_changed(*this); } - Option* clone(OptionManager& manager) const override - { - return new TypedOption{manager, m_desc, m_value}; - } - using Alloc = Allocator<TypedOption, MemoryDomain::Options>; static void* operator new (std::size_t sz) { @@ -158,9 +154,23 @@ public: return Alloc{}.deallocate(reinterpret_cast<TypedOption*>(ptr), 1); } private: + virtual void validate(const T& value) const {} T m_value; }; +template<typename T, void (*validator)(const T&)> +class TypedCheckedOption : public TypedOption<T> +{ + using TypedOption<T>::TypedOption; + + Option* clone(OptionManager& manager) const override + { + return new TypedCheckedOption{manager, this->m_desc, this->get()}; + } + + void validate(const T& value) const override { if (validator != nullptr) validator(value); } +}; + template<typename T> const T& Option::get() const { auto* typed_opt = dynamic_cast<const TypedOption<T>*>(this); @@ -199,7 +209,7 @@ class OptionsRegistry public: OptionsRegistry(OptionManager& global_manager) : m_global_manager(global_manager) {} - template<typename T> + template<typename T, void (*validator)(const T&) = nullptr> Option& declare_option(const String& name, const String& docstring, const T& value, OptionFlags flags = OptionFlags::None) @@ -213,7 +223,7 @@ public: throw runtime_error(format("option '{}' already declared with different type or flags", name)); } m_descs.emplace_back(new OptionDesc{name, docstring, flags}); - opts.emplace_back(new TypedOption<T>{m_global_manager, *m_descs.back(), value}); + opts.emplace_back(new TypedCheckedOption<T, validator>{m_global_manager, *m_descs.back(), value}); return *opts.back(); } |
