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
|
||||
};
|
||||
|
||||
constexpr Array<EnumDesc<EolFormat>, 2> enum_desc(EolFormat)
|
||||
constexpr Array<EnumDesc<EolFormat>, 2> enum_desc(Meta::Type<EolFormat>)
|
||||
{
|
||||
return { {
|
||||
{ EolFormat::Lf, "lf" },
|
||||
|
@ -35,7 +35,7 @@ enum class ByteOrderMark
|
|||
Utf8
|
||||
};
|
||||
|
||||
constexpr Array<EnumDesc<ByteOrderMark>, 2> enum_desc(ByteOrderMark)
|
||||
constexpr Array<EnumDesc<ByteOrderMark>, 2> enum_desc(Meta::Type<ByteOrderMark>)
|
||||
{
|
||||
return { {
|
||||
{ ByteOrderMark::None, "none" },
|
||||
|
|
|
@ -131,7 +131,7 @@ enum class Autoreload
|
|||
Ask
|
||||
};
|
||||
|
||||
constexpr Array<EnumDesc<Autoreload>, 5> enum_desc(Autoreload)
|
||||
constexpr Array<EnumDesc<Autoreload>, 5> enum_desc(Meta::Type<Autoreload>)
|
||||
{
|
||||
return { {
|
||||
{ Autoreload::Yes, "yes" },
|
||||
|
|
|
@ -43,17 +43,15 @@
|
|||
namespace Kakoune
|
||||
{
|
||||
|
||||
template<>
|
||||
struct option_type_name<TimestampedList<LineAndFlag>>
|
||||
StringView option_type_name(Meta::Type<TimestampedList<LineAndFlag>>)
|
||||
{
|
||||
static StringView name() { return "line-flags"; }
|
||||
};
|
||||
return "line-flags";
|
||||
}
|
||||
|
||||
template<>
|
||||
struct option_type_name<TimestampedList<RangeAndFace>>
|
||||
StringView option_type_name(Meta::Type<TimestampedList<RangeAndFace>>)
|
||||
{
|
||||
static StringView name() { return "range-faces"; }
|
||||
};
|
||||
return "range-faces";
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
19
src/enum.hh
19
src/enum.hh
|
@ -5,6 +5,7 @@
|
|||
#include "string.hh"
|
||||
#include "exception.hh"
|
||||
#include "containers.hh"
|
||||
#include "meta.hh"
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
@ -22,10 +23,10 @@ struct Array
|
|||
|
||||
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)
|
||||
{
|
||||
constexpr auto desc = enum_desc(Flags{});
|
||||
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
||||
String res;
|
||||
for (int i = 0; i < desc.size(); ++i)
|
||||
{
|
||||
|
@ -38,10 +39,10 @@ EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
|
|||
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)
|
||||
{
|
||||
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; });
|
||||
if (it != desc.end())
|
||||
return it->name.str();
|
||||
|
@ -49,10 +50,10 @@ EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
|
|||
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)
|
||||
{
|
||||
constexpr auto desc = enum_desc(Flags{});
|
||||
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
||||
flags = Flags{};
|
||||
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)
|
||||
{
|
||||
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; });
|
||||
if (it == desc.end())
|
||||
throw runtime_error(format("invalid enum value '{}'", str));
|
||||
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)
|
||||
{
|
||||
Flags res = Flags{};
|
||||
|
|
|
@ -134,7 +134,7 @@ enum class AutoInfo
|
|||
template<>
|
||||
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 { {
|
||||
{ AutoInfo::Command, "command"},
|
||||
|
|
|
@ -37,18 +37,18 @@ using InsertCompleterDescList = Vector<InsertCompleterDesc, MemoryDomain::Option
|
|||
String option_to_string(const 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 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
|
||||
{
|
||||
|
|
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;
|
||||
throw runtime_error{format("option '{}' already declared with different type or flags", name)};
|
||||
}
|
||||
String doc = docstring.empty() ? format("[{}]", option_type_name<T>::name())
|
||||
: format("[{}] - {}", option_type_name<T>::name(), docstring);
|
||||
String doc = docstring.empty() ? format("[{}]", option_type_name(Meta::Type<T>{}))
|
||||
: format("[{}] - {}", option_type_name(Meta::Type<T>{}), docstring);
|
||||
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});
|
||||
return *opts.back();
|
||||
|
|
|
@ -16,25 +16,22 @@
|
|||
namespace Kakoune
|
||||
{
|
||||
|
||||
template<typename T, typename = void> struct option_type_name;
|
||||
template<typename T> using void_t = void;
|
||||
template<typename T> using valid = std::true_type;
|
||||
|
||||
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>
|
||||
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(Enum{});
|
||||
auto name = enum_desc(Meta::Type<Enum>{});
|
||||
return type + "(" + join(name | transform(std::mem_fn(&EnumDesc<Enum>::name)), '|') + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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); }
|
||||
|
@ -44,7 +41,7 @@ inline bool option_add(int& opt, StringView str)
|
|||
opt += val;
|
||||
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 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
|
||||
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 = ':';
|
||||
|
||||
|
@ -101,10 +98,10 @@ bool option_add(Vector<T, domain>& opt, StringView str)
|
|||
}
|
||||
|
||||
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>
|
||||
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>
|
||||
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",
|
||||
option_type_name<K>::name(),
|
||||
option_type_name<V>::name()); }
|
||||
};
|
||||
return format("{}-to-{}-map", option_type_name(Meta::Type<K>{}),
|
||||
option_type_name(Meta::Type<V>{}));
|
||||
}
|
||||
|
||||
constexpr char tuple_separator = '|';
|
||||
|
||||
|
@ -251,7 +247,7 @@ enum class DebugFlags
|
|||
template<>
|
||||
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 { {
|
||||
{ DebugFlags::Hooks, "hooks" },
|
||||
|
|
Loading…
Reference in New Issue
Block a user