Migrate to a more value based meta programming model
Introduce Meta::Type<T> to store a type as value, and pass it around, migrate enum_desc and option_type_name to this.
This commit is contained in:
parent
a88e58763b
commit
a49e175727
|
@ -21,7 +21,7 @@ enum class EolFormat
|
||||||
Crlf
|
Crlf
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Array<EnumDesc<EolFormat>, 2> enum_desc(EolFormat)
|
constexpr Array<EnumDesc<EolFormat>, 2> enum_desc(Meta::Type<EolFormat>)
|
||||||
{
|
{
|
||||||
return { {
|
return { {
|
||||||
{ EolFormat::Lf, "lf" },
|
{ EolFormat::Lf, "lf" },
|
||||||
|
@ -35,7 +35,7 @@ enum class ByteOrderMark
|
||||||
Utf8
|
Utf8
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Array<EnumDesc<ByteOrderMark>, 2> enum_desc(ByteOrderMark)
|
constexpr Array<EnumDesc<ByteOrderMark>, 2> enum_desc(Meta::Type<ByteOrderMark>)
|
||||||
{
|
{
|
||||||
return { {
|
return { {
|
||||||
{ ByteOrderMark::None, "none" },
|
{ ByteOrderMark::None, "none" },
|
||||||
|
|
|
@ -131,7 +131,7 @@ enum class Autoreload
|
||||||
Ask
|
Ask
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Array<EnumDesc<Autoreload>, 5> enum_desc(Autoreload)
|
constexpr Array<EnumDesc<Autoreload>, 5> enum_desc(Meta::Type<Autoreload>)
|
||||||
{
|
{
|
||||||
return { {
|
return { {
|
||||||
{ Autoreload::Yes, "yes" },
|
{ Autoreload::Yes, "yes" },
|
||||||
|
|
|
@ -43,17 +43,15 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
template<>
|
StringView option_type_name(Meta::Type<TimestampedList<LineAndFlag>>)
|
||||||
struct option_type_name<TimestampedList<LineAndFlag>>
|
|
||||||
{
|
{
|
||||||
static StringView name() { return "line-flags"; }
|
return "line-flags";
|
||||||
};
|
}
|
||||||
|
|
||||||
template<>
|
StringView option_type_name(Meta::Type<TimestampedList<RangeAndFace>>)
|
||||||
struct option_type_name<TimestampedList<RangeAndFace>>
|
|
||||||
{
|
{
|
||||||
static StringView name() { return "range-faces"; }
|
return "range-faces";
|
||||||
};
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
19
src/enum.hh
19
src/enum.hh
|
@ -5,6 +5,7 @@
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
#include "containers.hh"
|
#include "containers.hh"
|
||||||
|
#include "meta.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -22,10 +23,10 @@ struct Array
|
||||||
|
|
||||||
template<typename T> struct EnumDesc { T value; StringView name; };
|
template<typename T> struct EnumDesc { T value; StringView name; };
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Flags{}))>
|
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
||||||
EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
|
EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Flags{});
|
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
||||||
String res;
|
String res;
|
||||||
for (int i = 0; i < desc.size(); ++i)
|
for (int i = 0; i < desc.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -38,10 +39,10 @@ EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enum, typename = decltype(enum_desc(Enum{}))>
|
template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
|
||||||
EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
|
EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Enum{});
|
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
||||||
auto it = find_if(desc, [e](const EnumDesc<Enum>& d) { return d.value == e; });
|
auto it = find_if(desc, [e](const EnumDesc<Enum>& d) { return d.value == e; });
|
||||||
if (it != desc.end())
|
if (it != desc.end())
|
||||||
return it->name.str();
|
return it->name.str();
|
||||||
|
@ -49,10 +50,10 @@ EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Flags{}))>
|
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
||||||
EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags)
|
EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Flags{});
|
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
||||||
flags = Flags{};
|
flags = Flags{};
|
||||||
for (auto s : str | split<StringView>('|'))
|
for (auto s : str | split<StringView>('|'))
|
||||||
{
|
{
|
||||||
|
@ -63,17 +64,17 @@ EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enum, typename = decltype(enum_desc(Enum{}))>
|
template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
|
||||||
EnableIfWithoutBitOps<Enum> option_from_string(StringView str, Enum& e)
|
EnableIfWithoutBitOps<Enum> option_from_string(StringView str, Enum& e)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Enum{});
|
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
||||||
auto it = find_if(desc, [str](const EnumDesc<Enum>& d) { return d.name == str; });
|
auto it = find_if(desc, [str](const EnumDesc<Enum>& d) { return d.name == str; });
|
||||||
if (it == desc.end())
|
if (it == desc.end())
|
||||||
throw runtime_error(format("invalid enum value '{}'", str));
|
throw runtime_error(format("invalid enum value '{}'", str));
|
||||||
e = it->value;
|
e = it->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Flags{}))>
|
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
||||||
EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str)
|
EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str)
|
||||||
{
|
{
|
||||||
Flags res = Flags{};
|
Flags res = Flags{};
|
||||||
|
|
|
@ -134,7 +134,7 @@ enum class AutoInfo
|
||||||
template<>
|
template<>
|
||||||
struct WithBitOps<AutoInfo> : std::true_type {};
|
struct WithBitOps<AutoInfo> : std::true_type {};
|
||||||
|
|
||||||
constexpr Array<EnumDesc<AutoInfo>, 3> enum_desc(AutoInfo)
|
constexpr Array<EnumDesc<AutoInfo>, 3> enum_desc(Meta::Type<AutoInfo>)
|
||||||
{
|
{
|
||||||
return { {
|
return { {
|
||||||
{ AutoInfo::Command, "command"},
|
{ AutoInfo::Command, "command"},
|
||||||
|
|
|
@ -37,18 +37,18 @@ using InsertCompleterDescList = Vector<InsertCompleterDesc, MemoryDomain::Option
|
||||||
String option_to_string(const InsertCompleterDesc& opt);
|
String option_to_string(const InsertCompleterDesc& opt);
|
||||||
void option_from_string(StringView str, InsertCompleterDesc& opt);
|
void option_from_string(StringView str, InsertCompleterDesc& opt);
|
||||||
|
|
||||||
template<> struct option_type_name<InsertCompleterDesc>
|
inline StringView option_type_name(Meta::Type<InsertCompleterDesc>)
|
||||||
{
|
{
|
||||||
static constexpr StringView name() { return "completer"; }
|
return "completer";
|
||||||
};
|
}
|
||||||
|
|
||||||
using CompletionCandidate = std::tuple<String, String, String>;
|
using CompletionCandidate = std::tuple<String, String, String>;
|
||||||
using CompletionList = PrefixedList<String, CompletionCandidate>;
|
using CompletionList = PrefixedList<String, CompletionCandidate>;
|
||||||
|
|
||||||
template<> struct option_type_name<CompletionList>
|
inline StringView option_type_name(Meta::Type<CompletionList>)
|
||||||
{
|
{
|
||||||
static constexpr StringView name() { return "completions"; }
|
return "completions";
|
||||||
};
|
}
|
||||||
|
|
||||||
struct InsertCompletion
|
struct InsertCompletion
|
||||||
{
|
{
|
||||||
|
|
14
src/meta.hh
Normal file
14
src/meta.hh
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef meta_hh_INCLUDED
|
||||||
|
#define meta_hh_INCLUDED
|
||||||
|
|
||||||
|
namespace Kakoune
|
||||||
|
{
|
||||||
|
namespace Meta
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T> struct Type {};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // meta_hh_INCLUDED
|
|
@ -221,8 +221,8 @@ public:
|
||||||
return **it;
|
return **it;
|
||||||
throw runtime_error{format("option '{}' already declared with different type or flags", name)};
|
throw runtime_error{format("option '{}' already declared with different type or flags", name)};
|
||||||
}
|
}
|
||||||
String doc = docstring.empty() ? format("[{}]", option_type_name<T>::name())
|
String doc = docstring.empty() ? format("[{}]", option_type_name(Meta::Type<T>{}))
|
||||||
: format("[{}] - {}", option_type_name<T>::name(), docstring);
|
: format("[{}] - {}", option_type_name(Meta::Type<T>{}), docstring);
|
||||||
m_descs.emplace_back(new OptionDesc{name.str(), std::move(doc), flags});
|
m_descs.emplace_back(new OptionDesc{name.str(), std::move(doc), flags});
|
||||||
opts.emplace_back(new TypedCheckedOption<T, validator>{m_global_manager, *m_descs.back(), value});
|
opts.emplace_back(new TypedCheckedOption<T, validator>{m_global_manager, *m_descs.back(), value});
|
||||||
return *opts.back();
|
return *opts.back();
|
||||||
|
|
|
@ -16,25 +16,22 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T, typename = void> struct option_type_name;
|
template<typename T> using valid = std::true_type;
|
||||||
template<typename T> using void_t = void;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct option_type_name<T, void_t<decltype(T::option_type_name)>>
|
constexpr decltype(T::option_type_name) option_type_name(Meta::Type<T>)
|
||||||
{
|
{
|
||||||
static decltype(T::option_type_name) name() { return T::option_type_name; }
|
return T::option_type_name;
|
||||||
};
|
}
|
||||||
|
|
||||||
template<typename Enum>
|
template<typename Enum>
|
||||||
struct option_type_name<Enum, typename std::enable_if<std::is_enum<Enum>::value>::type>
|
typename std::enable_if<std::is_enum<Enum>::value, String>::type
|
||||||
|
option_type_name(Meta::Type<Enum>)
|
||||||
{
|
{
|
||||||
static String name()
|
constexpr StringView type = WithBitOps<Enum>::value ? "flags" : "enum";
|
||||||
{
|
auto name = enum_desc(Meta::Type<Enum>{});
|
||||||
constexpr StringView type = WithBitOps<Enum>::value ? "flags" : "enum";
|
return type + "(" + join(name | transform(std::mem_fn(&EnumDesc<Enum>::name)), '|') + ")";
|
||||||
auto name = enum_desc(Enum{});
|
}
|
||||||
return type + "(" + join(name | transform(std::mem_fn(&EnumDesc<Enum>::name)), '|') + ")";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline String option_to_string(int opt) { return to_string(opt); }
|
inline String option_to_string(int opt) { return to_string(opt); }
|
||||||
inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); }
|
inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); }
|
||||||
|
@ -44,7 +41,7 @@ inline bool option_add(int& opt, StringView str)
|
||||||
opt += val;
|
opt += val;
|
||||||
return val != 0;
|
return val != 0;
|
||||||
}
|
}
|
||||||
template<> struct option_type_name<int> { static StringView name() { return "int"; } };
|
inline StringView option_type_name(Meta::Type<int>) { return "int"; }
|
||||||
|
|
||||||
inline String option_to_string(size_t opt) { return to_string(opt); }
|
inline String option_to_string(size_t opt) { return to_string(opt); }
|
||||||
inline void option_from_string(StringView str, size_t& opt) { opt = str_to_int(str); }
|
inline void option_from_string(StringView str, size_t& opt) { opt = str_to_int(str); }
|
||||||
|
@ -59,7 +56,7 @@ inline void option_from_string(StringView str, bool& opt)
|
||||||
else
|
else
|
||||||
throw runtime_error("boolean values are either true, yes, false or no");
|
throw runtime_error("boolean values are either true, yes, false or no");
|
||||||
}
|
}
|
||||||
template<> struct option_type_name<bool> { static StringView name() { return "bool"; } };
|
inline StringView option_type_name(Meta::Type<bool>) { return "bool"; }
|
||||||
|
|
||||||
constexpr char list_separator = ':';
|
constexpr char list_separator = ':';
|
||||||
|
|
||||||
|
@ -101,10 +98,10 @@ bool option_add(Vector<T, domain>& opt, StringView str)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, MemoryDomain D>
|
template<typename T, MemoryDomain D>
|
||||||
struct option_type_name<Vector<T, D>>
|
String option_type_name(Meta::Type<Vector<T, D>>)
|
||||||
{
|
{
|
||||||
static String name() { return option_type_name<T>::name() + StringView{"-list"}; }
|
return option_type_name(Meta::Type<T>{}) + StringView{"-list"};
|
||||||
};
|
}
|
||||||
|
|
||||||
template<typename Key, typename Value, MemoryDomain domain>
|
template<typename Key, typename Value, MemoryDomain domain>
|
||||||
String option_to_string(const HashMap<Key, Value, domain>& opt)
|
String option_to_string(const HashMap<Key, Value, domain>& opt)
|
||||||
|
@ -139,12 +136,11 @@ void option_from_string(StringView str, HashMap<Key, Value, domain>& opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename V, MemoryDomain D>
|
template<typename K, typename V, MemoryDomain D>
|
||||||
struct option_type_name<HashMap<K, V, D>>
|
String option_type_name(Meta::Type<HashMap<K, V, D>>)
|
||||||
{
|
{
|
||||||
static String name() { return format("{}-to-{}-map",
|
return format("{}-to-{}-map", option_type_name(Meta::Type<K>{}),
|
||||||
option_type_name<K>::name(),
|
option_type_name(Meta::Type<V>{}));
|
||||||
option_type_name<V>::name()); }
|
}
|
||||||
};
|
|
||||||
|
|
||||||
constexpr char tuple_separator = '|';
|
constexpr char tuple_separator = '|';
|
||||||
|
|
||||||
|
@ -251,7 +247,7 @@ enum class DebugFlags
|
||||||
template<>
|
template<>
|
||||||
struct WithBitOps<DebugFlags> : std::true_type {};
|
struct WithBitOps<DebugFlags> : std::true_type {};
|
||||||
|
|
||||||
constexpr Array<EnumDesc<DebugFlags>, 4> enum_desc(DebugFlags)
|
constexpr Array<EnumDesc<DebugFlags>, 4> enum_desc(Meta::Type<DebugFlags>)
|
||||||
{
|
{
|
||||||
return { {
|
return { {
|
||||||
{ DebugFlags::Hooks, "hooks" },
|
{ DebugFlags::Hooks, "hooks" },
|
||||||
|
|
Loading…
Reference in New Issue
Block a user