Make TypedOption templates public
This commit is contained in:
parent
14933bdeaf
commit
4ec9c4c32a
|
@ -1,154 +1,14 @@
|
||||||
#include "option_manager.hh"
|
#include "option_manager.hh"
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
|
|
||||||
#include "option_types.hh"
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
String option_to_string(const String& opt) { return opt; }
|
|
||||||
void option_from_string(const String& str, String& opt) { opt = str; }
|
|
||||||
|
|
||||||
String option_to_string(int opt) { return int_to_str(opt); }
|
|
||||||
void option_from_string(const String& str, int& opt) { opt = str_to_int(str); }
|
|
||||||
|
|
||||||
String option_to_string(bool opt) { return opt ? "true" : "false"; }
|
|
||||||
void option_from_string(const String& str, bool& opt)
|
|
||||||
{
|
|
||||||
if (str == "true" or str == "yes")
|
|
||||||
opt = true;
|
|
||||||
else if (str == "false" or str == "no")
|
|
||||||
opt = false;
|
|
||||||
else
|
|
||||||
throw runtime_error("boolean values are either true, yes, false or no");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
String option_to_string(const std::vector<T>& opt)
|
|
||||||
{
|
|
||||||
String res;
|
|
||||||
for (size_t i = 0; i < opt.size(); ++i)
|
|
||||||
{
|
|
||||||
res += option_to_string(opt[i]);
|
|
||||||
if (i != opt.size() - 1)
|
|
||||||
res += ",";
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void option_from_string(const String& str, std::vector<T>& opt)
|
|
||||||
{
|
|
||||||
opt.clear();
|
|
||||||
std::vector<String> elems = split(str, ',');
|
|
||||||
for (auto& elem: elems)
|
|
||||||
{
|
|
||||||
T opt_elem;
|
|
||||||
option_from_string(elem, opt_elem);
|
|
||||||
opt.push_back(opt_elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String option_to_string(const Regex& re)
|
|
||||||
{
|
|
||||||
return String{re.str()};
|
|
||||||
}
|
|
||||||
|
|
||||||
void option_from_string(const String& str, Regex& re)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
re = Regex{str.begin(), str.end()};
|
|
||||||
}
|
|
||||||
catch (boost::regex_error& err)
|
|
||||||
{
|
|
||||||
throw runtime_error("unable to create regex: "_str + err.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class TypedOption : public Option
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TypedOption(OptionManager& manager, String name, const T& value)
|
|
||||||
: Option(manager, std::move(name)), m_value(value) {}
|
|
||||||
|
|
||||||
void set(const T& value)
|
|
||||||
{
|
|
||||||
if (m_value != value)
|
|
||||||
{
|
|
||||||
m_value = value;
|
|
||||||
m_manager.on_option_changed(*this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const T& get() const { return m_value; }
|
|
||||||
|
|
||||||
String get_as_string() const override
|
|
||||||
{
|
|
||||||
return option_to_string(m_value);
|
|
||||||
}
|
|
||||||
void set_from_string(const String& str) override
|
|
||||||
{
|
|
||||||
T val;
|
|
||||||
option_from_string(str, val);
|
|
||||||
set(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
Option* clone(OptionManager& manager) const override
|
|
||||||
{
|
|
||||||
return new TypedOption{manager, name(), m_value};
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
T m_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Option::Option(OptionManager& manager, String name)
|
Option::Option(OptionManager& manager, String name)
|
||||||
: m_manager(manager), m_name(std::move(name)) {}
|
: m_manager(manager), m_name(std::move(name)) {}
|
||||||
|
|
||||||
template<typename T> const T& Option::get() const
|
|
||||||
{
|
|
||||||
auto* typed_opt = dynamic_cast<const TypedOption<T>*>(this);
|
|
||||||
if (not typed_opt)
|
|
||||||
throw runtime_error("option " + name() + " is not of type " + typeid(T).name());
|
|
||||||
return typed_opt->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> void Option::set(const T& val)
|
|
||||||
{
|
|
||||||
auto* typed_opt = dynamic_cast<TypedOption<T>*>(this);
|
|
||||||
if (not typed_opt)
|
|
||||||
throw runtime_error("option " + name() + " is not of type " + typeid(T).name());
|
|
||||||
return typed_opt->set(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
template const String& Option::get<String>() const;
|
|
||||||
template void Option::set<String>(const String&);
|
|
||||||
|
|
||||||
template const int& Option::get<int>() const;
|
|
||||||
template void Option::set<int>(const int&);
|
|
||||||
|
|
||||||
template const bool& Option::get<bool>() const;
|
|
||||||
template void Option::set<bool>(const bool&);
|
|
||||||
|
|
||||||
template const std::vector<int>& Option::get<std::vector<int>>() const;
|
|
||||||
template void Option::set<std::vector<int>>(const std::vector<int>&);
|
|
||||||
|
|
||||||
template const std::vector<String>& Option::get<std::vector<String>>() const;
|
|
||||||
template void Option::set<std::vector<String>>(const std::vector<String>&);
|
|
||||||
|
|
||||||
template const Regex& Option::get<Regex>() const;
|
|
||||||
template void Option::set<Regex>(const Regex&);
|
|
||||||
|
|
||||||
template const std::vector<LineAndFlag>& Option::get<std::vector<LineAndFlag>>() const;
|
|
||||||
template void Option::set<std::vector<LineAndFlag>>(const std::vector<LineAndFlag>&);
|
|
||||||
|
|
||||||
OptionManager::OptionManager(OptionManager& parent)
|
OptionManager::OptionManager(OptionManager& parent)
|
||||||
: m_parent(&parent)
|
: m_parent(&parent)
|
||||||
{
|
{
|
||||||
|
@ -176,13 +36,6 @@ void OptionManager::unregister_watcher(OptionManagerWatcher& watcher)
|
||||||
m_watchers.erase(it);
|
m_watchers.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto find_option(T& container, const String& name) -> decltype(container.begin())
|
|
||||||
{
|
|
||||||
using ptr_type = decltype(*container.begin());
|
|
||||||
return find_if(container, [&name](const ptr_type& opt) { return opt->name() == name; });
|
|
||||||
}
|
|
||||||
|
|
||||||
Option& OptionManager::get_local_option(const String& name)
|
Option& OptionManager::get_local_option(const String& name)
|
||||||
{
|
{
|
||||||
auto it = find_option(m_options, name);
|
auto it = find_option(m_options, name);
|
||||||
|
@ -268,16 +121,4 @@ GlobalOptions::GlobalOptions()
|
||||||
declare_option<bool>("insert_hide_sel", false);
|
declare_option<bool>("insert_hide_sel", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
Option& GlobalOptions::declare_option(const String& name, const T& value)
|
|
||||||
{
|
|
||||||
if (find_option(m_options, name) != m_options.end())
|
|
||||||
throw runtime_error("option " + name + " already declared");
|
|
||||||
m_options.emplace_back(new TypedOption<T>{*this, name, value});
|
|
||||||
return *m_options.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
template Option& GlobalOptions::declare_option<>(const String&, const std::vector<int>&);
|
|
||||||
template Option& GlobalOptions::declare_option<>(const String&, const std::vector<LineAndFlag>&);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
|
#include "option_types.hh"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
@ -78,6 +79,65 @@ private:
|
||||||
std::vector<OptionManagerWatcher*> m_watchers;
|
std::vector<OptionManagerWatcher*> m_watchers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class TypedOption : public Option
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TypedOption(OptionManager& manager, String name, const T& value)
|
||||||
|
: Option(manager, std::move(name)), m_value(value) {}
|
||||||
|
|
||||||
|
void set(const T& value)
|
||||||
|
{
|
||||||
|
if (m_value != value)
|
||||||
|
{
|
||||||
|
m_value = value;
|
||||||
|
m_manager.on_option_changed(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const T& get() const { return m_value; }
|
||||||
|
|
||||||
|
String get_as_string() const override
|
||||||
|
{
|
||||||
|
return option_to_string(m_value);
|
||||||
|
}
|
||||||
|
void set_from_string(const String& str) override
|
||||||
|
{
|
||||||
|
T val;
|
||||||
|
option_from_string(str, val);
|
||||||
|
set(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Option* clone(OptionManager& manager) const override
|
||||||
|
{
|
||||||
|
return new TypedOption{manager, name(), m_value};
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
T m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> const T& Option::get() const
|
||||||
|
{
|
||||||
|
auto* typed_opt = dynamic_cast<const TypedOption<T>*>(this);
|
||||||
|
if (not typed_opt)
|
||||||
|
throw runtime_error("option " + name() + " is not of type " + typeid(T).name());
|
||||||
|
return typed_opt->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> void Option::set(const T& val)
|
||||||
|
{
|
||||||
|
auto* typed_opt = dynamic_cast<TypedOption<T>*>(this);
|
||||||
|
if (not typed_opt)
|
||||||
|
throw runtime_error("option " + name() + " is not of type " + typeid(T).name());
|
||||||
|
return typed_opt->set(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto find_option(T& container, const String& name) -> decltype(container.begin())
|
||||||
|
{
|
||||||
|
using ptr_type = decltype(*container.begin());
|
||||||
|
return find_if(container, [&name](const ptr_type& opt) { return opt->name() == name; });
|
||||||
|
}
|
||||||
|
|
||||||
class GlobalOptions : public OptionManager,
|
class GlobalOptions : public OptionManager,
|
||||||
public Singleton<GlobalOptions>
|
public Singleton<GlobalOptions>
|
||||||
{
|
{
|
||||||
|
@ -85,7 +145,13 @@ public:
|
||||||
GlobalOptions();
|
GlobalOptions();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Option& declare_option(const String& name, const T& inital_value);
|
Option& declare_option(const String& name, const T& value)
|
||||||
|
{
|
||||||
|
if (find_option(m_options, name) != m_options.end())
|
||||||
|
throw runtime_error("option " + name + " already declared");
|
||||||
|
m_options.emplace_back(new TypedOption<T>{*this, name, value});
|
||||||
|
return *m_options.back();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,23 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
String option_to_string(const Regex& re)
|
||||||
|
{
|
||||||
|
return String{re.str()};
|
||||||
|
}
|
||||||
|
|
||||||
|
void option_from_string(const String& str, Regex& re)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
re = Regex{str.begin(), str.end()};
|
||||||
|
}
|
||||||
|
catch (boost::regex_error& err)
|
||||||
|
{
|
||||||
|
throw runtime_error("unable to create regex: "_str + err.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String option_to_string(const LineAndFlag& opt)
|
String option_to_string(const LineAndFlag& opt)
|
||||||
{
|
{
|
||||||
return int_to_str((int)opt.line) + ":" + color_to_str(opt.color) + ":" + opt.flag;
|
return int_to_str((int)opt.line) + ":" + color_to_str(opt.color) + ":" + opt.flag;
|
||||||
|
|
|
@ -4,10 +4,57 @@
|
||||||
#include "units.hh"
|
#include "units.hh"
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
#include "color.hh"
|
#include "color.hh"
|
||||||
|
#include "exception.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
inline String option_to_string(const String& opt) { return opt; }
|
||||||
|
inline void option_from_string(const String& str, String& opt) { opt = str; }
|
||||||
|
|
||||||
|
inline String option_to_string(int opt) { return int_to_str(opt); }
|
||||||
|
inline void option_from_string(const String& str, int& opt) { opt = str_to_int(str); }
|
||||||
|
|
||||||
|
inline String option_to_string(bool opt) { return opt ? "true" : "false"; }
|
||||||
|
inline void option_from_string(const String& str, bool& opt)
|
||||||
|
{
|
||||||
|
if (str == "true" or str == "yes")
|
||||||
|
opt = true;
|
||||||
|
else if (str == "false" or str == "no")
|
||||||
|
opt = false;
|
||||||
|
else
|
||||||
|
throw runtime_error("boolean values are either true, yes, false or no");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
String option_to_string(const std::vector<T>& opt)
|
||||||
|
{
|
||||||
|
String res;
|
||||||
|
for (size_t i = 0; i < opt.size(); ++i)
|
||||||
|
{
|
||||||
|
res += option_to_string(opt[i]);
|
||||||
|
if (i != opt.size() - 1)
|
||||||
|
res += ',';
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void option_from_string(const String& str, std::vector<T>& opt)
|
||||||
|
{
|
||||||
|
opt.clear();
|
||||||
|
std::vector<String> elems = split(str, ',');
|
||||||
|
for (auto& elem: elems)
|
||||||
|
{
|
||||||
|
T opt_elem;
|
||||||
|
option_from_string(elem, opt_elem);
|
||||||
|
opt.push_back(opt_elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String option_to_string(const Regex& re);
|
||||||
|
void option_from_string(const String& str, Regex& re);
|
||||||
|
|
||||||
struct LineAndFlag
|
struct LineAndFlag
|
||||||
{
|
{
|
||||||
LineCount line;
|
LineCount line;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user