summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2016-02-11 22:07:18 +0000
committerMaxime Coste <frrrwww@gmail.com>2016-02-11 22:07:18 +0000
commit986c91a8356bc0fb3dcff97479b167a4c8326d80 (patch)
tree69c99cbd07faab01caa96b9e9242bb1354a0f6ae /src
parent9cdfa4a81c9eee18a08bfef1bba43839fbc716f3 (diff)
Support validating some options values before setting them
Fixes #583
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/main.cc22
-rw-r--r--src/option_manager.hh24
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();
}