Make selection undo skip over entries that are nop after buffer change

After buffer modification - in particular after deletion - adjacent
selection history entries may correspond to the same effective
selection when applied to the current buffer. This means that we
sometimes need to press <c-h> multiple times to make one visible
change. This is not what the user expects, so let's keep walking the
selection history until we hit an actual change.

Alternatively, we could minimize the selection history after buffer
changes but I think that would make the it worse after content
undo+redo.
This commit is contained in:
Johannes Altmanninger 2022-12-22 18:09:45 +01:00
parent 8427379a5d
commit 516759bb2f
5 changed files with 31 additions and 16 deletions

View File

@ -225,24 +225,29 @@ void Context::SelectionHistory::undo()
if (in_edition())
throw runtime_error("selection undo is only supported at top-level");
kak_assert(not empty());
SelectionList old_selections = selections();
HistoryId next;
if constexpr (backward)
next = current_history_node().parent;
else
next = current_history_node().redo_child;
if (next == HistoryId::Invalid)
throw runtime_error(backward ? "no selection change to undo" : "no selection change to redo");
auto select_next = [&, next] {
HistoryId previous_id = m_history_id;
m_history_id = next;
do
{
if constexpr (backward)
current_history_node().redo_child = previous_id;
};
Buffer& destination_buffer = history_node(next).selections.buffer();
if (&destination_buffer == &m_context.buffer())
select_next();
else
m_context.change_buffer(destination_buffer, { std::move(select_next) });
next = current_history_node().parent;
else
next = current_history_node().redo_child;
if (next == HistoryId::Invalid)
throw runtime_error(backward ? "no selection change to undo" : "no selection change to redo");
auto select_next = [&, next] {
HistoryId previous_id = m_history_id;
m_history_id = next;
if constexpr (backward)
current_history_node().redo_child = previous_id;
};
Buffer& destination_buffer = history_node(next).selections.buffer();
if (&destination_buffer == &m_context.buffer())
select_next();
else
m_context.change_buffer(destination_buffer, { std::move(select_next) });
}
while (selections() == old_selections);
}
void Context::SelectionHistory::forget_buffer(Buffer& buffer)

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,4 @@
1
2
3
4

View File

@ -0,0 +1,3 @@
2
3
here4

View File

@ -0,0 +1,2 @@
ui_out -ignore 4
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "gjgkxd<c-h>ihere<esc>" ] }'