unmap: fail if the mapping is currently executing
When unmapping a key sequence that is currently executing, we continue executing freed memory which can have weird effects. Let's instead throw an error if that happens. In future we can support unmap in this scenario. Closes #4896
This commit is contained in:
parent
cfa658b899
commit
e49c0fb040
|
@ -1933,10 +1933,15 @@ const CommandDesc unmap_key_cmd = {
|
||||||
if (key.size() != 1)
|
if (key.size() != 1)
|
||||||
throw runtime_error("only a single key can be unmapped");
|
throw runtime_error("only a single key can be unmapped");
|
||||||
|
|
||||||
if (keymaps.is_mapped(key[0], keymap_mode) and
|
if (not keymaps.is_mapped(key[0], keymap_mode))
|
||||||
(parser.positional_count() < 4 or
|
return;
|
||||||
(keymaps.get_mapping(key[0], keymap_mode).keys ==
|
auto& mapping = keymaps.get_mapping(key[0], keymap_mode);
|
||||||
parse_keys(parser[3]))))
|
|
||||||
|
if (mapping.is_executing)
|
||||||
|
throw runtime_error("cannot unmap key that is currently executing");
|
||||||
|
|
||||||
|
if (parser.positional_count() < 4 or
|
||||||
|
(mapping.keys == parse_keys(parser[3])))
|
||||||
keymaps.unmap_key(key[0], keymap_mode);
|
keymaps.unmap_key(key[0], keymap_mode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2653,8 +2658,12 @@ void enter_user_mode(Context& context, String mode_name, KeymapMode mode, bool l
|
||||||
InputHandler::ScopedForceNormal force_normal{context.input_handler(), {}};
|
InputHandler::ScopedForceNormal force_normal{context.input_handler(), {}};
|
||||||
|
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
|
|
||||||
|
{
|
||||||
|
ScopedSetBool executing_mapping{mapping.is_executing};
|
||||||
for (auto& key : mapping.keys)
|
for (auto& key : mapping.keys)
|
||||||
context.input_handler().handle_key(key);
|
context.input_handler().handle_key(key);
|
||||||
|
}
|
||||||
|
|
||||||
if (lock)
|
if (lock)
|
||||||
enter_user_mode(context, std::move(mode_name), mode, true);
|
enter_user_mode(context, std::move(mode_name), mode, true);
|
||||||
|
|
|
@ -1773,7 +1773,10 @@ void InputHandler::handle_key(Key key)
|
||||||
if (keymaps.is_mapped(key, keymap_mode) and not m_context.keymaps_disabled())
|
if (keymaps.is_mapped(key, keymap_mode) and not m_context.keymaps_disabled())
|
||||||
{
|
{
|
||||||
ScopedSetBool disable_history{context().history_disabled()};
|
ScopedSetBool disable_history{context().history_disabled()};
|
||||||
for (auto& k : keymaps.get_mapping(key, keymap_mode).keys)
|
|
||||||
|
auto& mapping = keymaps.get_mapping(key, keymap_mode);
|
||||||
|
ScopedSetBool executing_mapping{mapping.is_executing};
|
||||||
|
for (auto& k : mapping.keys)
|
||||||
process_key(k);
|
process_key(k);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -40,8 +40,8 @@ bool KeymapManager::is_mapped(Key key, KeymapMode mode) const
|
||||||
(m_parent and m_parent->is_mapped(key, mode));
|
(m_parent and m_parent->is_mapped(key, mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
const KeymapManager::KeymapInfo&
|
KeymapManager::KeymapInfo&
|
||||||
KeymapManager::get_mapping(Key key, KeymapMode mode) const
|
KeymapManager::get_mapping(Key key, KeymapMode mode)
|
||||||
{
|
{
|
||||||
auto it = m_mapping.find(KeyAndMode{key, mode});
|
auto it = m_mapping.find(KeyAndMode{key, mode});
|
||||||
if (it != m_mapping.end())
|
if (it != m_mapping.end())
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "hash.hh"
|
#include "hash.hh"
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
#include "hash_map.hh"
|
#include "hash_map.hh"
|
||||||
|
#include "utils.hh"
|
||||||
#include "vector.hh"
|
#include "vector.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
|
@ -42,8 +43,9 @@ public:
|
||||||
{
|
{
|
||||||
KeyList keys;
|
KeyList keys;
|
||||||
String docstring;
|
String docstring;
|
||||||
|
NestedBool is_executing{};
|
||||||
};
|
};
|
||||||
const KeymapInfo& get_mapping(Key key, KeymapMode mode) const;
|
KeymapInfo& get_mapping(Key key, KeymapMode mode);
|
||||||
|
|
||||||
using UserModeList = Vector<String>;
|
using UserModeList = Vector<String>;
|
||||||
UserModeList& user_modes() {
|
UserModeList& user_modes() {
|
||||||
|
|
|
@ -2033,6 +2033,7 @@ void exec_user_mappings(Context& context, NormalParams params)
|
||||||
|
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
ScopedSelectionEdition selection_edition{context};
|
ScopedSelectionEdition selection_edition{context};
|
||||||
|
ScopedSetBool executing_mapping{mapping.is_executing};
|
||||||
for (auto& key : mapping.keys)
|
for (auto& key : mapping.keys)
|
||||||
context.input_handler().handle_key(key);
|
context.input_handler().handle_key(key);
|
||||||
}, "user mapping",
|
}, "user mapping",
|
||||||
|
|
1
test/regression/4896-unmap-executing-mapping/cmd
Normal file
1
test/regression/4896-unmap-executing-mapping/cmd
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<space>u
|
1
test/regression/4896-unmap-executing-mapping/in
Normal file
1
test/regression/4896-unmap-executing-mapping/in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
1
test/regression/4896-unmap-executing-mapping/out
Normal file
1
test/regression/4896-unmap-executing-mapping/out
Normal file
|
@ -0,0 +1 @@
|
||||||
|
123
|
1
test/regression/4896-unmap-executing-mapping/rc
Normal file
1
test/regression/4896-unmap-executing-mapping/rc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
map global user u %{i123<esc>:unmap global user u<ret>i456<esc>}
|
Loading…
Reference in New Issue
Block a user