From 107e95622d910309ab2c324583f216cee9fd926b Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 11 Apr 2013 14:29:10 +0200 Subject: [PATCH] Hooks can have an (shareable) identifier, and thus be removed --- src/commands.cc | 39 +++++++++++++++++++++++---------------- src/hook_manager.cc | 18 ++++++++++++++---- src/hook_manager.hh | 6 ++++-- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index 02f816f4..68f7bdfd 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -73,7 +73,7 @@ Buffer* open_fifo(const String& name , const String& filename, Context& context) } }); - buffer->hooks().add_hook("BufClose", + buffer->hooks().add_hook("BufClose", "", [buffer, watcher](const String&, const Context&) { // Check if fifo is still alive, else watcher is already dead if (buffer->flags() & Buffer::Flags::Fifo) @@ -313,30 +313,36 @@ void rm_filter(const CommandParameters& params, Context& context) group.remove(parser[0]); } +static HookManager& get_hook_manager(const String& scope, Context& context) +{ + if (scope == "global") + return GlobalHooks::instance(); + else if (scope == "buffer") + return context.buffer().hooks(); + else if (scope == "window") + return context.window().hooks(); + throw runtime_error("error: no such hook container " + scope); +} + void add_hook(const CommandParameters& params, Context& context) { - if (params.size() != 4) - throw wrong_argument_count(); - + ParametersParser parser(params, { { "id", true } }, ParametersParser::Flags::None, 4, 4); // copy so that the lambda gets a copy as well - Regex regex(params[2].begin(), params[2].end()); - String command = params[3]; + Regex regex(parser[2].begin(), parser[2].end()); + String command = parser[3]; auto hook_func = [=](const String& param, Context& context) { if (boost::regex_match(param.begin(), param.end(), regex)) CommandManager::instance().execute(command, context, {}, { { "hook_param", param } }); }; + String id = parser.has_option("id") ? parser.option_value("id") : ""; + get_hook_manager(parser[0], context).add_hook(parser[1], id, hook_func); +} - const String& scope = params[0]; - const String& name = params[1]; - if (scope == "global") - GlobalHooks::instance().add_hook(name, hook_func); - else if (scope == "buffer") - context.buffer().hooks().add_hook(name, hook_func); - else if (scope == "window") - context.window().hooks().add_hook(name , hook_func); - else - throw runtime_error("error: no such hook container " + scope); +void rm_hooks(const CommandParameters& params, Context& context) +{ + ParametersParser parser(params, {}, ParametersParser::Flags::None, 2, 2); + get_hook_manager(parser[0], context).remove_hooks(parser[1]); } EnvVarMap params_to_env_var_map(const CommandParameters& params) @@ -895,6 +901,7 @@ void register_commands() cm.register_commands({ "rf", "rmfilter" }, rm_filter, group_rm_completer(get_filters)); cm.register_command("hook", add_hook); + cm.register_command("rmhooks", rm_hooks); cm.register_command("source", exec_commands_in_file, filename_completer); diff --git a/src/hook_manager.cc b/src/hook_manager.cc index 5eae3fc9..344b6ce0 100644 --- a/src/hook_manager.cc +++ b/src/hook_manager.cc @@ -5,9 +5,18 @@ namespace Kakoune { -void HookManager::add_hook(const String& hook_name, HookFunc hook) +void HookManager::add_hook(const String& hook_name, String id, HookFunc hook) { - m_hook[hook_name].push_back(hook); + auto& hooks = m_hook[hook_name]; + hooks.append({std::move(id), std::move(hook)}); +} + +void HookManager::remove_hooks(const String& id) +{ + if (id.empty()) + throw runtime_error("invalid id"); + for (auto& hooks : m_hook) + hooks.second.remove_all(id); } void HookManager::run_hook(const String& hook_name, @@ -25,11 +34,12 @@ void HookManager::run_hook(const String& hook_name, { try { - hook(param, context); + hook.second(param, context); } catch (runtime_error& err) { - write_debug("error running hook " + hook_name + ": " + err.what()); + write_debug("error running hook " + hook_name + "/" + + hook.first + ": " + err.what()); } } } diff --git a/src/hook_manager.hh b/src/hook_manager.hh index 3fcc0b74..c5b0e152 100644 --- a/src/hook_manager.hh +++ b/src/hook_manager.hh @@ -1,6 +1,7 @@ #ifndef hook_manager_hh_INCLUDED #define hook_manager_hh_INCLUDED +#include "idvaluemap.hh" #include "utils.hh" #include @@ -16,7 +17,8 @@ class HookManager public: HookManager(HookManager& parent) : m_parent(&parent) {} - void add_hook(const String& hook_name, HookFunc hook); + void add_hook(const String& hook_name, String id, HookFunc hook); + void remove_hooks(const String& id); void run_hook(const String& hook_name, const String& param, Context& context) const; @@ -27,7 +29,7 @@ private: friend class GlobalHooks; HookManager* m_parent; - std::unordered_map> m_hook; + std::unordered_map> m_hook; }; class GlobalHooks : public HookManager,