diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2016-03-22 22:54:29 +0000 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2016-03-22 22:54:29 +0000 |
| commit | 5bf92430064a5136dba51402bd852398cee7e994 (patch) | |
| tree | a146fff9cb74b25a7e00a90eaa2c4afe3d451001 | |
| parent | c1c17db5e9a3bc62f2023bbf355b9031837ee7f4 (diff) | |
User mappings and :exec are always executed in normal mode
Fix #551
| -rw-r--r-- | src/commands.cc | 4 | ||||
| -rw-r--r-- | src/input_handler.cc | 29 | ||||
| -rw-r--r-- | src/input_handler.hh | 11 | ||||
| -rw-r--r-- | src/normal.cc | 3 |
4 files changed, 46 insertions, 1 deletions
diff --git a/src/commands.cc b/src/commands.cc index 8eb676ba..d92f3ee9 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -1405,7 +1405,7 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func) const CommandDesc exec_string_cmd = { "exec", nullptr, - "exec <switches> <keys>: execute given keys as if entered by user", + "exec <switches> <keys>: execute given keys in normal mode as if entered by user", context_wrap_params, CommandFlags::None, CommandHelper{}, @@ -1420,6 +1420,8 @@ const CommandDesc exec_string_cmd = { keys.insert(keys.end(), param_keys.begin(), param_keys.end()); } + InputHandler::ScopedForceNormal force_normal{context.input_handler()}; + ScopedEdition edition(context); for (auto& key : keys) context.input_handler().handle_key(key); diff --git a/src/input_handler.cc b/src/input_handler.cc index 0dbd5ddc..874601c2 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -1325,6 +1325,35 @@ void InputHandler::on_next_key(KeymapMode keymap_mode, KeyCallback callback) push_mode(new InputModes::NextKey(*this, keymap_mode, callback)); } +InputHandler::ScopedForceNormal::ScopedForceNormal(InputHandler& handler) + : m_handler(handler), m_mode(nullptr) +{ + if (handler.m_mode_stack.size() == 1) + return; + + handler.push_mode(new InputModes::Normal(handler)); + m_mode = handler.m_mode_stack.back().get(); +} + +InputHandler::ScopedForceNormal::~ScopedForceNormal() +{ + if (not m_mode) + return; + + kak_assert(m_handler.m_mode_stack.size() > 1); + + if (m_mode == m_handler.m_mode_stack.back().get()) + m_handler.pop_mode(m_mode); + else + { + auto it = find_if(m_handler.m_mode_stack, + [this](const RefPtr<InputMode>& m) + { return m.get() == m_mode; }); + kak_assert(it != m_handler.m_mode_stack.end()); + m_handler.m_mode_stack.erase(it); + } +} + static bool is_valid(Key key) { return key != Key::Invalid and diff --git a/src/input_handler.hh b/src/input_handler.hh index 8719ca15..41397b28 100644 --- a/src/input_handler.hh +++ b/src/input_handler.hh @@ -82,6 +82,17 @@ public: DisplayLine mode_line() const; + // Force an input handler into normal mode temporarily + struct ScopedForceNormal + { + ScopedForceNormal(InputHandler& handler); + ~ScopedForceNormal(); + + private: + InputHandler& m_handler; + InputMode* m_mode; + }; + private: Context m_context; diff --git a/src/normal.cc b/src/normal.cc index 5f5fb177..ab08da9b 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1456,6 +1456,9 @@ void exec_user_mappings(Context& context, NormalParams params) auto mapping = context.keymaps().get_mapping(key, KeymapMode::User); ScopedSetBool disable_keymaps(context.keymaps_disabled()); + + InputHandler::ScopedForceNormal force_normal{context.input_handler()}; + ScopedEdition edition(context); for (auto& key : mapping) context.input_handler().handle_key(key); |
