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:
parent
e399bf7562
commit
dfc11d1c43
|
@ -114,16 +114,16 @@ void Buffer::on_registered()
|
||||||
return;
|
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 & Flags::File)
|
||||||
{
|
{
|
||||||
if (m_flags & Buffer::Flags::New)
|
if (m_flags & Buffer::Flags::New)
|
||||||
run_hook_in_own_context("BufNewFile", m_name);
|
run_hook_in_own_context(Hook::BufNewFile, m_name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kak_assert(m_fs_timestamp != InvalidTime);
|
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;
|
return;
|
||||||
|
|
||||||
options().unregister_watcher(*this);
|
options().unregister_watcher(*this);
|
||||||
run_hook_in_own_context("BufClose", m_name);
|
run_hook_in_own_context(Hook::BufClose, m_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer()
|
Buffer::~Buffer()
|
||||||
|
@ -687,11 +687,11 @@ void Buffer::on_option_changed(const Option& option)
|
||||||
else
|
else
|
||||||
m_flags &= ~Flags::ReadOnly;
|
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)));
|
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)
|
if (m_flags & Buffer::Flags::NoHooks)
|
||||||
return;
|
return;
|
||||||
|
@ -699,7 +699,7 @@ void Buffer::run_hook_in_own_context(StringView hook_name, StringView param, Str
|
||||||
InputHandler hook_handler{{ *this, Selection{} },
|
InputHandler hook_handler{{ *this, Selection{} },
|
||||||
Context::Flags::Draft,
|
Context::Flags::Draft,
|
||||||
std::move(client_name)};
|
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
|
Optional<BufferCoord> Buffer::last_modification_coord() const
|
||||||
|
|
|
@ -199,7 +199,7 @@ public:
|
||||||
|
|
||||||
ValueMap& values() const { return m_values; }
|
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 = {});
|
String client_name = {});
|
||||||
|
|
||||||
void reload(StringView data, timespec fs_timestamp = InvalidTime);
|
void reload(StringView data, timespec fs_timestamp = InvalidTime);
|
||||||
|
|
|
@ -107,7 +107,7 @@ Buffer* create_fifo_buffer(String name, int fd, Buffer::Flags flags, bool scroll
|
||||||
auto watcher_deleter = [buffer](FDWatcher* watcher) {
|
auto watcher_deleter = [buffer](FDWatcher* watcher) {
|
||||||
kak_assert(buffer->flags() & Buffer::Flags::Fifo);
|
kak_assert(buffer->flags() & Buffer::Flags::Fifo);
|
||||||
watcher->close_fd();
|
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);
|
buffer->flags() &= ~(Buffer::Flags::Fifo | Buffer::Flags::NoUndo);
|
||||||
delete watcher;
|
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));
|
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));
|
}), std::move(watcher_deleter));
|
||||||
|
|
||||||
buffer->values()[fifo_watcher_id] = Value(std::move(watcher));
|
buffer->values()[fifo_watcher_id] = Value(std::move(watcher));
|
||||||
buffer->flags() = flags | Buffer::Flags::Fifo | Buffer::Flags::NoUndo;
|
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;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ Client::Client(std::unique_ptr<UserInterface>&& ui,
|
||||||
m_pending_keys.push_back(key);
|
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();
|
force_redraw();
|
||||||
}
|
}
|
||||||
|
@ -91,20 +91,20 @@ bool Client::process_pending_inputs()
|
||||||
context().name(), key_to_str(key)));
|
context().name(), key_to_str(key)));
|
||||||
|
|
||||||
if (key == Key::FocusIn)
|
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)
|
else if (key == Key::FocusOut)
|
||||||
context().hooks().run_hook("FocusOut", context().name(), context());
|
context().hooks().run_hook(Hook::FocusOut, context().name(), context());
|
||||||
else
|
else
|
||||||
m_input_handler.handle_key(key);
|
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)
|
catch (Kakoune::runtime_error& error)
|
||||||
{
|
{
|
||||||
write_to_debug_buffer(format("Error: {}", error.what()));
|
write_to_debug_buffer(format("Error: {}", error.what()));
|
||||||
context().print_status({ fix_atom_text(error.what().str()),
|
context().print_status({ fix_atom_text(error.what().str()),
|
||||||
context().faces()["Error"] });
|
context().faces()["Error"] });
|
||||||
context().hooks().run_hook("RuntimeError", error.what(), context());
|
context().hooks().run_hook(Hook::RuntimeError, error.what(), context());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return not keys.empty();
|
return not keys.empty();
|
||||||
|
@ -188,7 +188,7 @@ void Client::change_buffer(Buffer& buffer)
|
||||||
context().set_window(*m_window);
|
context().set_window(*m_window);
|
||||||
m_window->set_dimensions(m_ui->dimensions());
|
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();
|
force_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ void Client::reload_buffer()
|
||||||
context().print_status({ format("'{}' reloaded", buffer.display_name()),
|
context().print_status({ format("'{}' reloaded", buffer.display_name()),
|
||||||
context().faces()["Information"] });
|
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)
|
catch (runtime_error& error)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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().print_status({ fix_atom_text(error.what().str()),
|
||||||
client->context().faces()["Error"] });
|
client->context().faces()["Error"] });
|
||||||
client->context().hooks().run_hook("RuntimeError", error.what(),
|
client->context().hooks().run_hook(Hook::RuntimeError, error.what(),
|
||||||
client->context());
|
client->context());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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);
|
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>
|
template<bool force = false>
|
||||||
|
@ -395,9 +395,9 @@ void write_all_buffers(Context& context, bool sync = false)
|
||||||
buffer->is_modified())
|
buffer->is_modified())
|
||||||
and !(buffer->flags() & Buffer::Flags::ReadOnly))
|
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);
|
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,
|
static Completions complete_hooks(const Context&, CompletionFlags,
|
||||||
const String& prefix, ByteCount cursor_pos)
|
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 = {
|
const CommandDesc add_hook_cmd = {
|
||||||
|
@ -860,7 +850,9 @@ const CommandDesc add_hook_cmd = {
|
||||||
context, flags, prefix, cursor_pos); }),
|
context, flags, prefix, cursor_pos); }),
|
||||||
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
[](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])};
|
throw runtime_error{format("no such hook: '{}'", parser[1])};
|
||||||
|
|
||||||
Regex regex{parser[2], RegexCompileFlags::Optimize};
|
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) |
|
const auto flags = (parser.get_switch("always") ? HookFlags::Always : HookFlags::None) |
|
||||||
(parser.get_switch("once") ? HookFlags::Once : 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);
|
std::move(regex), command);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,10 @@ struct Array
|
||||||
constexpr const T* begin() const { return m_data; }
|
constexpr const T* begin() const { return m_data; }
|
||||||
constexpr const T* end() const { return m_data+N; }
|
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 ArrayView<T>() { return {m_data, N}; }
|
||||||
constexpr operator ConstArrayView<T>() const { return {m_data, N}; }
|
constexpr operator ConstArrayView<T>() const { return {m_data, N}; }
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
struct HookManager::Hook
|
struct HookManager::HookData
|
||||||
{
|
{
|
||||||
String group;
|
String group;
|
||||||
HookFlags flags;
|
HookFlags flags;
|
||||||
|
@ -26,23 +26,23 @@ HookManager::HookManager() : m_parent(nullptr) {}
|
||||||
HookManager::HookManager(HookManager& parent) : SafeCountable{}, m_parent(&parent) {}
|
HookManager::HookManager(HookManager& parent) : SafeCountable{}, m_parent(&parent) {}
|
||||||
HookManager::~HookManager() = default;
|
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];
|
auto& hooks = m_hooks[to_underlying(hook)];
|
||||||
hooks.emplace_back(new Hook{std::move(group), flags, std::move(filter), std::move(commands)});
|
hooks.emplace_back(new HookData{std::move(group), flags, std::move(filter), std::move(commands)});
|
||||||
}
|
}
|
||||||
|
|
||||||
void HookManager::remove_hooks(const Regex& regex)
|
void HookManager::remove_hooks(const Regex& regex)
|
||||||
{
|
{
|
||||||
for (auto& list : m_hooks)
|
for (auto& list : m_hooks)
|
||||||
{
|
{
|
||||||
auto it = std::remove_if(list.value.begin(), list.value.end(),
|
auto it = std::remove_if(list.begin(), list.end(),
|
||||||
[&](const std::unique_ptr<Hook>& h)
|
[&](const std::unique_ptr<HookData>& h)
|
||||||
{ return regex_match(h->group.begin(), h->group.end(), regex); });
|
{ return regex_match(h->group.begin(), h->group.end(), regex); });
|
||||||
if (not m_running_hooks.empty()) // we are running some hooks, defer deletion
|
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),
|
m_hooks_trash.insert(m_hooks_trash.end(), std::make_move_iterator(it),
|
||||||
std::make_move_iterator(list.value.end()));
|
std::make_move_iterator(list.end()));
|
||||||
list.value.erase(it, list.value.end());
|
list.erase(it, list.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_
|
||||||
CandidateList res;
|
CandidateList res;
|
||||||
for (auto& list : m_hooks)
|
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))
|
for (auto& c : complete(prefix, pos_in_token, container))
|
||||||
{
|
{
|
||||||
if (!contains(res, c))
|
if (!contains(res, c))
|
||||||
|
@ -61,25 +61,23 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_
|
||||||
return res;
|
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();
|
const bool only_always = context.hooks_disabled();
|
||||||
|
|
||||||
if (m_parent)
|
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);
|
auto& hook_list = m_hooks[to_underlying(hook)];
|
||||||
if (hook_list == m_hooks.end())
|
auto hook_name = enum_desc(Meta::Type<Hook>{})[to_underlying(hook)].name;
|
||||||
return;
|
if (contains(m_running_hooks, std::make_pair(hook, param)))
|
||||||
|
|
||||||
if (contains(m_running_hooks, std::make_pair(hook_name, param)))
|
|
||||||
{
|
{
|
||||||
auto error = format("recursive call of hook {}/{}, not executing", hook_name, param);
|
auto error = format("recursive call of hook {}/{}, not executing", hook_name, param);
|
||||||
write_to_debug_buffer(error);
|
write_to_debug_buffer(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_running_hooks.emplace_back(hook_name, param);
|
m_running_hooks.emplace_back(hook, param);
|
||||||
auto pop_running_hook = on_scope_end([this]{
|
auto pop_running_hook = on_scope_end([this]{
|
||||||
m_running_hooks.pop_back();
|
m_running_hooks.pop_back();
|
||||||
if (m_running_hooks.empty())
|
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>();
|
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
|
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;
|
MatchResults<const char*> captures;
|
||||||
if ((not only_always or (hook->flags & HookFlags::Always)) and
|
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)
|
if (to_run.hook->flags & HookFlags::Once)
|
||||||
{
|
{
|
||||||
auto it = find(hook_list->value, to_run.hook);
|
auto it = find(hook_list, to_run.hook);
|
||||||
if (it != hook_list->value.end())
|
if (it != hook_list.end())
|
||||||
{
|
{
|
||||||
m_hooks_trash.push_back(std::move(*it));
|
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;
|
hook_error = true;
|
||||||
write_to_debug_buffer(format("error running hook {}({})/{}: {}",
|
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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "hash_map.hh"
|
#include "hash_map.hh"
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
#include "safe_ptr.hh"
|
#include "safe_ptr.hh"
|
||||||
|
#include "meta.hh"
|
||||||
|
#include "enum.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -11,6 +13,94 @@ namespace Kakoune
|
||||||
class Context;
|
class Context;
|
||||||
class Regex;
|
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
|
enum class HookFlags
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
@ -25,25 +115,24 @@ public:
|
||||||
HookManager(HookManager& parent);
|
HookManager(HookManager& parent);
|
||||||
~HookManager();
|
~HookManager();
|
||||||
|
|
||||||
void add_hook(StringView hook_name, String group, HookFlags flags,
|
void add_hook(Hook hook, String group, HookFlags flags,
|
||||||
Regex filter, String commands);
|
Regex filter, String commands);
|
||||||
void remove_hooks(const Regex& regex);
|
void remove_hooks(const Regex& regex);
|
||||||
CandidateList complete_hook_group(StringView prefix, ByteCount pos_in_token);
|
CandidateList complete_hook_group(StringView prefix, ByteCount pos_in_token);
|
||||||
void run_hook(StringView hook_name, StringView param,
|
void run_hook(Hook hook, StringView param, Context& context);
|
||||||
Context& context);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HookManager();
|
HookManager();
|
||||||
// the only one allowed to construct a root hook manager
|
// the only one allowed to construct a root hook manager
|
||||||
friend class Scope;
|
friend class Scope;
|
||||||
|
|
||||||
struct Hook;
|
struct HookData;
|
||||||
|
|
||||||
SafePtr<HookManager> m_parent;
|
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::pair<Hook, StringView>, MemoryDomain::Hooks> m_running_hooks;
|
||||||
mutable Vector<std::unique_ptr<Hook>, MemoryDomain::Hooks> m_hooks_trash;
|
mutable Vector<std::unique_ptr<HookData>, MemoryDomain::Hooks> m_hooks_trash;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ public:
|
||||||
m_idle_timer{TimePoint::max(),
|
m_idle_timer{TimePoint::max(),
|
||||||
context().flags() & Context::Flags::Draft ?
|
context().flags() & Context::Flags::Draft ?
|
||||||
Timer::Callback{} : [this](Timer&) {
|
Timer::Callback{} : [this](Timer&) {
|
||||||
context().hooks().run_hook("NormalIdle", "", context());
|
context().hooks().run_hook(Hook::NormalIdle, "", context());
|
||||||
}},
|
}},
|
||||||
m_fs_check_timer{TimePoint::max(),
|
m_fs_check_timer{TimePoint::max(),
|
||||||
context().flags() & Context::Flags::Draft ?
|
context().flags() & Context::Flags::Draft ?
|
||||||
|
@ -198,7 +198,7 @@ public:
|
||||||
m_hooks_disabled = false;
|
m_hooks_disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
context().hooks().run_hook("NormalBegin", "", context());
|
context().hooks().run_hook(Hook::NormalBegin, "", context());
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_disabled(bool temporary) override
|
void on_disabled(bool temporary) override
|
||||||
|
@ -212,7 +212,7 @@ public:
|
||||||
m_hooks_disabled = false;
|
m_hooks_disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
context().hooks().run_hook("NormalEnd", "", context());
|
context().hooks().run_hook(Hook::NormalEnd, "", context());
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_key(Key key) override
|
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
|
if (enabled() and not transient) // The hook might have changed mode
|
||||||
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
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_callback(m_line_editor.line(), PromptEvent::Change, context());
|
||||||
m_line_changed = false;
|
m_line_changed = false;
|
||||||
}
|
}
|
||||||
context().hooks().run_hook("PromptIdle", "", context());
|
context().hooks().run_hook(Hook::PromptIdle, "", context());
|
||||||
}},
|
}},
|
||||||
m_line_editor{context().faces()}
|
m_line_editor{context().faces()}
|
||||||
{
|
{
|
||||||
|
@ -1128,7 +1128,7 @@ public:
|
||||||
m_idle_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ?
|
m_idle_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ?
|
||||||
Timer::Callback{} : [this](Timer&) {
|
Timer::Callback{} : [this](Timer&) {
|
||||||
m_completer.update(m_auto_complete);
|
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();
|
context().buffer().throw_if_read_only();
|
||||||
|
@ -1138,7 +1138,7 @@ public:
|
||||||
last_insert().keys.clear();
|
last_insert().keys.clear();
|
||||||
last_insert().disable_hooks = context().hooks_disabled();
|
last_insert().disable_hooks = context().hooks_disabled();
|
||||||
last_insert().count = count;
|
last_insert().count = count;
|
||||||
context().hooks().run_hook("InsertBegin", "", context());
|
context().hooks().run_hook(Hook::InsertBegin, "", context());
|
||||||
prepare(mode, count);
|
prepare(mode, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1185,7 +1185,7 @@ public:
|
||||||
if (m_in_end)
|
if (m_in_end)
|
||||||
throw runtime_error("asked to exit insert mode while running InsertEnd hook");
|
throw runtime_error("asked to exit insert mode while running InsertEnd hook");
|
||||||
m_in_end = true;
|
m_in_end = true;
|
||||||
context().hooks().run_hook("InsertEnd", "", context());
|
context().hooks().run_hook(Hook::InsertEnd, "", context());
|
||||||
|
|
||||||
m_completer.reset();
|
m_completer.reset();
|
||||||
pop_mode();
|
pop_mode();
|
||||||
|
@ -1209,7 +1209,7 @@ public:
|
||||||
SelectionList{buffer, std::move(sels)}.erase();
|
SelectionList{buffer, std::move(sels)}.erase();
|
||||||
|
|
||||||
if (not main_char.empty())
|
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)
|
else if (key == Key::Delete)
|
||||||
{
|
{
|
||||||
|
@ -1328,7 +1328,7 @@ public:
|
||||||
if (auto cp = get_raw_codepoint(key))
|
if (auto cp = get_raw_codepoint(key))
|
||||||
{
|
{
|
||||||
insert(*cp);
|
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)
|
if (enabled() and not transient)
|
||||||
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
||||||
}
|
}
|
||||||
|
@ -1341,9 +1341,9 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context().hooks().run_hook("InsertKey", key_to_str(key), context());
|
context().hooks().run_hook(Hook::InsertKey, key_to_str(key), context());
|
||||||
if (moved)
|
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
|
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()));
|
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
||||||
|
@ -1386,7 +1386,7 @@ private:
|
||||||
{
|
{
|
||||||
String str{key};
|
String str{key};
|
||||||
context().selections().insert(str, InsertMode::InsertCursor);
|
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)
|
void prepare(InsertMode mode, int count)
|
||||||
|
@ -1430,7 +1430,7 @@ private:
|
||||||
}
|
}
|
||||||
selections.set(std::move(new_sels),
|
selections.set(std::move(new_sels),
|
||||||
selections.main_index() * count + count - 1);
|
selections.main_index() * count + count - 1);
|
||||||
context().hooks().run_hook("InsertChar", "\n", context());
|
context().hooks().run_hook(Hook::InsertChar, "\n", context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case InsertMode::OpenLineAbove:
|
case InsertMode::OpenLineAbove:
|
||||||
|
@ -1448,7 +1448,7 @@ private:
|
||||||
}
|
}
|
||||||
selections.set(std::move(new_sels),
|
selections.set(std::move(new_sels),
|
||||||
selections.main_index() * count + count - 1);
|
selections.main_index() * count + count - 1);
|
||||||
context().hooks().run_hook("InsertChar", "\n", context());
|
context().hooks().run_hook(Hook::InsertChar, "\n", context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case InsertMode::InsertAtLineBegin:
|
case InsertMode::InsertAtLineBegin:
|
||||||
|
@ -1503,7 +1503,7 @@ void InputHandler::push_mode(InputMode* new_mode)
|
||||||
m_mode_stack.emplace_back(new_mode);
|
m_mode_stack.emplace_back(new_mode);
|
||||||
new_mode->on_enabled();
|
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)
|
void InputHandler::pop_mode(InputMode* mode)
|
||||||
|
@ -1517,7 +1517,7 @@ void InputHandler::pop_mode(InputMode* mode)
|
||||||
m_mode_stack.pop_back();
|
m_mode_stack.pop_back();
|
||||||
current_mode().on_enabled();
|
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()
|
void InputHandler::reset_normal_mode()
|
||||||
|
@ -1531,7 +1531,7 @@ void InputHandler::reset_normal_mode()
|
||||||
m_mode_stack.resize(1);
|
m_mode_stack.resize(1);
|
||||||
current_mode().on_enabled();
|
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)
|
void InputHandler::insert(InsertMode mode, int count)
|
||||||
|
|
|
@ -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) ?
|
const auto param = (m_current_candidate == m_completions.candidates.size() - 1) ?
|
||||||
StringView{} : candidate.completion;
|
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().menu_hide();
|
||||||
m_context.client().info_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,
|
m_context.client().menu_show(std::move(menu_entries), m_completions.begin,
|
||||||
MenuStyle::Inline);
|
MenuStyle::Inline);
|
||||||
m_context.client().menu_select(m_current_candidate);
|
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)
|
void InsertCompleter::on_option_changed(const Option& opt)
|
||||||
|
|
|
@ -674,7 +674,7 @@ int run_server(StringView session, StringView server_init,
|
||||||
|
|
||||||
{
|
{
|
||||||
Context empty_context{Context::EmptyContextFlag{}};
|
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
|
if (not files.empty()) try
|
||||||
|
@ -776,7 +776,7 @@ int run_server(StringView session, StringView server_init,
|
||||||
|
|
||||||
{
|
{
|
||||||
Context empty_context{Context::EmptyContextFlag{}};
|
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;
|
return local_client_exit;
|
||||||
|
|
|
@ -18,7 +18,7 @@ GlobalScope::~GlobalScope()
|
||||||
void GlobalScope::on_option_changed(const Option& option)
|
void GlobalScope::on_option_changed(const Option& option)
|
||||||
{
|
{
|
||||||
Context empty_context{Context::EmptyContextFlag{}};
|
Context empty_context{Context::EmptyContextFlag{}};
|
||||||
hooks().run_hook("GlobalSetOption",
|
hooks().run_hook(Hook::GlobalSetOption,
|
||||||
format("{}={}", option.name(), option.get_as_string(Quoting::Kakoune)),
|
format("{}={}", option.name(), option.get_as_string(Quoting::Kakoune)),
|
||||||
empty_context);
|
empty_context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ Window::Window(Buffer& buffer)
|
||||||
m_buffer(&buffer),
|
m_buffer(&buffer),
|
||||||
m_builtin_highlighters{highlighters()}
|
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);
|
options().register_watcher(*this);
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ Window::Window(Buffer& buffer)
|
||||||
|
|
||||||
Window::~Window()
|
Window::~Window()
|
||||||
{
|
{
|
||||||
run_hook_in_own_context("WinClose", buffer().name());
|
run_hook_in_own_context(Hook::WinClose, buffer().name());
|
||||||
options().unregister_watcher(*this);
|
options().unregister_watcher(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ void Window::set_dimensions(DisplayCoord dimensions)
|
||||||
if (m_dimensions != dimensions)
|
if (m_dimensions != dimensions)
|
||||||
{
|
{
|
||||||
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));
|
dimensions.column));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,15 +339,14 @@ void Window::clear_display_buffer()
|
||||||
|
|
||||||
void Window::on_option_changed(const Option& option)
|
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)));
|
option.get_as_string(Quoting::Kakoune)));
|
||||||
// an highlighter might depend on the option, so we need to redraw
|
// an highlighter might depend on the option, so we need to redraw
|
||||||
force_redraw();
|
force_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Window::run_hook_in_own_context(StringView hook_name, StringView param,
|
void Window::run_hook_in_own_context(Hook hook, StringView param, String client_name)
|
||||||
String client_name)
|
|
||||||
{
|
{
|
||||||
if (m_buffer->flags() & Buffer::Flags::NoHooks)
|
if (m_buffer->flags() & Buffer::Flags::NoHooks)
|
||||||
return;
|
return;
|
||||||
|
@ -359,6 +358,6 @@ void Window::run_hook_in_own_context(StringView hook_name, StringView param,
|
||||||
if (m_client)
|
if (m_client)
|
||||||
hook_handler.context().set_client(*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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum class Hook;
|
||||||
|
|
||||||
// A Window is a view onto a Buffer
|
// A Window is a view onto a Buffer
|
||||||
class Window final : public SafeCountable, public Scope, private OptionManagerWatcher
|
class Window final : public SafeCountable, public Scope, private OptionManagerWatcher
|
||||||
{
|
{
|
||||||
|
@ -52,7 +54,7 @@ private:
|
||||||
void on_option_changed(const Option& option) override;
|
void on_option_changed(const Option& option) override;
|
||||||
DisplaySetup compute_display_setup(const Context& context) const;
|
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 = "");
|
String client_name = "");
|
||||||
|
|
||||||
SafePtr<Buffer> m_buffer;
|
SafePtr<Buffer> m_buffer;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user