Move hook executing logic into HookManager
The existing HookManager was able to run arbitrary hook functions, but in practice was only used for user provided textual hooks. That separation was causing some suboptimal performances, by moving that logic directly in the hook manager we can improve hook filtering performance which is a big part of startup time when opening lots of files.
This commit is contained in:
parent
4606453fed
commit
f0285a8e60
|
@ -805,24 +805,8 @@ const CommandDesc add_hook_cmd = {
|
||||||
|
|
||||||
Regex regex{parser[2], Regex::optimize | Regex::ECMAScript};
|
Regex regex{parser[2], Regex::optimize | Regex::ECMAScript};
|
||||||
const String& command = parser[3];
|
const String& command = parser[3];
|
||||||
|
|
||||||
auto hook_func = [=](StringView param, Context& context) {
|
|
||||||
ScopedSetBool disable_history{context.history_disabled()};
|
|
||||||
|
|
||||||
MatchResults<const char*> res;
|
|
||||||
if (not regex_match(param.begin(), param.end(), res, regex))
|
|
||||||
return;
|
|
||||||
|
|
||||||
EnvVarMap env_vars{ {"hook_param", param.str()} };
|
|
||||||
for (size_t i = 0; i < res.size(); ++i)
|
|
||||||
env_vars.insert({format("hook_param_capture_{}", i),
|
|
||||||
{res[i].first, res[i].second}});
|
|
||||||
|
|
||||||
CommandManager::instance().execute(command, context,
|
|
||||||
{ {}, std::move(env_vars) });
|
|
||||||
};
|
|
||||||
auto group = parser.get_switch("group").value_or(StringView{});
|
auto group = parser.get_switch("group").value_or(StringView{});
|
||||||
get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(), std::move(hook_func));
|
get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(), std::move(regex), command);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,17 @@
|
||||||
#include "buffer_utils.hh"
|
#include "buffer_utils.hh"
|
||||||
#include "display_buffer.hh"
|
#include "display_buffer.hh"
|
||||||
#include "face_registry.hh"
|
#include "face_registry.hh"
|
||||||
|
#include "command_manager.hh"
|
||||||
#include "regex.hh"
|
#include "regex.hh"
|
||||||
#include "option.hh"
|
#include "option.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
void HookManager::add_hook(StringView hook_name, String group, HookFunc func)
|
void HookManager::add_hook(StringView hook_name, String group, Regex filter, String commands)
|
||||||
{
|
{
|
||||||
auto& hooks = m_hooks[hook_name];
|
auto& hooks = m_hooks[hook_name];
|
||||||
hooks.emplace_back(new Hook{std::move(group), std::move(func)});
|
hooks.emplace_back(new Hook{std::move(group), std::move(filter), {}, std::move(commands)});
|
||||||
}
|
}
|
||||||
|
|
||||||
void HookManager::remove_hooks(StringView group)
|
void HookManager::remove_hooks(StringView group)
|
||||||
|
@ -84,8 +85,9 @@ void HookManager::run_hook(StringView hook_name,
|
||||||
Vector<Hook*> hooks_to_run; // The m_hooks_trash vector ensure hooks wont die during this method
|
Vector<Hook*> 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->value)
|
||||||
{
|
{
|
||||||
if (hook->group.empty() or disabled_hooks.empty() or
|
if ((hook->group.empty() or disabled_hooks.empty() or
|
||||||
not regex_match(hook->group.begin(), hook->group.end(), disabled_hooks))
|
not regex_match(hook->group.begin(), hook->group.end(), disabled_hooks))
|
||||||
|
and regex_match(param.begin(), param.end(), hook->captures, hook->filter))
|
||||||
hooks_to_run.push_back(hook.get());
|
hooks_to_run.push_back(hook.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +98,16 @@ void HookManager::run_hook(StringView hook_name,
|
||||||
{
|
{
|
||||||
if (debug_flags & DebugFlags::Hooks)
|
if (debug_flags & DebugFlags::Hooks)
|
||||||
write_to_debug_buffer(format("hook {}({})/{}", hook_name, param, hook->group));
|
write_to_debug_buffer(format("hook {}({})/{}", hook_name, param, hook->group));
|
||||||
hook->func(param, context);
|
|
||||||
|
ScopedSetBool disable_history{context.history_disabled()};
|
||||||
|
|
||||||
|
EnvVarMap env_vars{ {"hook_param", param.str()} };
|
||||||
|
for (size_t i = 0; i < hook->captures.size(); ++i)
|
||||||
|
env_vars.insert({format("hook_param_capture_{}", i),
|
||||||
|
{hook->captures[i].first, hook->captures[i].second}});
|
||||||
|
|
||||||
|
CommandManager::instance().execute(hook->commands, context,
|
||||||
|
{ {}, std::move(env_vars) });
|
||||||
}
|
}
|
||||||
catch (runtime_error& err)
|
catch (runtime_error& err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,19 +4,19 @@
|
||||||
#include "hash_map.hh"
|
#include "hash_map.hh"
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
#include "safe_ptr.hh"
|
#include "safe_ptr.hh"
|
||||||
|
#include "regex.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
using HookFunc = std::function<void (StringView, Context&)>;
|
|
||||||
|
|
||||||
class HookManager : public SafeCountable
|
class HookManager : public SafeCountable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HookManager(HookManager& parent) : m_parent(&parent) {}
|
HookManager(HookManager& parent) : m_parent(&parent) {}
|
||||||
|
|
||||||
void add_hook(StringView hook_name, String group, HookFunc func);
|
void add_hook(StringView hook_name, String group, Regex filter, String commands);
|
||||||
void remove_hooks(StringView group);
|
void remove_hooks(StringView group);
|
||||||
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(StringView hook_name, StringView param,
|
||||||
|
@ -31,7 +31,9 @@ private:
|
||||||
struct Hook
|
struct Hook
|
||||||
{
|
{
|
||||||
String group;
|
String group;
|
||||||
HookFunc func;
|
Regex filter;
|
||||||
|
MatchResults<const char*> captures;
|
||||||
|
String commands;
|
||||||
};
|
};
|
||||||
|
|
||||||
SafePtr<HookManager> m_parent;
|
SafePtr<HookManager> m_parent;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user