Merged
Fix PageDown/Up overshoot on single soft-wrapped line#2085
Conversation
On a buffer that is one very long soft-wrapped line (e.g. a minified JS bundle), PageDown from the top jumped the caret straight to EOF, and the following Up jumped it back to the document start. handle_page_motion judged "did the viewport scroll?" by comparing only top_byte. For a single logical line, scrolling advances top_view_line_offset while top_byte stays 0, so the check always saw "no movement" and fell through to the logical-line MovePageDown handler, which clamps the caret to EOF. The off-screen caret then defeated the wrap-aware MoveUp intercept, so Up fell through to byte-based MoveUp and landed at byte 0. Detect viewport movement via the (top_byte, top_view_line_offset) pair, and land the caret at the source byte of the visual row now shown at the top of the viewport (new Viewport::top_visual_row_source_byte, which maps the wrap-segment offset back to a buffer byte). The helper defers to top_byte when plugin soft-breaks / virtual rows touch the line, leaving plugin and no-wrap behaviour unchanged. Reproduced by tests/semantic/page_motion_single_long_line.rs against a new single-long-line fixture: without the fix PageDown lands the caret at EOF and the following Up at byte 0; with the fix the caret stays roughly one page down.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On a buffer that is one very long soft-wrapped line (e.g. a minified JS
bundle), PageDown from the top jumped the caret straight to EOF, and the
following Up jumped it back to the document start.
handle_page_motion judged "did the viewport scroll?" by comparing only
top_byte. For a single logical line, scrolling advances
top_view_line_offset while top_byte stays 0, so the check always saw "no
movement" and fell through to the logical-line MovePageDown handler, which
clamps the caret to EOF. The off-screen caret then defeated the wrap-aware
MoveUp intercept, so Up fell through to byte-based MoveUp and landed at
byte 0.
Detect viewport movement via the (top_byte, top_view_line_offset) pair, and
land the caret at the source byte of the visual row now shown at the top of
the viewport (new Viewport::top_visual_row_source_byte, which maps the
wrap-segment offset back to a buffer byte). The helper defers to top_byte
when plugin soft-breaks / virtual rows touch the line, leaving plugin and
no-wrap behaviour unchanged.
Reproduced by tests/semantic/page_motion_single_long_line.rs against a new
single-long-line fixture: without the fix PageDown lands the caret at EOF
and the following Up at byte 0; with the fix the caret stays roughly one
page down.