Skip to content

Commit

Permalink
Refactor last insert recording logic
Browse files Browse the repository at this point in the history
Only record non-synthetized insertions, removing the need to
re-record on replay and fixing the last replay getting dropped by
macro execution.

Fixes #5122
  • Loading branch information
mawww committed Mar 23, 2024
1 parent 71b003b commit 6e4bb5f
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 35 deletions.
48 changes: 21 additions & 27 deletions src/input_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ class InputMode : public RefCountable
}

using Insertion = InputHandler::Insertion;
Insertion& last_insert() { return m_input_handler.m_last_insert; }

protected:
virtual void on_key(Key key, bool synthesized) = 0;
Expand Down Expand Up @@ -1140,11 +1139,12 @@ class NextKey : public InputMode
class Insert : public InputMode
{
public:
Insert(InputHandler& input_handler, InsertMode mode, int count)
Insert(InputHandler& input_handler, InsertMode mode, int count, Insertion* last_insert)
: InputMode(input_handler),
m_edition(context()),
m_selection_edition(context()),
m_completer(context()),
m_last_insert(last_insert),
m_restore_cursor(mode == InsertMode::Append),
m_auto_complete{context().options()["autocomplete"].get<AutoComplete>() & AutoComplete::Insert},
m_idle_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ?
Expand All @@ -1157,11 +1157,14 @@ class Insert : public InputMode
{
context().buffer().throw_if_read_only();

last_insert().recording.set();
last_insert().mode = mode;
last_insert().keys.clear();
last_insert().disable_hooks = context().hooks_disabled();
last_insert().count = count;
if (m_last_insert)
{
m_last_insert->recording.set();
m_last_insert->mode = mode;
m_last_insert->keys.clear();
m_last_insert->disable_hooks = context().hooks_disabled();
m_last_insert->count = count;
}
prepare(mode, count);
}

Expand All @@ -1177,7 +1180,8 @@ class Insert : public InputMode

if (not from_push)
{
last_insert().recording.unset();
if (m_last_insert)
m_last_insert->recording.unset();

auto& selections = context().selections();
if (m_restore_cursor)
Expand Down Expand Up @@ -1291,11 +1295,11 @@ class Insert : public InputMode
}
else if (key == ctrl('n') or key == ctrl('p') or key.modifiers == Key::Modifiers::MenuSelect)
{
if (not synthesized)
last_insert().keys.pop_back();
if (m_last_insert and not synthesized)
m_last_insert->keys.pop_back();
bool relative = key.modifiers != Key::Modifiers::MenuSelect;
int index = relative ? (key == ctrl('n') ? 1 : -1) : key.key;
m_completer.select(index, relative, last_insert().keys);
m_completer.select(index, relative, m_last_insert ? &m_last_insert->keys : nullptr);
update_completions = false;
}
else if (key == ctrl('x'))
Expand Down Expand Up @@ -1494,6 +1498,7 @@ class Insert : public InputMode
ScopedEdition m_edition;
ScopedSelectionEdition m_selection_edition;
InsertCompleter m_completer;
Insertion* m_last_insert;
const bool m_restore_cursor;
bool m_auto_complete;
Timer m_idle_timer;
Expand Down Expand Up @@ -1550,7 +1555,7 @@ void InputHandler::reset_normal_mode()

void InputHandler::insert(InsertMode mode, int count)
{
push_mode(new InputModes::Insert(*this, mode, count));
push_mode(new InputModes::Insert(*this, mode, count, m_handle_key_level <= 1 ? &m_last_insert : nullptr));
}

void InputHandler::repeat_last_insert()
Expand All @@ -1562,19 +1567,12 @@ void InputHandler::repeat_last_insert()
m_last_insert.recording)
throw runtime_error{"repeating last insert not available in this context"};

Vector<Key> keys;
swap(keys, m_last_insert.keys);
ScopedSetBool disable_hooks(context().hooks_disabled(),
m_last_insert.disable_hooks);

push_mode(new InputModes::Insert(*this, m_last_insert.mode, m_last_insert.count));
for (auto& key : keys)
{
// refill last_insert, this is very inefficient, but necessary at the moment
// to properly handle insert completion
m_last_insert.keys.push_back(key);
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);
}
kak_assert(dynamic_cast<InputModes::Normal*>(&current_mode()) != nullptr);
}

Expand Down Expand Up @@ -1645,10 +1643,6 @@ void InputHandler::handle_key(Key key)
++m_handle_key_level;
auto dec = on_scope_end([this]{ --m_handle_key_level;} );

auto process_key = [&](Key key, bool synthesized) {
current_mode().handle_key(key, synthesized);
};

if (m_last_insert.recording and m_handle_key_level <= 1)
m_last_insert.keys.push_back(key);

Expand All @@ -1659,10 +1653,10 @@ void InputHandler::handle_key(Key key)
ScopedSetBool noninteractive{context().noninteractive()};

for (auto& k : keymaps.get_mapping_keys(key, keymap_mode))
process_key(k, true);
current_mode().handle_key(k, true);
}
else
process_key(key, m_handle_key_level > 1);
current_mode().handle_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.
Expand Down
17 changes: 10 additions & 7 deletions src/insert_completer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,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, Vector<Key>* keystrokes)
{
m_enabled = true;
if (not setup_ifn())
Expand Down Expand Up @@ -450,12 +450,15 @@ void InsertCompleter::select(int index, bool relative, Vector<Key>& keystrokes)
m_context.client().menu_select(m_current_candidate);
}

for (auto i = 0_byte; i < prefix_len; ++i)
keystrokes.emplace_back(Key::Backspace);
for (auto i = 0_byte; i < suffix_len; ++i)
keystrokes.emplace_back(Key::Delete);
for (auto& c : candidate.completion)
keystrokes.emplace_back(c);
if (keystrokes)
{
for (auto i = 0_byte; i < prefix_len; ++i)
keystrokes->emplace_back(Key::Backspace);
for (auto i = 0_byte; i < suffix_len; ++i)
keystrokes->emplace_back(Key::Delete);
for (auto& c : candidate.completion)
keystrokes->emplace_back(c);
}

if (not candidate.on_select.empty())
CommandManager::instance().execute(candidate.on_select, m_context);
Expand Down
2 changes: 1 addition & 1 deletion src/insert_completer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public:
InsertCompleter& operator=(const InsertCompleter&) = delete;
~InsertCompleter();

void select(int index, bool relative, Vector<Key>& keystrokes);
void select(int index, bool relative, Vector<Key>* keystrokes);
void update(bool allow_implicit);
void try_accept();
void reset();
Expand Down
1 change: 1 addition & 0 deletions test/regression/5122-dot-fails-after-macro-replay/cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
QA?<esc>Qq.
1 change: 1 addition & 0 deletions test/regression/5122-dot-fails-after-macro-replay/in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions test/regression/5122-dot-fails-after-macro-replay/out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
???

0 comments on commit 6e4bb5f

Please sign in to comment.