diff options
| -rw-r--r-- | src/client.cc | 6 | ||||
| -rw-r--r-- | src/client.hh | 19 | ||||
| -rw-r--r-- | src/enum.hh | 76 | ||||
| -rw-r--r-- | src/flags.hh | 7 | ||||
| -rw-r--r-- | src/input_handler.hh | 20 | ||||
| -rw-r--r-- | src/main.cc | 2 | ||||
| -rw-r--r-- | src/option_types.hh | 115 |
7 files changed, 131 insertions, 114 deletions
diff --git a/src/client.cc b/src/client.cc index 79d1df7a..ec7f3ce8 100644 --- a/src/client.cc +++ b/src/client.cc @@ -236,15 +236,15 @@ void Client::check_if_buffer_needs_reloading() return; Buffer& buffer = context().buffer(); - auto reload = context().options()["autoreload"].get<YesNoAsk>(); - if (not (buffer.flags() & Buffer::Flags::File) or reload == No) + auto reload = context().options()["autoreload"].get<Autoreload>(); + if (not (buffer.flags() & Buffer::Flags::File) or reload == Autoreload::No) return; const String& filename = buffer.name(); timespec ts = get_fs_timestamp(filename); if (ts == InvalidTime or ts == buffer.fs_timestamp()) return; - if (reload == Ask) + if (reload == Autoreload::Ask) { m_ui->info_show( format("reload '{}' ?", buffer.display_name()), diff --git a/src/client.hh b/src/client.hh index f16bd09b..7a0c8571 100644 --- a/src/client.hh +++ b/src/client.hh @@ -7,6 +7,7 @@ #include "safe_ptr.hh" #include "utils.hh" #include "option_manager.hh" +#include "enum.hh" namespace Kakoune { @@ -84,6 +85,24 @@ private: SafePtr<Buffer> m_last_buffer; }; +enum class Autoreload +{ + Yes, + No, + Ask +}; + +constexpr Array<EnumDesc<Autoreload>, 5> enum_desc(Autoreload) +{ + return { { + { Autoreload::Yes, "yes" }, + { Autoreload::No, "no" }, + { Autoreload::Ask, "ask" }, + { Autoreload::Yes, "true" }, + { Autoreload::No, "false" } + } }; +} + } #endif // client_hh_INCLUDED diff --git a/src/enum.hh b/src/enum.hh new file mode 100644 index 00000000..af532391 --- /dev/null +++ b/src/enum.hh @@ -0,0 +1,76 @@ +#ifndef enum_hh_INCLUDED +#define enum_hh_INCLUDED + +#include "flags.hh" +#include "string.hh" +#include "exception.hh" +#include "containers.hh" + +namespace Kakoune +{ + +template<typename T, size_t N> +struct Array +{ + constexpr size_t size() const { return N; } + constexpr const T& operator[](int i) const { return m_data[i]; } + constexpr const T* begin() const { return m_data; } + constexpr const T* end() const { return m_data+N; } + + T m_data[N]; +}; + +template<typename T> struct EnumDesc { T value; StringView name; }; + +template<typename Flags, typename = decltype(enum_desc(Flags{}))> +EnableIfWithBitOps<Flags, String> option_to_string(Flags flags) +{ + constexpr auto desc = enum_desc(Flags{}); + String res; + for (int i = 0; i < desc.size(); ++i) + { + if (not (flags & desc[i].value)) + continue; + if (not res.empty()) + res += "|"; + res += desc[i].name; + } + return res; +} + +template<typename Enum, typename = decltype(enum_desc(Enum{}))> +EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e) +{ + constexpr auto desc = enum_desc(Enum{}); + auto it = find_if(desc, [e](const EnumDesc<Enum>& d) { return d.value == e; }); + kak_assert(it != desc.end()); + return it->name.str(); +} + +template<typename Flags, typename = decltype(enum_desc(Flags{}))> +EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags) +{ + constexpr auto desc = enum_desc(Flags{}); + flags = Flags{}; + for (auto s : split(str, '|')) + { + auto it = find_if(desc, [s](const EnumDesc<Flags>& d) { return d.name == s; }); + if (it == desc.end()) + throw runtime_error(format("invalid flag value '{}'", s)); + flags |= it->value; + } +} + +template<typename Enum, typename = decltype(enum_desc(Enum{}))> +EnableIfWithoutBitOps<Enum> option_from_string(StringView str, Enum& e) +{ + constexpr auto desc = enum_desc(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; +} + +} + +#endif // enum_hh_INCLUDED diff --git a/src/flags.hh b/src/flags.hh index 2b68751b..6b72ba05 100644 --- a/src/flags.hh +++ b/src/flags.hh @@ -12,8 +12,11 @@ struct WithBitOps : std::false_type {}; template<typename Flags> using UnderlyingType = typename std::underlying_type<Flags>::type; -template<typename Flags> -using EnableIfWithBitOps = typename std::enable_if<WithBitOps<Flags>::value>::type; +template<typename Flags, typename T = void> +using EnableIfWithBitOps = typename std::enable_if<WithBitOps<Flags>::value, T>::type; + +template<typename Flags, typename T = void> +using EnableIfWithoutBitOps = typename std::enable_if<not WithBitOps<Flags>::value, T>::type; template<typename Flags, typename = EnableIfWithBitOps<Flags>> constexpr Flags operator|(Flags lhs, Flags rhs) diff --git a/src/input_handler.hh b/src/input_handler.hh index 49767eb4..036633dc 100644 --- a/src/input_handler.hh +++ b/src/input_handler.hh @@ -103,6 +103,26 @@ private: int m_handle_key_level = 0; }; +enum class AutoInfo +{ + None = 0, + Command = 1 << 0, + OnKey = 1 << 1, + Normal = 1 << 2 +}; + +template<> +struct WithBitOps<AutoInfo> : std::true_type {}; + +constexpr Array<EnumDesc<AutoInfo>, 3> enum_desc(AutoInfo) +{ + return { { + { AutoInfo::Command, "command"}, + { AutoInfo::OnKey, "onkey"}, + { AutoInfo::Normal, "normal" } + } }; +} + bool show_auto_info_ifn(StringView title, StringView info, AutoInfo mask, const Context& context); template<typename Cmd> diff --git a/src/main.cc b/src/main.cc index 5dc3d854..83d9519b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -224,7 +224,7 @@ void register_options() }), OptionFlags::None); reg.declare_option("autoreload", "autoreload buffer when a filesystem modification is detected", - Ask); + Autoreload::Ask); reg.declare_option("ui_options", "colon separated list of <key>=<value> options that are " "passed to and interpreted by the user interface\n" diff --git a/src/option_types.hh b/src/option_types.hh index 2dda3d7e..f95c61f0 100644 --- a/src/option_types.hh +++ b/src/option_types.hh @@ -8,6 +8,7 @@ #include "array_view.hh" #include "id_map.hh" #include "flags.hh" +#include "enum.hh" #include <tuple> #include <vector> @@ -192,101 +193,6 @@ inline String option_to_string(const LineAndColumn<EffectiveType, LineType, Colu return format("{},{}", opt.line, opt.column); } -enum YesNoAsk -{ - Yes, - No, - Ask -}; - -inline String option_to_string(YesNoAsk opt) -{ - switch (opt) - { - case Yes: return "yes"; - case No: return "no"; - case Ask: return "ask"; - } - kak_assert(false); - return "ask"; -} - -inline void option_from_string(StringView str, YesNoAsk& opt) -{ - if (str == "yes" or str == "true") - opt = Yes; - else if (str == "no" or str == "false") - opt = No; - else if (str == "ask") - opt = Ask; - else - throw runtime_error(format("invalid value '{}', expected yes, no or ask", str)); -} - -template<typename T> struct EnumInfo; - -template<typename Flags, - typename = EnableIfWithBitOps<Flags>, - typename = decltype(EnumInfo<Flags>::values(), EnumInfo<Flags>::names())> -String option_to_string(Flags flags) -{ - auto names = EnumInfo<Flags>::names(); - auto values = EnumInfo<Flags>::values(); - String res; - for (int i = 0; i < values.size(); ++i) - { - if (not (flags & values[i])) - continue; - if (not res.empty()) - res += "|"; - res += names[i]; - } - return res; -} - -template<typename Flags, - typename = EnableIfWithBitOps<Flags>, - typename = decltype(EnumInfo<Flags>::values(), EnumInfo<Flags>::names())> -void option_from_string(StringView str, Flags& flags) -{ - auto names = EnumInfo<Flags>::names(); - auto values = EnumInfo<Flags>::values(); - flags = Flags{}; - for (auto s : split(str, '|')) - { - auto it = std::find(names.begin(), names.end(), s); - if (it == names.end()) - throw runtime_error(format("invalid flag value '{}'", s)); - flags |= values[it - names.begin()]; - } -} - -enum class AutoInfo -{ - None = 0, - Command = 1 << 0, - OnKey = 1 << 1, - Normal = 1 << 2 -}; - -template<> -struct WithBitOps<AutoInfo> : std::true_type {}; - -template<> struct EnumInfo<AutoInfo> -{ - static ArrayView<const AutoInfo> values() - { - static constexpr AutoInfo values[] = { AutoInfo::Command, AutoInfo::OnKey, AutoInfo::Normal }; - return { values }; - } - - static ArrayView<const StringView> names() - { - static constexpr StringView names[] = { "command", "onkey", "normal" }; - return { names }; - } -}; - enum class DebugFlags { None = 0, @@ -297,20 +203,13 @@ enum class DebugFlags template<> struct WithBitOps<DebugFlags> : std::true_type {}; -template<> struct EnumInfo<DebugFlags> +constexpr Array<EnumDesc<DebugFlags>, 2> enum_desc(DebugFlags) { - static ArrayView<const DebugFlags> values() - { - static constexpr DebugFlags values[] = { DebugFlags::Hooks, DebugFlags::Shell }; - return { values }; - } - - static ArrayView<const StringView> names() - { - static constexpr StringView names[] = { "hooks", "shell" }; - return { names }; - } -}; + return { { + { DebugFlags::Hooks, "hooks" }, + { DebugFlags::Shell, "shell" } + } }; +} } |
