summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2024-07-22 17:43:37 +1000
committerMaxime Coste <mawww@kakoune.org>2024-07-22 20:22:14 +1000
commite938d724f16ef06cbc97a4fedc20d56edf34e7f2 (patch)
treebc5828353bdc26259b59bf6eadf8e7bb08b9f062 /src
parent6f562aa0add09092d390f7ea2691959490234ed0 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/client.cc2
-rw-r--r--src/commands.cc4
-rw-r--r--src/input_handler.cc73
-rw-r--r--src/input_handler.hh13
-rw-r--r--src/insert_completer.cc9
-rw-r--r--src/insert_completer.hh3
-rw-r--r--src/main.cc2
-rw-r--r--src/normal.cc4
8 files changed, 66 insertions, 44 deletions
diff --git a/src/client.cc b/src/client.cc
index 6e5d082a..7cfea960 100644
--- a/src/client.cc
+++ b/src/client.cc
@@ -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());
diff --git a/src/commands.cc b/src/commands.cc
index ef51555e..69fca0d6 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -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);
diff --git a/src/input_handler.cc b/src/input_handler.cc
index 15156c2b..2703b51a 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -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*>(&current_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;
diff --git a/src/input_handler.hh b/src/input_handler.hh
index ba73d2b1..dd475c92 100644
--- a/src/input_handler.hh
+++ b/src/input_handler.hh
@@ -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
diff --git a/src/insert_completer.cc b/src/insert_completer.cc
index 3e1bcd2d..73c08a43 100644
--- a/src/insert_completer.cc
+++ b/src/insert_completer.cc
@@ -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())
diff --git a/src/insert_completer.hh b/src/insert_completer.hh
index 3d5f2ca6..c624639d 100644
--- a/src/insert_completer.hh
+++ b/src/insert_completer.hh
@@ -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();
diff --git a/src/main.cc b/src/main.cc
index f2e31cab..e86ffae3 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -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)
{
diff --git a/src/normal.cc b/src/normal.cc
index af4d5fb1..9f1d3de7 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -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, {}));
}