From d57be835220b35e3a4630d0e79f027ef7b2bd545 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 5 Dec 2014 14:01:07 +0000 Subject: [PATCH] Disable history writing when running hooks --- src/commands.cc | 49 +++++++++++++++++++------------------------- src/context.hh | 24 ++++++++++++++++++++++ src/input_handler.cc | 6 ++++-- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index e9db2c05..de9aec62 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -551,6 +551,9 @@ const CommandDesc add_hook_cmd = { if (context.user_hooks_support().is_disabled()) return; + // Do not let hooks touch prompt history + ScopedDisable disable_history{context.history_support()}; + if (regex_match(param.begin(), param.end(), regex)) CommandManager::instance().execute(command, context, {}, { { "hook_param", param } }); @@ -1028,12 +1031,13 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func) { Buffer& buffer = BufferManager::instance().get_buffer(name); InputHandler input_handler{{ buffer, Selection{} }}; + Context& c = input_handler.context(); + // Propagate user hooks disabled status to the temporary context - if (disable_hooks) - input_handler.context().user_hooks_support().disable(); - if (disable_keymaps) - input_handler.context().keymaps_support().disable(); - func(parser, input_handler.context()); + ScopedDisable hook_disable(c.user_hooks_support(), disable_hooks); + ScopedDisable keymaps_disable(c.keymaps_support(), disable_keymaps); + + func(parser, c); } return; } @@ -1051,52 +1055,41 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func) if (parser.has_option("draft")) { InputHandler input_handler(real_context->selections(), real_context->name()); + Context& c = input_handler.context(); // We do not want this draft context to commit undo groups if the real one is // going to commit the whole thing later if (real_context->is_editing()) - input_handler.context().disable_undo_handling(); + c.disable_undo_handling(); - // Propagate user hooks disabled status to the temporary context - if (disable_hooks) - input_handler.context().user_hooks_support().disable(); - if (disable_keymaps) - input_handler.context().keymaps_support().disable(); + ScopedDisable hook_disable(c.user_hooks_support(), disable_hooks); + ScopedDisable keymaps_disable(c.keymaps_support(), disable_keymaps); if (parser.has_option("itersel")) { SelectionList sels{real_context->selections()}; - ScopedEdition edition{input_handler.context()}; + ScopedEdition edition{c}; for (auto& sel : sels) { - input_handler.context().selections() = SelectionList{ sels.buffer(), sel, sels.timestamp() }; - input_handler.context().selections().update(); + c.selections() = SelectionList{ sels.buffer(), sel, sels.timestamp() }; + c.selections().update(); - func(parser, input_handler.context()); + func(parser, c); - if (&sels.buffer() != &input_handler.context().buffer()) + if (&sels.buffer() != &c.buffer()) throw runtime_error("the buffer has changed while iterating on selections"); } } else - func(parser, input_handler.context()); + func(parser, c); } else { if (parser.has_option("itersel")) throw runtime_error("-itersel makes no sense without -draft"); - if (disable_hooks) - real_context->user_hooks_support().disable(); - if (disable_keymaps) - real_context->keymaps_support().disable(); - - auto restore = on_scope_end([&](){ - if (disable_hooks) - real_context->user_hooks_support().enable(); - if (disable_keymaps) - real_context->keymaps_support().enable(); - }); + ScopedDisable hook_disable(real_context->user_hooks_support(), disable_hooks); + ScopedDisable keymaps_disable(real_context->keymaps_support(), disable_keymaps); func(parser, *real_context); } diff --git a/src/context.hh b/src/context.hh index 104fb1a6..be602033 100644 --- a/src/context.hh +++ b/src/context.hh @@ -27,6 +27,26 @@ private: int m_disable_count = 0; }; +struct ScopedDisable +{ + ScopedDisable(Disableable& disableable, bool condition = true) + : m_disableable(disableable), m_condition(condition) + { + if (m_condition) + m_disableable.disable(); + } + + ~ScopedDisable() + { + if (m_condition) + m_disableable.enable(); + } + +private: + Disableable& m_disableable; + bool m_condition; +}; + // A Context is used to access non singleton objects for various services // in commands. // @@ -97,6 +117,9 @@ public: Disableable& keymaps_support() { return m_keymaps_support; } const Disableable& keymaps_support() const { return m_keymaps_support; } + Disableable& history_support() { return m_history_support; } + const Disableable& history_support() const { return m_history_support; } + private: void begin_edition(); void end_edition(); @@ -119,6 +142,7 @@ private: Disableable m_user_hooks_support; Disableable m_keymaps_support; + Disableable m_history_support; }; struct ScopedEdition diff --git a/src/input_handler.cc b/src/input_handler.cc index 9554bf35..23d5eb50 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -516,7 +516,8 @@ public: } else if (key == ctrl('m')) // enter { - history_push(history, line); + if (context().history_support().is_enabled()) + history_push(history, line); context().print_status(DisplayLine{}); if (context().has_ui()) context().ui().menu_hide(); @@ -528,7 +529,8 @@ public: } else if (key == Key::Escape or key == ctrl('c')) { - history_push(history, line); + if (context().history_support().is_enabled()) + history_push(history, line); context().print_status(DisplayLine{}); if (context().has_ui()) context().ui().menu_hide();