Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid moving the cursor when applying textedits #407

Merged
merged 1 commit into from
Oct 16, 2023

Conversation

vimpostor
Copy link
Contributor

@vimpostor vimpostor commented Oct 12, 2023

Currently the ApplyTextEdits() code loses the cursor position, because it applies the text edits by deleting the entire range with deletebufline() and then adding the new range with appendbufline().
Obviously the cursor will move, if it happens to be inside this range, which is often the case (e.g. when renaming a variable).

This is also apparently the reason, why in the past there was a workaround that saved the cursor position before applying any edits, and then restored it afterwards.
That workaround was already (correctly) removed with: #389 (comment)

Instead of reintroducing the workaround, this patch avoids losing the cursor position altogether by not deleting the entire range, but only deleting lines that actually need to be deleted (and adding new lines that actually need to be added).

In my opinion this solution is even simpler code-wise than it was before where we removed the entire region.

I also added a new test case for the scenario where lines have to be removed, all other cases already have test cases.

Demo

The old behaviour is on the left side: After renaming the variable, the cursor jumps to the end of the range.
The new behaviour is on the right side: After renaming the variable, the cursor does not move.

demo.mp4

In 33c9dc3 we removed a workaround that
resets the cursor to the previous location after applying an
workspaceEdit, because it interfered with auto-imports.

Turns out the workaround was there for a reason: When we apply general
textedits (e.g. when we rename a variable), then we are always moving
the cursor by accident, because internally (to apply a textedit) we
delete the entire text range and then append the new range.
Obviously this loses the cursor position, hence the reason for the
original manual cursor reset workaround.

Instead of reintroducing that workaround, we now avoid moving the cursor
altogether: We accomplish this by no longer deleting the entire range
and inserting it again. Instead we just remove lines that actually need
to be deleted, add lines that actually need to be added and then handle
the rest with a normal setbufline() call.

This will cause the cursor to never lose the correct position, because
we never remove the entire region where the cursor is located in.

We have to be careful with off-by-one errors, therefore this also adds
an extra test for the scenario where we have to delete some lines. The
two other scenarios already had comprehensive tests (adding lines, and
keeping the amount of lines).
@Shane-XB-Qian
Copy link
Contributor

@yegappan not sure if had outage, but so far i felt this is a good refine, if you had no objection, perhaps good to merge.

// @vimpostor
// if you have time, perhaps continue to test or think some if there other concern cases if there were.
// and thanks, this should be a good enhancement if there no side outage.

@yegappan
Copy link
Owner

Thanks for the patch and the detailed description.

@yegappan yegappan merged commit 3897040 into yegappan:main Oct 16, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants