Hooks can have an (shareable) identifier, and thus be removed

This commit is contained in:
Maxime Coste 2013-04-11 14:29:10 +02:00
parent 172f46f679
commit 107e95622d
3 changed files with 41 additions and 22 deletions

View File

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

View File

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

View File

@ -1,6 +1,7 @@
#ifndef hook_manager_hh_INCLUDED
#define hook_manager_hh_INCLUDED
#include "idvaluemap.hh"
#include "utils.hh"
#include <unordered_map>
@ -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<String, std::vector<HookFunc>> m_hook;
std::unordered_map<String, idvaluemap<String, HookFunc>> m_hook;
};
class GlobalHooks : public HookManager,