diff options
| author | Johannes Altmanninger <aclopte@gmail.com> | 2025-05-10 21:39:27 +0200 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2025-05-11 10:08:43 +1000 |
| commit | 23ea6e6a5230a62fc4c183b1898efb550db0c347 (patch) | |
| tree | f89b24375e5f3d7aadb881349a2a6e20bfd9a15f /src/selection.cc | |
| parent | a89747c458b7e316ba78fc0a52fad36f827dd63f (diff) | |
Work around non-forward insertions by linewise <a-P>
Given a buffer with two selections
%(a)b%(c)
Consider <a-P>, which inserts all elements of the dquote register, joined
to a scalar string. This insertion happens once before each selection.
Let the dquote register contain "\n" and "\nd". Since the first element ends
in a newline, we enable linewise paste mode.
The insertion at the first selection results in:
contents: \n\nd%(a)b%(c)
timestamps: 11111000000000
On top of that, the insertion at the second selection would result in:
contents: \n\n\n\ndd%(a)b%(c)
timestamps: 1111222221000000000
Observe that the second insertion actually takes place inside the text added
by the first insertion.
This is because we are inserting before the current line, and the first
insertion does not end in a newline.
This breaks the forward change tracker's assumption that each change takes
place after the previous one, causing an assertion failure. We use this
data structure to translate from old to new coordinates. Specifically,
after the first insertion, the selection around %(c) which is initially
1.3,1.3 needs to be updated to 3.4,3.4.
Work around this by instantiating a new ForwardChangesTracker after each step.
This is very ugly because it's quadratic, and because it doesn't change the
fact that the second insertion is made inside the first one. I think we
can revert the workaround added by this patch, see the next patch.
Closes #5312
Diffstat (limited to 'src/selection.cc')
| -rw-r--r-- | src/selection.cc | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/src/selection.cc b/src/selection.cc index 99b21c3e..f893f21f 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -394,18 +394,18 @@ void SelectionList::for_each(ApplyFunc func, bool may_append) } else { - ForwardChangesTracker changes_tracker; for (size_t index = 0; index < m_selections.size(); ++index) { - auto& sel = m_selections[index]; - - sel.anchor() = changes_tracker.get_new_coord_tolerant(sel.anchor()); - sel.cursor() = changes_tracker.get_new_coord_tolerant(sel.cursor()); - kak_assert(m_buffer->is_valid(sel.anchor()) and m_buffer->is_valid(sel.cursor())); - - func(index, sel); - + ForwardChangesTracker changes_tracker; + func(index, m_selections[index]); changes_tracker.update(*m_buffer, m_timestamp); + for (size_t i = index + 1; i < m_selections.size(); ++i) + { + auto& sel = m_selections[i]; + sel.anchor() = changes_tracker.get_new_coord_tolerant(sel.anchor()); + sel.cursor() = changes_tracker.get_new_coord_tolerant(sel.cursor()); + kak_assert(m_buffer->is_valid(sel.anchor()) and m_buffer->is_valid(sel.cursor())); + } } } |
