summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrank LENORMAND <lenormf@gmail.com>2018-08-02 12:52:48 +0300
committerFrank LENORMAND <lenormf@gmail.com>2018-08-06 15:14:20 +0300
commite84dcf72c0e525da8a2d2580488f76b08743752b (patch)
tree3bd775e67f1ae9178cc4aaecb51b0dc986158b9c /src
parentae75032936ed9ffa2bf14589fef115d3d684a7c6 (diff)
src: Allow hooks to be run only once
This commit implements the -once flag on the `:hook` command, which automatically removes a hook after it was run, to avoid having to declare a group and remove it in the hook implementation. Closes #2277
Diffstat (limited to 'src')
-rw-r--r--src/commands.cc9
-rw-r--r--src/hook_manager.cc14
-rw-r--r--src/hook_manager.hh5
3 files changed, 20 insertions, 8 deletions
diff --git a/src/commands.cc b/src/commands.cc
index dcee0281..f8a3e4dc 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -842,7 +842,8 @@ const CommandDesc add_hook_cmd = {
" * window: hook is executed only for the current window\n",
ParameterDesc{
{ { "group", { true, "set hook group, see remove-hooks" } },
- { "always", { false, "run hook even if hooks are disabled" } }},
+ { "always", { false, "run hook even if hooks are disabled" } },
+ { "once", { false, "run the hook only once" } } },
ParameterDesc::Flags::None, 4, 4
},
CommandFlags::None,
@@ -860,9 +861,9 @@ const CommandDesc add_hook_cmd = {
Regex regex{parser[2], RegexCompileFlags::Optimize};
const String& command = parser[3];
auto group = parser.get_switch("group").value_or(StringView{});
- get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(),
- 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);
+ get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(), flags,
std::move(regex), command);
}
};
diff --git a/src/hook_manager.cc b/src/hook_manager.cc
index 378756c0..8dabb66a 100644
--- a/src/hook_manager.cc
+++ b/src/hook_manager.cc
@@ -63,7 +63,7 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_
return res;
}
-void HookManager::run_hook(StringView hook_name, StringView param, Context& context) const
+void HookManager::run_hook(StringView hook_name, StringView param, Context& context)
{
const bool only_always = context.hooks_disabled();
@@ -99,7 +99,7 @@ void HookManager::run_hook(StringView hook_name, StringView param, Context& cont
for (auto& hook : hook_list->value)
{
MatchResults<const char*> captures;
- if ((not only_always or (hook->flags & HookFlags::Always)) and
+ if ((not only_always or (hook->flags & HookFlags::Always)) and
(hook->group.empty() or disabled_hooks.empty() or
not regex_match(hook->group.begin(), hook->group.end(), disabled_hooks))
and regex_match(param.begin(), param.end(), captures, hook->filter))
@@ -123,6 +123,16 @@ void HookManager::run_hook(StringView hook_name, StringView param, Context& cont
CommandManager::instance().execute(to_run.hook->commands, context,
{ {}, std::move(env_vars) });
+
+ if (to_run.hook->flags & HookFlags::Once)
+ {
+ auto it = std::find_if(hook_list->value.begin(), hook_list->value.end(),
+ [&](const std::unique_ptr<Hook>& h)
+ { return h.get() == to_run.hook; });
+
+ m_hooks_trash.push_back(std::move(*it));
+ hook_list->value.erase(it);
+ }
}
catch (runtime_error& err)
{
diff --git a/src/hook_manager.hh b/src/hook_manager.hh
index 44fb9107..9e75c086 100644
--- a/src/hook_manager.hh
+++ b/src/hook_manager.hh
@@ -14,7 +14,8 @@ class Regex;
enum class HookFlags
{
None = 0,
- Always = 1 << 0
+ Always = 1 << 0,
+ Once = 1 << 1
};
constexpr bool with_bit_ops(Meta::Type<HookFlags>) { return true; }
@@ -29,7 +30,7 @@ public:
void remove_hooks(StringView group);
CandidateList complete_hook_group(StringView prefix, ByteCount pos_in_token);
void run_hook(StringView hook_name, StringView param,
- Context& context) const;
+ Context& context);
private:
HookManager();