User mappings and :exec are always executed in normal mode

Fix #551
This commit is contained in:
Maxime Coste 2016-03-22 22:54:29 +00:00
parent c1c17db5e9
commit 5bf9243006
4 changed files with 46 additions and 1 deletions

View File

@ -1405,7 +1405,7 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func)
const CommandDesc exec_string_cmd = { const CommandDesc exec_string_cmd = {
"exec", "exec",
nullptr, 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, context_wrap_params,
CommandFlags::None, CommandFlags::None,
CommandHelper{}, CommandHelper{},
@ -1420,6 +1420,8 @@ const CommandDesc exec_string_cmd = {
keys.insert(keys.end(), param_keys.begin(), param_keys.end()); keys.insert(keys.end(), param_keys.begin(), param_keys.end());
} }
InputHandler::ScopedForceNormal force_normal{context.input_handler()};
ScopedEdition edition(context); ScopedEdition edition(context);
for (auto& key : keys) for (auto& key : keys)
context.input_handler().handle_key(key); context.input_handler().handle_key(key);

View File

@ -1325,6 +1325,35 @@ void InputHandler::on_next_key(KeymapMode keymap_mode, KeyCallback callback)
push_mode(new InputModes::NextKey(*this, keymap_mode, 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) static bool is_valid(Key key)
{ {
return key != Key::Invalid and return key != Key::Invalid and

View File

@ -82,6 +82,17 @@ public:
DisplayLine mode_line() const; 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: private:
Context m_context; Context m_context;

View File

@ -1456,6 +1456,9 @@ void exec_user_mappings(Context& context, NormalParams params)
auto mapping = context.keymaps().get_mapping(key, KeymapMode::User); auto mapping = context.keymaps().get_mapping(key, KeymapMode::User);
ScopedSetBool disable_keymaps(context.keymaps_disabled()); ScopedSetBool disable_keymaps(context.keymaps_disabled());
InputHandler::ScopedForceNormal force_normal{context.input_handler()};
ScopedEdition edition(context); ScopedEdition edition(context);
for (auto& key : mapping) for (auto& key : mapping)
context.input_handler().handle_key(key); context.input_handler().handle_key(key);