Refactor Hook management to have a well defined list of hooks

Hooks are now an enum class instead of passing strings around.
This commit is contained in:
Maxime Coste 2018-10-23 08:15:53 +11:00
parent e399bf7562
commit dfc11d1c43
15 changed files with 182 additions and 98 deletions

View File

@ -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<BufferCoord> Buffer::last_modification_coord() const

View File

@ -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);

View File

@ -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;
}

View File

@ -57,7 +57,7 @@ Client::Client(std::unique_ptr<UserInterface>&& 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)
{

View File

@ -67,7 +67,7 @@ Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& 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());
}

View File

@ -344,9 +344,9 @@ void do_write_buffer(Context& context, Optional<String> 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<bool force = false>
@ -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<Hook>{}) | transform(&EnumDesc<Hook>::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<Hook>{});
auto it = find_if(descs, [&](const EnumDesc<Hook>& 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);
}
};

View File

@ -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<T>() { return {m_data, N}; }
constexpr operator ConstArrayView<T>() const { return {m_data, N}; }

View File

@ -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<Hook>& h)
auto it = std::remove_if(list.begin(), list.end(),
[&](const std::unique_ptr<HookData>& 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<Hook>& h) -> const String& { return h->group; });
auto container = list | transform([](const std::unique_ptr<HookData>& 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<Hook>{})[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<Regex>();
struct ToRun { Hook* hook; MatchResults<const char*> captures; };
struct ToRun { HookData* hook; MatchResults<const char*> captures; };
Vector<ToRun> 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<const char*> 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);
}
}
}

View File

@ -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<Hook>)
{
return make_array<EnumDesc<Hook>, 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<HookManager> m_parent;
HashMap<String, Vector<std::unique_ptr<Hook>, MemoryDomain::Hooks>, MemoryDomain::Hooks> m_hooks;
Array<Vector<std::unique_ptr<HookData>, MemoryDomain::Hooks>, enum_desc(Meta::Type<Hook>{}).size()> m_hooks;
mutable Vector<std::pair<StringView, StringView>, MemoryDomain::Hooks> m_running_hooks;
mutable Vector<std::unique_ptr<Hook>, MemoryDomain::Hooks> m_hooks_trash;
mutable Vector<std::pair<Hook, StringView>, MemoryDomain::Hooks> m_running_hooks;
mutable Vector<std::unique_ptr<HookData>, MemoryDomain::Hooks> m_hooks_trash;
};
}

View File

@ -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)

View File

@ -455,7 +455,7 @@ void InsertCompleter::select(int index, bool relative, Vector<Key>& 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)

View File

@ -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;

View File

@ -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);
}

View File

@ -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());
}
}

View File

@ -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<Buffer> m_buffer;