From dfc11d1c43b898394df8fda52a8079b34058de27 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 23 Oct 2018 08:15:53 +1100 Subject: [PATCH] Refactor Hook management to have a well defined list of hooks Hooks are now an enum class instead of passing strings around. --- src/buffer.cc | 14 +++--- src/buffer.hh | 2 +- src/buffer_utils.cc | 6 +-- src/client.cc | 14 +++--- src/client_manager.cc | 2 +- src/commands.cc | 26 ++++------ src/constexpr_utils.hh | 4 ++ src/hook_manager.cc | 44 ++++++++--------- src/hook_manager.hh | 103 +++++++++++++++++++++++++++++++++++++--- src/input_handler.cc | 36 +++++++------- src/insert_completer.cc | 6 +-- src/main.cc | 4 +- src/scope.cc | 2 +- src/window.cc | 13 +++-- src/window.hh | 4 +- 15 files changed, 182 insertions(+), 98 deletions(-) diff --git a/src/buffer.cc b/src/buffer.cc index 8ef76a09..5d3702eb 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -114,16 +114,16 @@ void Buffer::on_registered() return; } - run_hook_in_own_context("BufCreate", m_name); + run_hook_in_own_context(Hook::BufCreate, m_name); if (m_flags & Flags::File) { if (m_flags & Buffer::Flags::New) - run_hook_in_own_context("BufNewFile", m_name); + run_hook_in_own_context(Hook::BufNewFile, m_name); else { kak_assert(m_fs_timestamp != InvalidTime); - run_hook_in_own_context("BufOpenFile", m_name); + run_hook_in_own_context(Hook::BufOpenFile, m_name); } } @@ -139,7 +139,7 @@ void Buffer::on_unregistered() return; options().unregister_watcher(*this); - run_hook_in_own_context("BufClose", m_name); + run_hook_in_own_context(Hook::BufClose, m_name); } Buffer::~Buffer() @@ -687,11 +687,11 @@ void Buffer::on_option_changed(const Option& option) else m_flags &= ~Flags::ReadOnly; } - run_hook_in_own_context("BufSetOption", + run_hook_in_own_context(Hook::BufSetOption, format("{}={}", option.name(), option.get_as_string(Quoting::Kakoune))); } -void Buffer::run_hook_in_own_context(StringView hook_name, StringView param, String client_name) +void Buffer::run_hook_in_own_context(Hook hook, StringView param, String client_name) { if (m_flags & Buffer::Flags::NoHooks) return; @@ -699,7 +699,7 @@ void Buffer::run_hook_in_own_context(StringView hook_name, StringView param, Str InputHandler hook_handler{{ *this, Selection{} }, Context::Flags::Draft, std::move(client_name)}; - hooks().run_hook(hook_name, param, hook_handler.context()); + hooks().run_hook(hook, param, hook_handler.context()); } Optional Buffer::last_modification_coord() const diff --git a/src/buffer.hh b/src/buffer.hh index 202469bb..0cdb8209 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -199,7 +199,7 @@ public: ValueMap& values() const { return m_values; } - void run_hook_in_own_context(StringView hook_name, StringView param, + void run_hook_in_own_context(Hook hook, StringView param, String client_name = {}); void reload(StringView data, timespec fs_timestamp = InvalidTime); diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc index 4a6e3816..c2c75da0 100644 --- a/src/buffer_utils.cc +++ b/src/buffer_utils.cc @@ -107,7 +107,7 @@ Buffer* create_fifo_buffer(String name, int fd, Buffer::Flags flags, bool scroll auto watcher_deleter = [buffer](FDWatcher* watcher) { kak_assert(buffer->flags() & Buffer::Flags::Fifo); watcher->close_fd(); - buffer->run_hook_in_own_context("BufCloseFifo", ""); + buffer->run_hook_in_own_context(Hook::BufCloseFifo, ""); buffer->flags() &= ~(Buffer::Flags::Fifo | Buffer::Flags::NoUndo); delete watcher; }; @@ -157,12 +157,12 @@ Buffer* create_fifo_buffer(String name, int fd, Buffer::Flags flags, bool scroll } while (--loops and fd_readable(fifo)); - buffer->run_hook_in_own_context("BufReadFifo", buffer->name()); + buffer->run_hook_in_own_context(Hook::BufReadFifo, buffer->name()); }), std::move(watcher_deleter)); buffer->values()[fifo_watcher_id] = Value(std::move(watcher)); buffer->flags() = flags | Buffer::Flags::Fifo | Buffer::Flags::NoUndo; - buffer->run_hook_in_own_context("BufOpenFifo", buffer->name()); + buffer->run_hook_in_own_context(Hook::BufOpenFifo, buffer->name()); return buffer; } diff --git a/src/client.cc b/src/client.cc index 44702331..f72cbac1 100644 --- a/src/client.cc +++ b/src/client.cc @@ -57,7 +57,7 @@ Client::Client(std::unique_ptr&& ui, m_pending_keys.push_back(key); }); - m_window->hooks().run_hook("WinDisplay", m_window->buffer().name(), context()); + m_window->hooks().run_hook(Hook::WinDisplay, m_window->buffer().name(), context()); force_redraw(); } @@ -91,20 +91,20 @@ bool Client::process_pending_inputs() context().name(), key_to_str(key))); if (key == Key::FocusIn) - context().hooks().run_hook("FocusIn", context().name(), context()); + context().hooks().run_hook(Hook::FocusIn, context().name(), context()); else if (key == Key::FocusOut) - context().hooks().run_hook("FocusOut", context().name(), context()); + context().hooks().run_hook(Hook::FocusOut, context().name(), context()); else m_input_handler.handle_key(key); - context().hooks().run_hook("RawKey", key_to_str(key), context()); + context().hooks().run_hook(Hook::RawKey, key_to_str(key), context()); } catch (Kakoune::runtime_error& error) { write_to_debug_buffer(format("Error: {}", error.what())); context().print_status({ fix_atom_text(error.what().str()), context().faces()["Error"] }); - context().hooks().run_hook("RuntimeError", error.what(), context()); + context().hooks().run_hook(Hook::RuntimeError, error.what(), context()); } } return not keys.empty(); @@ -188,7 +188,7 @@ void Client::change_buffer(Buffer& buffer) context().set_window(*m_window); m_window->set_dimensions(m_ui->dimensions()); - m_window->hooks().run_hook("WinDisplay", buffer.name(), context()); + m_window->hooks().run_hook(Hook::WinDisplay, buffer.name(), context()); force_redraw(); } @@ -284,7 +284,7 @@ void Client::reload_buffer() context().print_status({ format("'{}' reloaded", buffer.display_name()), context().faces()["Information"] }); - m_window->hooks().run_hook("BufReload", buffer.name(), context()); + m_window->hooks().run_hook(Hook::BufReload, buffer.name(), context()); } catch (runtime_error& error) { diff --git a/src/client_manager.cc b/src/client_manager.cc index 612d1753..18aa175f 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -67,7 +67,7 @@ Client* ClientManager::create_client(std::unique_ptr&& ui, int pi { client->context().print_status({ fix_atom_text(error.what().str()), client->context().faces()["Error"] }); - client->context().hooks().run_hook("RuntimeError", error.what(), + client->context().hooks().run_hook(Hook::RuntimeError, error.what(), client->context()); } diff --git a/src/commands.cc b/src/commands.cc index 15658ede..6c1ab1b5 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -344,9 +344,9 @@ void do_write_buffer(Context& context, Optional filename, bool sync_file auto effective_filename = not filename ? buffer.name() : parse_filename(*filename); - context.hooks().run_hook("BufWritePre", effective_filename, context); + context.hooks().run_hook(Hook::BufWritePre, effective_filename, context); write_buffer_to_file(buffer, effective_filename, force, sync_file); - context.hooks().run_hook("BufWritePost", effective_filename, context); + context.hooks().run_hook(Hook::BufWritePost, effective_filename, context); } template @@ -395,9 +395,9 @@ void write_all_buffers(Context& context, bool sync = false) buffer->is_modified()) and !(buffer->flags() & Buffer::Flags::ReadOnly)) { - buffer->run_hook_in_own_context("BufWritePre", buffer->name(), context.name()); + buffer->run_hook_in_own_context(Hook::BufWritePre, buffer->name(), context.name()); write_buffer_to_file(*buffer, buffer->name(), sync); - buffer->run_hook_in_own_context("BufWritePost", buffer->name(), context.name()); + buffer->run_hook_in_own_context(Hook::BufWritePost, buffer->name(), context.name()); } } } @@ -819,20 +819,10 @@ const CommandDesc remove_highlighter_cmd = { } }; -static constexpr auto hooks = { - "BufCreate", "BufNewFile", "BufOpenFile", "BufClose", "BufWritePost", "BufReload", - "BufWritePre", "BufOpenFifo", "BufCloseFifo", "BufReadFifo", "BufSetOption", - "InsertBegin", "InsertChar", "InsertDelete", "InsertEnd", "InsertIdle", "InsertKey", - "InsertMove", "InsertCompletionHide", "InsertCompletionShow", "InsertCompletionSelect", - "KakBegin", "KakEnd", "FocusIn", "FocusOut", "GlobalSetOption", "RuntimeError", "PromptIdle", - "NormalBegin", "NormalEnd", "NormalIdle", "NormalKey", "ModeChange", "RawKey", - "WinClose", "WinCreate", "WinDisplay", "WinResize", "WinSetOption", -}; - static Completions complete_hooks(const Context&, CompletionFlags, const String& prefix, ByteCount cursor_pos) { - return { 0_byte, cursor_pos, complete(prefix, cursor_pos, hooks) }; + return { 0_byte, cursor_pos, complete(prefix, cursor_pos, enum_desc(Meta::Type{}) | transform(&EnumDesc::name)) }; } const CommandDesc add_hook_cmd = { @@ -860,7 +850,9 @@ const CommandDesc add_hook_cmd = { context, flags, prefix, cursor_pos); }), [](const ParametersParser& parser, Context& context, const ShellContext&) { - if (not contains(hooks, parser[1])) + auto descs = enum_desc(Meta::Type{}); + auto it = find_if(descs, [&](const EnumDesc& desc) { return desc.name == parser[1]; }); + if (it == descs.end()) throw runtime_error{format("no such hook: '{}'", parser[1])}; Regex regex{parser[2], RegexCompileFlags::Optimize}; @@ -873,7 +865,7 @@ const CommandDesc add_hook_cmd = { const auto flags = (parser.get_switch("always") ? HookFlags::Always : HookFlags::None) | (parser.get_switch("once") ? HookFlags::Once : HookFlags::None); - get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(), flags, + get_scope(parser[0], context).hooks().add_hook(it->value, group.str(), flags, std::move(regex), command); } }; diff --git a/src/constexpr_utils.hh b/src/constexpr_utils.hh index b0d5643f..d9ba2abb 100644 --- a/src/constexpr_utils.hh +++ b/src/constexpr_utils.hh @@ -18,6 +18,10 @@ struct Array constexpr const T* begin() const { return m_data; } constexpr const T* end() const { return m_data+N; } + constexpr T& operator[](int i) { return m_data[i]; } + constexpr T* begin() { return m_data; } + constexpr T* end() { return m_data+N; } + constexpr operator ArrayView() { return {m_data, N}; } constexpr operator ConstArrayView() const { return {m_data, N}; } diff --git a/src/hook_manager.cc b/src/hook_manager.cc index 93a4fc1e..e55eb89e 100644 --- a/src/hook_manager.cc +++ b/src/hook_manager.cc @@ -14,7 +14,7 @@ namespace Kakoune { -struct HookManager::Hook +struct HookManager::HookData { String group; HookFlags flags; @@ -26,23 +26,23 @@ HookManager::HookManager() : m_parent(nullptr) {} HookManager::HookManager(HookManager& parent) : SafeCountable{}, m_parent(&parent) {} HookManager::~HookManager() = default; -void HookManager::add_hook(StringView hook_name, String group, HookFlags flags, Regex filter, String commands) +void HookManager::add_hook(Hook hook, String group, HookFlags flags, Regex filter, String commands) { - auto& hooks = m_hooks[hook_name]; - hooks.emplace_back(new Hook{std::move(group), flags, std::move(filter), std::move(commands)}); + auto& hooks = m_hooks[to_underlying(hook)]; + hooks.emplace_back(new HookData{std::move(group), flags, std::move(filter), std::move(commands)}); } void HookManager::remove_hooks(const Regex& regex) { for (auto& list : m_hooks) { - auto it = std::remove_if(list.value.begin(), list.value.end(), - [&](const std::unique_ptr& h) + auto it = std::remove_if(list.begin(), list.end(), + [&](const std::unique_ptr& h) { return regex_match(h->group.begin(), h->group.end(), regex); }); if (not m_running_hooks.empty()) // we are running some hooks, defer deletion m_hooks_trash.insert(m_hooks_trash.end(), std::make_move_iterator(it), - std::make_move_iterator(list.value.end())); - list.value.erase(it, list.value.end()); + std::make_move_iterator(list.end())); + list.erase(it, list.end()); } } @@ -51,7 +51,7 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_ CandidateList res; for (auto& list : m_hooks) { - auto container = list.value | transform([](const std::unique_ptr& h) -> const String& { return h->group; }); + auto container = list | transform([](const std::unique_ptr& h) -> const String& { return h->group; }); for (auto& c : complete(prefix, pos_in_token, container)) { if (!contains(res, c)) @@ -61,25 +61,23 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_ return res; } -void HookManager::run_hook(StringView hook_name, StringView param, Context& context) +void HookManager::run_hook(Hook hook, StringView param, Context& context) { const bool only_always = context.hooks_disabled(); if (m_parent) - m_parent->run_hook(hook_name, param, context); + m_parent->run_hook(hook, param, context); - auto hook_list = m_hooks.find(hook_name); - if (hook_list == m_hooks.end()) - return; - - if (contains(m_running_hooks, std::make_pair(hook_name, param))) + auto& hook_list = m_hooks[to_underlying(hook)]; + auto hook_name = enum_desc(Meta::Type{})[to_underlying(hook)].name; + if (contains(m_running_hooks, std::make_pair(hook, param))) { auto error = format("recursive call of hook {}/{}, not executing", hook_name, param); write_to_debug_buffer(error); return; } - m_running_hooks.emplace_back(hook_name, param); + m_running_hooks.emplace_back(hook, param); auto pop_running_hook = on_scope_end([this]{ m_running_hooks.pop_back(); if (m_running_hooks.empty()) @@ -92,9 +90,9 @@ void HookManager::run_hook(StringView hook_name, StringView param, Context& cont auto& disabled_hooks = context.options()["disabled_hooks"].get(); - struct ToRun { Hook* hook; MatchResults captures; }; + struct ToRun { HookData* hook; MatchResults captures; }; Vector hooks_to_run; // The m_hooks_trash vector ensure hooks wont die during this method - for (auto& hook : hook_list->value) + for (auto& hook : hook_list) { MatchResults captures; if ((not only_always or (hook->flags & HookFlags::Always)) and @@ -124,11 +122,11 @@ void HookManager::run_hook(StringView hook_name, StringView param, Context& cont if (to_run.hook->flags & HookFlags::Once) { - auto it = find(hook_list->value, to_run.hook); - if (it != hook_list->value.end()) + auto it = find(hook_list, to_run.hook); + if (it != hook_list.end()) { m_hooks_trash.push_back(std::move(*it)); - hook_list->value.erase(it); + hook_list.erase(it); } } } @@ -136,7 +134,7 @@ void HookManager::run_hook(StringView hook_name, StringView param, Context& cont { hook_error = true; write_to_debug_buffer(format("error running hook {}({})/{}: {}", - hook_name, param, to_run.hook->group, err.what())); + hook_name, param, to_run.hook->group, err.what())); } } diff --git a/src/hook_manager.hh b/src/hook_manager.hh index 6da5fe30..bae6cca4 100644 --- a/src/hook_manager.hh +++ b/src/hook_manager.hh @@ -4,6 +4,8 @@ #include "hash_map.hh" #include "completion.hh" #include "safe_ptr.hh" +#include "meta.hh" +#include "enum.hh" namespace Kakoune { @@ -11,6 +13,94 @@ namespace Kakoune class Context; class Regex; +enum class Hook +{ + BufCreate, + BufNewFile, + BufOpenFile, + BufClose, + BufWritePost, + BufReload, + BufWritePre, + BufOpenFifo, + BufCloseFifo, + BufReadFifo, + BufSetOption, + InsertBegin, + InsertChar, + InsertDelete, + InsertEnd, + InsertIdle, + InsertKey, + InsertMove, + InsertCompletionHide, + InsertCompletionShow, + InsertCompletionSelect, + KakBegin, + KakEnd, + FocusIn, + FocusOut, + GlobalSetOption, + RuntimeError, + PromptIdle, + NormalBegin, + NormalEnd, + NormalIdle, + NormalKey, + ModeChange, + RawKey, + WinClose, + WinCreate, + WinDisplay, + WinResize, + WinSetOption +}; + +constexpr auto enum_desc(Meta::Type) +{ + return make_array, 39>({ + {Hook::BufCreate, "BufCreate"}, + {Hook::BufNewFile, "BufNewFile"}, + {Hook::BufOpenFile, "BufOpenFile"}, + {Hook::BufClose, "BufClose"}, + {Hook::BufWritePost, "BufWritePost"}, + {Hook::BufReload, "BufReload"}, + {Hook::BufWritePre, "BufWritePre"}, + {Hook::BufOpenFifo, "BufOpenFifo"}, + {Hook::BufCloseFifo, "BufCloseFifo"}, + {Hook::BufReadFifo, "BufReadFifo"}, + {Hook::BufSetOption, "BufSetOption"}, + {Hook::InsertBegin, "InsertBegin"}, + {Hook::InsertChar, "InsertChar"}, + {Hook::InsertDelete, "InsertDelete"}, + {Hook::InsertEnd, "InsertEnd"}, + {Hook::InsertIdle, "InsertIdle"}, + {Hook::InsertKey, "InsertKey"}, + {Hook::InsertMove, "InsertMove"}, + {Hook::InsertCompletionHide, "InsertCompletionHide"}, + {Hook::InsertCompletionShow, "InsertCompletionShow"}, + {Hook::InsertCompletionSelect, "InsertCompletionSelect"}, + {Hook::KakBegin, "KakBegin"}, + {Hook::KakEnd, "KakEnd"}, + {Hook::FocusIn, "FocusIn"}, + {Hook::FocusOut, "FocusOut"}, + {Hook::GlobalSetOption, "GlobalSetOption"}, + {Hook::RuntimeError, "RuntimeError"}, + {Hook::PromptIdle, "PromptIdle"}, + {Hook::NormalBegin, "NormalBegin"}, + {Hook::NormalEnd, "NormalEnd"}, + {Hook::NormalIdle, "NormalIdle"}, + {Hook::NormalKey, "NormalKey"}, + {Hook::ModeChange, "ModeChange"}, + {Hook::RawKey, "RawKey"}, + {Hook::WinClose, "WinClose"}, + {Hook::WinCreate, "WinCreate"}, + {Hook::WinDisplay, "WinDisplay"}, + {Hook::WinResize, "WinResize"}, + {Hook::WinSetOption, "WinSetOption"}, + }); +} + enum class HookFlags { None = 0, @@ -25,25 +115,24 @@ public: HookManager(HookManager& parent); ~HookManager(); - void add_hook(StringView hook_name, String group, HookFlags flags, + void add_hook(Hook hook, String group, HookFlags flags, Regex filter, String commands); void remove_hooks(const Regex& regex); CandidateList complete_hook_group(StringView prefix, ByteCount pos_in_token); - void run_hook(StringView hook_name, StringView param, - Context& context); + void run_hook(Hook hook, StringView param, Context& context); private: HookManager(); // the only one allowed to construct a root hook manager friend class Scope; - struct Hook; + struct HookData; SafePtr m_parent; - HashMap, MemoryDomain::Hooks>, MemoryDomain::Hooks> m_hooks; + Array, MemoryDomain::Hooks>, enum_desc(Meta::Type{}).size()> m_hooks; - mutable Vector, MemoryDomain::Hooks> m_running_hooks; - mutable Vector, MemoryDomain::Hooks> m_hooks_trash; + mutable Vector, MemoryDomain::Hooks> m_running_hooks; + mutable Vector, MemoryDomain::Hooks> m_hooks_trash; }; } diff --git a/src/input_handler.cc b/src/input_handler.cc index b423f713..1964e116 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -166,7 +166,7 @@ public: m_idle_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ? Timer::Callback{} : [this](Timer&) { - context().hooks().run_hook("NormalIdle", "", context()); + context().hooks().run_hook(Hook::NormalIdle, "", context()); }}, m_fs_check_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ? @@ -198,7 +198,7 @@ public: m_hooks_disabled = false; } - context().hooks().run_hook("NormalBegin", "", context()); + context().hooks().run_hook(Hook::NormalBegin, "", context()); } void on_disabled(bool temporary) override @@ -212,7 +212,7 @@ public: m_hooks_disabled = false; } - context().hooks().run_hook("NormalEnd", "", context()); + context().hooks().run_hook(Hook::NormalEnd, "", context()); } void on_key(Key key) override @@ -314,7 +314,7 @@ public: } } - context().hooks().run_hook("NormalKey", key_to_str(key), context()); + context().hooks().run_hook(Hook::NormalKey, key_to_str(key), context()); if (enabled() and not transient) // The hook might have changed mode m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context())); } @@ -753,7 +753,7 @@ public: m_callback(m_line_editor.line(), PromptEvent::Change, context()); m_line_changed = false; } - context().hooks().run_hook("PromptIdle", "", context()); + context().hooks().run_hook(Hook::PromptIdle, "", context()); }}, m_line_editor{context().faces()} { @@ -1128,7 +1128,7 @@ public: m_idle_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ? Timer::Callback{} : [this](Timer&) { m_completer.update(m_auto_complete); - context().hooks().run_hook("InsertIdle", "", context()); + context().hooks().run_hook(Hook::InsertIdle, "", context()); }} { context().buffer().throw_if_read_only(); @@ -1138,7 +1138,7 @@ public: last_insert().keys.clear(); last_insert().disable_hooks = context().hooks_disabled(); last_insert().count = count; - context().hooks().run_hook("InsertBegin", "", context()); + context().hooks().run_hook(Hook::InsertBegin, "", context()); prepare(mode, count); } @@ -1185,7 +1185,7 @@ public: if (m_in_end) throw runtime_error("asked to exit insert mode while running InsertEnd hook"); m_in_end = true; - context().hooks().run_hook("InsertEnd", "", context()); + context().hooks().run_hook(Hook::InsertEnd, "", context()); m_completer.reset(); pop_mode(); @@ -1209,7 +1209,7 @@ public: SelectionList{buffer, std::move(sels)}.erase(); if (not main_char.empty()) - context().hooks().run_hook("InsertDelete", main_char, context()); + context().hooks().run_hook(Hook::InsertDelete, main_char, context()); } else if (key == Key::Delete) { @@ -1328,7 +1328,7 @@ public: if (auto cp = get_raw_codepoint(key)) { insert(*cp); - context().hooks().run_hook("InsertKey", key_to_str(key), context()); + context().hooks().run_hook(Hook::InsertKey, key_to_str(key), context()); if (enabled() and not transient) m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context())); } @@ -1341,9 +1341,9 @@ public: return; } - context().hooks().run_hook("InsertKey", key_to_str(key), context()); + context().hooks().run_hook(Hook::InsertKey, key_to_str(key), context()); if (moved) - context().hooks().run_hook("InsertMove", key_to_str(key), context()); + context().hooks().run_hook(Hook::InsertMove, key_to_str(key), context()); if (update_completions and enabled() and not transient) // Hooks might have disabled us m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context())); @@ -1386,7 +1386,7 @@ private: { String str{key}; context().selections().insert(str, InsertMode::InsertCursor); - context().hooks().run_hook("InsertChar", str, context()); + context().hooks().run_hook(Hook::InsertChar, str, context()); } void prepare(InsertMode mode, int count) @@ -1430,7 +1430,7 @@ private: } selections.set(std::move(new_sels), selections.main_index() * count + count - 1); - context().hooks().run_hook("InsertChar", "\n", context()); + context().hooks().run_hook(Hook::InsertChar, "\n", context()); break; } case InsertMode::OpenLineAbove: @@ -1448,7 +1448,7 @@ private: } selections.set(std::move(new_sels), selections.main_index() * count + count - 1); - context().hooks().run_hook("InsertChar", "\n", context()); + context().hooks().run_hook(Hook::InsertChar, "\n", context()); break; } case InsertMode::InsertAtLineBegin: @@ -1503,7 +1503,7 @@ void InputHandler::push_mode(InputMode* new_mode) m_mode_stack.emplace_back(new_mode); new_mode->on_enabled(); - context().hooks().run_hook("ModeChange", format("{}:{}", prev_name, new_mode->name()), context()); + context().hooks().run_hook(Hook::ModeChange, format("{}:{}", prev_name, new_mode->name()), context()); } void InputHandler::pop_mode(InputMode* mode) @@ -1517,7 +1517,7 @@ void InputHandler::pop_mode(InputMode* mode) m_mode_stack.pop_back(); current_mode().on_enabled(); - context().hooks().run_hook("ModeChange", format("{}:{}", prev_name, current_mode().name()), context()); + context().hooks().run_hook(Hook::ModeChange, format("{}:{}", prev_name, current_mode().name()), context()); } void InputHandler::reset_normal_mode() @@ -1531,7 +1531,7 @@ void InputHandler::reset_normal_mode() m_mode_stack.resize(1); current_mode().on_enabled(); - context().hooks().run_hook("ModeChange", format("{}:{}", prev_name, current_mode().name()), context()); + context().hooks().run_hook(Hook::ModeChange, format("{}:{}", prev_name, current_mode().name()), context()); } void InputHandler::insert(InsertMode mode, int count) diff --git a/src/insert_completer.cc b/src/insert_completer.cc index 3dbe699b..69641085 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -455,7 +455,7 @@ void InsertCompleter::select(int index, bool relative, Vector& keystrokes) { const auto param = (m_current_candidate == m_completions.candidates.size() - 1) ? StringView{} : candidate.completion; - m_context.hooks().run_hook("InsertCompletionSelect", param, m_context); + m_context.hooks().run_hook(Hook::InsertCompletionSelect, param, m_context); } } @@ -479,7 +479,7 @@ void InsertCompleter::reset() { m_context.client().menu_hide(); m_context.client().info_hide(); - m_context.hooks().run_hook("InsertCompletionHide", "", m_context); + m_context.hooks().run_hook(Hook::InsertCompletionHide, "", m_context); } } } @@ -536,7 +536,7 @@ void InsertCompleter::menu_show() m_context.client().menu_show(std::move(menu_entries), m_completions.begin, MenuStyle::Inline); m_context.client().menu_select(m_current_candidate); - m_context.hooks().run_hook("InsertCompletionShow", "", m_context); + m_context.hooks().run_hook(Hook::InsertCompletionShow, "", m_context); } void InsertCompleter::on_option_changed(const Option& opt) diff --git a/src/main.cc b/src/main.cc index 6fda5da6..3981011b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -674,7 +674,7 @@ int run_server(StringView session, StringView server_init, { Context empty_context{Context::EmptyContextFlag{}}; - global_scope.hooks().run_hook("KakBegin", session, empty_context); + global_scope.hooks().run_hook(Hook::KakBegin, session, empty_context); } if (not files.empty()) try @@ -776,7 +776,7 @@ int run_server(StringView session, StringView server_init, { Context empty_context{Context::EmptyContextFlag{}}; - global_scope.hooks().run_hook("KakEnd", "", empty_context); + global_scope.hooks().run_hook(Hook::KakEnd, "", empty_context); } return local_client_exit; diff --git a/src/scope.cc b/src/scope.cc index 2930be97..fab7ed0d 100644 --- a/src/scope.cc +++ b/src/scope.cc @@ -18,7 +18,7 @@ GlobalScope::~GlobalScope() void GlobalScope::on_option_changed(const Option& option) { Context empty_context{Context::EmptyContextFlag{}}; - hooks().run_hook("GlobalSetOption", + hooks().run_hook(Hook::GlobalSetOption, format("{}={}", option.name(), option.get_as_string(Quoting::Kakoune)), empty_context); } diff --git a/src/window.cc b/src/window.cc index de5a1b2a..1b814b8f 100644 --- a/src/window.cc +++ b/src/window.cc @@ -25,7 +25,7 @@ Window::Window(Buffer& buffer) m_buffer(&buffer), m_builtin_highlighters{highlighters()} { - run_hook_in_own_context("WinCreate", buffer.name()); + run_hook_in_own_context(Hook::WinCreate, buffer.name()); options().register_watcher(*this); @@ -40,7 +40,7 @@ Window::Window(Buffer& buffer) Window::~Window() { - run_hook_in_own_context("WinClose", buffer().name()); + run_hook_in_own_context(Hook::WinClose, buffer().name()); options().unregister_watcher(*this); } @@ -195,7 +195,7 @@ void Window::set_dimensions(DisplayCoord dimensions) if (m_dimensions != dimensions) { m_dimensions = dimensions; - run_hook_in_own_context("WinResize", format("{}.{}", dimensions.line, + run_hook_in_own_context(Hook::WinResize, format("{}.{}", dimensions.line, dimensions.column)); } } @@ -339,15 +339,14 @@ void Window::clear_display_buffer() void Window::on_option_changed(const Option& option) { - run_hook_in_own_context("WinSetOption", format("{}={}", option.name(), + run_hook_in_own_context(Hook::WinSetOption, format("{}={}", option.name(), option.get_as_string(Quoting::Kakoune))); // an highlighter might depend on the option, so we need to redraw force_redraw(); } -void Window::run_hook_in_own_context(StringView hook_name, StringView param, - String client_name) +void Window::run_hook_in_own_context(Hook hook, StringView param, String client_name) { if (m_buffer->flags() & Buffer::Flags::NoHooks) return; @@ -359,6 +358,6 @@ void Window::run_hook_in_own_context(StringView hook_name, StringView param, if (m_client) hook_handler.context().set_client(*m_client); - hooks().run_hook(hook_name, param, hook_handler.context()); + hooks().run_hook(hook, param, hook_handler.context()); } } diff --git a/src/window.hh b/src/window.hh index 0abca45d..cf7afebf 100644 --- a/src/window.hh +++ b/src/window.hh @@ -12,6 +12,8 @@ namespace Kakoune { +enum class Hook; + // A Window is a view onto a Buffer class Window final : public SafeCountable, public Scope, private OptionManagerWatcher { @@ -52,7 +54,7 @@ private: void on_option_changed(const Option& option) override; DisplaySetup compute_display_setup(const Context& context) const; - void run_hook_in_own_context(StringView hook_name, StringView param, + void run_hook_in_own_context(Hook hook, StringView param, String client_name = ""); SafePtr m_buffer;