Disable hooks on a per context basis, and propagate that to Insert mode

using \ before entering insert mode will disable hooks during the whole
insert session rather than only the entering phase. That gives a nice
way of pasting text into kakoune.
This commit is contained in:
Maxime Coste 2014-07-24 19:18:39 +01:00
parent 826bf22eef
commit 731277a425
5 changed files with 42 additions and 27 deletions

View File

@ -546,7 +546,7 @@ const CommandDesc add_hook_cmd = {
Regex regex(parser[2].begin(), parser[2].end());
String command = parser[3];
auto hook_func = [=](const String& param, Context& context) {
if (GlobalHooks::instance().are_user_hooks_disabled())
if (context.are_user_hooks_disabled())
return;
if (boost::regex_match(param.begin(), param.end(), regex))
@ -1002,18 +1002,13 @@ struct DisableOption {
template<typename Func>
void context_wrap(const ParametersParser& parser, Context& context, Func func)
{
const bool disable_hooks = parser.has_option("no-hooks");
if (disable_hooks)
GlobalHooks::instance().disable_user_hooks();
auto restore_hooks = on_scope_end([&](){
if (disable_hooks)
GlobalHooks::instance().enable_user_hooks();
});
// Disable these options to avoid costly code paths (and potential screen
// redraws) That are useful only in interactive contexts.
DisableOption<int> disable_autoinfo(context, "autoinfo");
DisableOption<bool> disable_autoshowcompl(context, "autoshowcompl");
DisableOption<bool> disable_incsearch(context, "incsearch");
const bool disable_hooks = parser.has_option("no-hooks") or context.are_user_hooks_disabled();
ClientManager& cm = ClientManager::instance();
if (parser.has_option("buffer"))
@ -1023,6 +1018,9 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func)
{
Buffer& buffer = BufferManager::instance().get_buffer(name);
InputHandler input_handler{{ buffer, Selection{} }};
// Propagate user hooks disabled status to the temporary context
if (disable_hooks)
input_handler.context().disable_user_hooks();
func(parser, input_handler.context());
}
return;
@ -1047,6 +1045,10 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func)
if (real_context->is_editing())
input_handler.context().disable_undo_handling();
// Propagate user hooks disabled status to the temporary context
if (disable_hooks)
input_handler.context().disable_user_hooks();
if (parser.has_option("itersel"))
{
SelectionList sels{real_context->selections()};
@ -1069,6 +1071,14 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func)
{
if (parser.has_option("itersel"))
throw runtime_error("-itersel makes no sense without -draft");
if (disable_hooks)
real_context->disable_user_hooks();
auto restore_hooks = on_scope_end([&](){
if (disable_hooks)
real_context->enable_user_hooks();
});
func(parser, *real_context);
}

View File

@ -75,6 +75,12 @@ public:
bool is_editing() const { return m_edition_level!= 0; }
void disable_undo_handling() { m_edition_level = -1; }
bool are_user_hooks_disabled() const { return m_user_hooks_disabled; }
void disable_user_hooks() { ++m_user_hooks_disabled; }
void enable_user_hooks() { --m_user_hooks_disabled; }
private:
void begin_edition();
void end_edition();
@ -94,6 +100,8 @@ private:
using JumpList = std::vector<SelectionList>;
JumpList m_jump_list;
JumpList::iterator m_current_jump = m_jump_list.begin();
int m_user_hooks_disabled = 0;
};
struct ScopedEdition

View File

@ -59,11 +59,4 @@ void HookManager::run_hook(const String& hook_name,
}
}
bool GlobalHooks::are_user_hooks_disabled() const
{
kak_assert(m_disabled >= 0);
return m_disabled > 0;
}
}

View File

@ -36,13 +36,6 @@ private:
class GlobalHooks : public HookManager,
public Singleton<GlobalHooks>
{
public:
bool are_user_hooks_disabled() const;
void disable_user_hooks() { ++m_disabled; }
void enable_user_hooks() { --m_disabled; }
private:
int m_disabled = 0;
};
}

View File

@ -86,12 +86,14 @@ public:
auto restore_hooks = on_scope_end([&, this]{
if (do_restore_hooks)
{
GlobalHooks::instance().enable_user_hooks();
context().enable_user_hooks();
m_disable_hooks = false;
}
});
context().print_status({}); // clear status line
context().print_status({});
if (context().has_ui())
context().ui().info_hide();
if (key.modifiers == Key::Modifiers::None and isdigit(key.key))
m_count = m_count * 10 + key.key - '0';
@ -103,7 +105,7 @@ public:
{
if (m_disable_hooks)
{
GlobalHooks::instance().disable_user_hooks();
context().disable_user_hooks();
do_restore_hooks = true;
}
auto it = keymap.find(key);
@ -663,8 +665,13 @@ public:
[this](Timer& timer) {
context().hooks().run_hook("InsertIdle", "", context());
m_completer.update();
}}
}},
m_disable_hooks{context().are_user_hooks_disabled()}
{
// Prolongate hook disabling for the whole insert session
if (m_disable_hooks)
context().disable_user_hooks();
last_insert().first = mode;
last_insert().second.clear();
context().hooks().run_hook("InsertBegin", "", context());
@ -886,6 +893,9 @@ private:
sel.cursor() = context().buffer().char_prev(sel.cursor());
}
selections.avoid_eol();
if (m_disable_hooks)
context().enable_user_hooks();
}
enum class Mode { Default, Complete, InsertReg };
@ -894,6 +904,7 @@ private:
ScopedEdition m_edition;
InsertCompleter m_completer;
Timer m_idle_timer;
bool m_disable_hooks;
};
}