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

The viewport jumping problem #2

Open
kaste opened this issue May 12, 2021 · 1 comment
Open

The viewport jumping problem #2

kaste opened this issue May 12, 2021 · 1 comment

Comments

@kaste
Copy link

kaste commented May 12, 2021

Hi!

I read https://discord.com/channels/280102180189634562/280157067396775936/840207551065096284 and the linked issues, for example sublimehq/sublime_text#4144

From my experience working on GitSavvy and SublimeLinter you can split the problem to make it more simple.

First, you can stabilize the viewport, just using

vx, vy = view.viewport_position()  # read

view.replace(...)

view.set_viewport_position((0, 0), animate=False)  # intentional force!
view.set_viewport_position((vx, vy), animate=False)  # write

This has to be done sync as a TextCommand. (see: https://github.com/timbrel/GitSavvy/blob/d6e24d714c08e5b975ae08bafbebb2f75eabe303/core/view.py#L183-L194)

This is a good start. However, you might want to improve further by first reading a row_offset and reapplying it after replace and setting the new cursor. With the row_offset you basically measure that the cursor is at the nth row/line, or x pixels, from the top of the viewport. (Refer: https://github.com/timbrel/GitSavvy/blob/d6e24d714c08e5b975ae08bafbebb2f75eabe303/core/view.py#L111-L115)

Reapplying:

    vy = (new_row - row_offset) * view.line_height()
    vx, _ = view.viewport_position()
    view.set_viewport_position((vx, vy), animate=False)

So, in other words, you first see the cursor is on the row 50, after applying the patch/formatting, you observe the cursor is now on row 40. You modify vy so that the distance from the top of the viewport to the cursor (the row_offset) does not change.

The second problem is where the cursor actually lands or ideally should land after applying the patch. That's a problem you cannot solve under all circumstances. (That's why Prettier can - given a cursor position - return the new cursor position; computed as part of the formatting job.)

Doing a diff is probably a good approach. Iirc, you only have to "fix" the cursor if you replace (including expanding or shrinking) a region where the cursor is in ("contained") or at ("at the edges"). This is of course always true if you replace the whole buffer.

From my understanding, it would be enough to diff the text up to the line the last cursor is on. Then compute the new cursors using the diff, replace the whole view, and set the new cursors.

You could also apply the diff hunk by hunk, t.i. calling replace et.al. multiple times. As Sublime controls the cursor just perfect as long as the replaced region does not own a cursor, you only have to "fine" diff a hunk iff it contains one of the cursors which should be a good speed up computational-wise.

That's an unrequested wall of text. Take what you want out of it.

Regards

@mitranim
Copy link
Owner

mitranim commented May 13, 2021

Thank you for the tips! Will take some time to go through these, got a lot happening right now. 😅

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

No branches or pull requests

2 participants