mirror of
https://github.com/mawww/kakoune.git
synced 2024-11-23 15:23:29 +03:00
Handle word completion when recording macros
Make last insert and macro recording closer together, paving the way towards moving last insert to a register. Use a FunctionRef for insert completer key insertion support.
This commit is contained in:
parent
6f562aa0ad
commit
e938d724f1
@ -111,7 +111,7 @@ bool Client::process_pending_inputs()
|
||||
else
|
||||
{
|
||||
context().ensure_cursor_visible = true;
|
||||
m_input_handler.handle_key(key);
|
||||
m_input_handler.handle_key(key, false);
|
||||
}
|
||||
|
||||
context().hooks().run_hook(Hook::RawKey, to_string(key), context());
|
||||
|
@ -2202,7 +2202,7 @@ const CommandDesc execute_keys_cmd = {
|
||||
ScopedSetBool disable_hooks(context.hooks_disabled(), not parser.get_switch("with-hooks"));
|
||||
|
||||
for (auto& key : parser | transform(parse_keys) | flatten())
|
||||
context.input_handler().handle_key(key);
|
||||
context.input_handler().handle_key(key, true);
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -2675,7 +2675,7 @@ void enter_user_mode(Context& context, String mode_name, KeymapMode mode, bool l
|
||||
ScopedEdition edition(context);
|
||||
|
||||
for (auto& key : context.keymaps().get_mapping_keys(key, mode))
|
||||
context.input_handler().handle_key(key);
|
||||
context.input_handler().handle_key(key, true);
|
||||
|
||||
if (lock)
|
||||
enter_user_mode(context, std::move(mode_name), mode, true);
|
||||
|
@ -67,15 +67,12 @@ public:
|
||||
protected:
|
||||
virtual void on_key(Key key, bool synthesized) = 0;
|
||||
|
||||
void push_mode(InputMode* new_mode)
|
||||
{
|
||||
m_input_handler.push_mode(new_mode);
|
||||
}
|
||||
void push_mode(InputMode* new_mode) { m_input_handler.push_mode(new_mode); }
|
||||
void pop_mode() { m_input_handler.pop_mode(this); }
|
||||
|
||||
void record_key(Key key) { m_input_handler.record_key(key); }
|
||||
void drop_last_recorded_key() { m_input_handler.drop_last_recorded_key(); }
|
||||
|
||||
void pop_mode()
|
||||
{
|
||||
m_input_handler.pop_mode(this);
|
||||
}
|
||||
private:
|
||||
InputHandler& m_input_handler;
|
||||
};
|
||||
@ -1307,11 +1304,10 @@ public:
|
||||
}
|
||||
else if (key == ctrl('n') or key == ctrl('p') or key.modifiers == Key::Modifiers::MenuSelect)
|
||||
{
|
||||
if (m_last_insert)
|
||||
m_last_insert->keys.pop_back();
|
||||
drop_last_recorded_key();
|
||||
bool relative = key.modifiers != Key::Modifiers::MenuSelect;
|
||||
int index = relative ? (key == ctrl('n') ? 1 : -1) : key.key;
|
||||
m_completer.select(index, relative, m_last_insert ? &m_last_insert->keys : nullptr);
|
||||
m_completer.select(index, relative, [&](Key key) { record_key(key); });
|
||||
update_completions = false;
|
||||
}
|
||||
else if (key == ctrl('x'))
|
||||
@ -1585,7 +1581,7 @@ void InputHandler::repeat_last_insert()
|
||||
|
||||
push_mode(new InputModes::Insert(*this, m_last_insert.mode, m_last_insert.count, nullptr));
|
||||
for (auto& key : m_last_insert.keys)
|
||||
handle_key(key);
|
||||
handle_key(key, true);
|
||||
kak_assert(dynamic_cast<InputModes::Normal*>(¤t_mode()) != nullptr);
|
||||
}
|
||||
|
||||
@ -1647,18 +1643,16 @@ static bool is_valid(Key key)
|
||||
return ((key.modifiers & ~valid_mods) or key.key <= 0x10FFFF);
|
||||
}
|
||||
|
||||
void InputHandler::handle_key(Key key)
|
||||
void InputHandler::handle_key(Key key, bool synthesized)
|
||||
{
|
||||
if (not is_valid(key))
|
||||
return;
|
||||
|
||||
const bool was_recording = is_recording();
|
||||
++m_handle_key_level;
|
||||
auto dec = on_scope_end([this]{ --m_handle_key_level;} );
|
||||
|
||||
auto process_key = [&](Key k, bool synthesized) {
|
||||
if (m_last_insert.recording and m_handle_key_level <= 1)
|
||||
m_last_insert.keys.push_back(k);
|
||||
auto process_key = [this](Key k, bool synthesized) {
|
||||
record_key(k);
|
||||
current_mode().handle_key(k, synthesized);
|
||||
};
|
||||
|
||||
@ -1671,12 +1665,7 @@ void InputHandler::handle_key(Key key)
|
||||
process_key(k, true);
|
||||
}
|
||||
else
|
||||
process_key(key, m_handle_key_level > 1);
|
||||
|
||||
// do not record the key that made us enter or leave recording mode,
|
||||
// and the ones that are triggered recursively by previous keys.
|
||||
if (was_recording and is_recording() and m_handle_key_level == m_recording_level)
|
||||
m_recorded_keys += to_string(key);
|
||||
process_key(key, synthesized or m_handle_key_level > 1);
|
||||
|
||||
if (m_handle_key_level < m_recording_level)
|
||||
{
|
||||
@ -1686,6 +1675,29 @@ void InputHandler::handle_key(Key key)
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::record_key(Key key)
|
||||
{
|
||||
if (m_last_insert.recording and m_handle_key_level <= 1)
|
||||
m_last_insert.keys.push_back(key);
|
||||
if (is_recording() and m_handle_key_level == m_recording_level)
|
||||
m_recorded_keys.push_back(key);
|
||||
}
|
||||
|
||||
void InputHandler::drop_last_recorded_key()
|
||||
{
|
||||
if (m_last_insert.recording and m_handle_key_level <= 1)
|
||||
{
|
||||
kak_assert(not m_last_insert.keys.empty());
|
||||
m_last_insert.keys.pop_back();
|
||||
}
|
||||
|
||||
if (is_recording() and m_handle_key_level == m_recording_level)
|
||||
{
|
||||
kak_assert(not m_recorded_keys.empty());
|
||||
m_recorded_keys.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::refresh_ifn()
|
||||
{
|
||||
current_mode().refresh_ifn();
|
||||
@ -1695,7 +1707,7 @@ void InputHandler::start_recording(char reg)
|
||||
{
|
||||
kak_assert(m_recording_reg == 0);
|
||||
m_recording_level = m_handle_key_level;
|
||||
m_recorded_keys = "";
|
||||
m_recorded_keys.clear();
|
||||
m_recording_reg = reg;
|
||||
}
|
||||
|
||||
@ -1707,10 +1719,17 @@ bool InputHandler::is_recording() const
|
||||
void InputHandler::stop_recording()
|
||||
{
|
||||
kak_assert(m_recording_reg != 0);
|
||||
|
||||
if (not m_recorded_keys.empty())
|
||||
RegisterManager::instance()[m_recording_reg].set(
|
||||
context(), {m_recorded_keys});
|
||||
{
|
||||
// Forget the key that got us to exit recording
|
||||
if (m_handle_key_level == m_recording_level)
|
||||
m_recorded_keys.pop_back();
|
||||
|
||||
String keys;
|
||||
for (auto& key : m_recorded_keys)
|
||||
keys += to_string(key);
|
||||
RegisterManager::instance()[m_recording_reg].set(context(), {keys});
|
||||
}
|
||||
|
||||
m_recording_reg = 0;
|
||||
m_recording_level = -1;
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
Timer::Callback idle_callback = Timer::Callback{});
|
||||
|
||||
// process the given key
|
||||
void handle_key(Key key);
|
||||
void handle_key(Key key, bool synthesized);
|
||||
|
||||
void refresh_ifn();
|
||||
|
||||
@ -131,6 +131,9 @@ private:
|
||||
void push_mode(InputMode* new_mode);
|
||||
void pop_mode(InputMode* current_mode);
|
||||
|
||||
void record_key(Key key);
|
||||
void drop_last_recorded_key();
|
||||
|
||||
struct Insertion{
|
||||
NestedBool recording;
|
||||
InsertMode mode;
|
||||
@ -139,11 +142,11 @@ private:
|
||||
int count;
|
||||
} m_last_insert = { {}, InsertMode::Insert, {}, false, 1 };
|
||||
|
||||
char m_recording_reg = 0;
|
||||
String m_recorded_keys;
|
||||
int m_recording_level = -1;
|
||||
int m_handle_key_level = 0;
|
||||
|
||||
int m_handle_key_level = 0;
|
||||
char m_recording_reg = 0;
|
||||
Vector<Key> m_recorded_keys;
|
||||
int m_recording_level = -1;
|
||||
};
|
||||
|
||||
enum class AutoInfo
|
||||
|
@ -416,7 +416,7 @@ InsertCompleter::~InsertCompleter()
|
||||
m_options.unregister_watcher(*this);
|
||||
}
|
||||
|
||||
void InsertCompleter::select(int index, bool relative, Vector<Key>* keystrokes)
|
||||
void InsertCompleter::select(int index, bool relative, FunctionRef<void (Key)> record_key)
|
||||
{
|
||||
m_enabled = true;
|
||||
if (not setup_ifn())
|
||||
@ -453,14 +453,13 @@ void InsertCompleter::select(int index, bool relative, Vector<Key>* keystrokes)
|
||||
m_context.client().menu_select(m_current_candidate);
|
||||
}
|
||||
|
||||
if (keystrokes)
|
||||
{
|
||||
for (auto i = 0_byte; i < prefix_len; ++i)
|
||||
keystrokes->emplace_back(Key::Backspace);
|
||||
record_key(Key::Backspace);
|
||||
for (auto i = 0_byte; i < suffix_len; ++i)
|
||||
keystrokes->emplace_back(Key::Delete);
|
||||
record_key(Key::Delete);
|
||||
for (auto& c : candidate.completion)
|
||||
keystrokes->emplace_back(c);
|
||||
record_key(c);
|
||||
}
|
||||
|
||||
if (not candidate.on_select.empty())
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "option.hh"
|
||||
#include "display_buffer.hh"
|
||||
#include "vector.hh"
|
||||
#include "utils.hh"
|
||||
|
||||
#include "optional.hh"
|
||||
|
||||
@ -78,7 +79,7 @@ public:
|
||||
InsertCompleter& operator=(const InsertCompleter&) = delete;
|
||||
~InsertCompleter();
|
||||
|
||||
void select(int index, bool relative, Vector<Key>* keystrokes);
|
||||
void select(int index, bool relative, FunctionRef<void (Key)> record_key);
|
||||
void update(bool allow_implicit);
|
||||
void try_accept();
|
||||
void reset();
|
||||
|
@ -985,7 +985,7 @@ int run_filter(StringView keystr, ConstArrayView<StringView> files, bool quiet,
|
||||
};
|
||||
|
||||
for (auto& key : keys)
|
||||
input_handler.handle_key(key);
|
||||
input_handler.handle_key(key, true);
|
||||
}
|
||||
catch (runtime_error& err)
|
||||
{
|
||||
|
@ -1601,7 +1601,7 @@ void replay_macro(Context& context, NormalParams params)
|
||||
do
|
||||
{
|
||||
for (auto& key : keys)
|
||||
context.input_handler().handle_key(key);
|
||||
context.input_handler().handle_key(key, true);
|
||||
} while (--params.count > 0);
|
||||
}
|
||||
|
||||
@ -2073,7 +2073,7 @@ void exec_user_mappings(Context& context, NormalParams params)
|
||||
ScopedEdition edition(context);
|
||||
ScopedSelectionEdition selection_edition{context};
|
||||
for (auto& key : context.keymaps().get_mapping_keys(key, KeymapMode::User))
|
||||
context.input_handler().handle_key(key);
|
||||
context.input_handler().handle_key(key, true);
|
||||
}, "user mapping",
|
||||
build_autoinfo_for_mapping(context, KeymapMode::User, {}));
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
Qofo<c-x><c-w><tab><esc>Qq
|
1
test/normal/macro/replay-macro-mapped-word-completion/in
Normal file
1
test/normal/macro/replay-macro-mapped-word-completion/in
Normal file
@ -0,0 +1 @@
|
||||
foobar
|
@ -0,0 +1,3 @@
|
||||
foobar
|
||||
foobar
|
||||
foobar
|
1
test/normal/macro/replay-macro-mapped-word-completion/rc
Normal file
1
test/normal/macro/replay-macro-mapped-word-completion/rc
Normal file
@ -0,0 +1 @@
|
||||
map global insert <tab> <c-n>
|
Loading…
Reference in New Issue
Block a user