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(); - if (not (buffer.flags() & Buffer::Flags::File) or reload == No) + auto reload = context().options()["autoreload"].get(); + 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 m_last_buffer; }; +enum class Autoreload +{ + Yes, + No, + Ask +}; + +constexpr Array, 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 +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 struct EnumDesc { T value; StringView name; }; + +template +EnableIfWithBitOps 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 +EnableIfWithoutBitOps option_to_string(Enum e) +{ + constexpr auto desc = enum_desc(Enum{}); + auto it = find_if(desc, [e](const EnumDesc& d) { return d.value == e; }); + kak_assert(it != desc.end()); + return it->name.str(); +} + +template +EnableIfWithBitOps 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& d) { return d.name == s; }); + if (it == desc.end()) + throw runtime_error(format("invalid flag value '{}'", s)); + flags |= it->value; + } +} + +template +EnableIfWithoutBitOps option_from_string(StringView str, Enum& e) +{ + constexpr auto desc = enum_desc(Enum{}); + auto it = find_if(desc, [str](const EnumDesc& 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 using UnderlyingType = typename std::underlying_type::type; -template -using EnableIfWithBitOps = typename std::enable_if::value>::type; +template +using EnableIfWithBitOps = typename std::enable_if::value, T>::type; + +template +using EnableIfWithoutBitOps = typename std::enable_if::value, T>::type; template> 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 : std::true_type {}; + +constexpr Array, 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 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 = 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 #include @@ -192,101 +193,6 @@ inline String option_to_string(const LineAndColumn struct EnumInfo; - -template, - typename = decltype(EnumInfo::values(), EnumInfo::names())> -String option_to_string(Flags flags) -{ - auto names = EnumInfo::names(); - auto values = EnumInfo::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 = decltype(EnumInfo::values(), EnumInfo::names())> -void option_from_string(StringView str, Flags& flags) -{ - auto names = EnumInfo::names(); - auto values = EnumInfo::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 : std::true_type {}; - -template<> struct EnumInfo -{ - static ArrayView values() - { - static constexpr AutoInfo values[] = { AutoInfo::Command, AutoInfo::OnKey, AutoInfo::Normal }; - return { values }; - } - - static ArrayView 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 : std::true_type {}; -template<> struct EnumInfo +constexpr Array, 2> enum_desc(DebugFlags) { - static ArrayView values() - { - static constexpr DebugFlags values[] = { DebugFlags::Hooks, DebugFlags::Shell }; - return { values }; - } - - static ArrayView names() - { - static constexpr StringView names[] = { "hooks", "shell" }; - return { names }; - } -}; + return { { + { DebugFlags::Hooks, "hooks" }, + { DebugFlags::Shell, "shell" } + } }; +} }