Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fix PageDown/Up overshoot on single soft-wrapped line#2085

Merged
sinelaw merged 1 commit into
mastersinelaw/fresh:masterfrom
claude/bold-noether-7DLpPsinelaw/fresh:claude/bold-noether-7DLpPCopy head branch name to clipboard
May 24, 2026
Merged

Fix PageDown/Up overshoot on single soft-wrapped line#2085
sinelaw merged 1 commit into
mastersinelaw/fresh:masterfrom
claude/bold-noether-7DLpPsinelaw/fresh:claude/bold-noether-7DLpPCopy head branch name to clipboard

Conversation

@sinelaw

@sinelaw sinelaw commented May 24, 2026

Copy link
Copy Markdown
Owner

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.

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.
@sinelaw
sinelaw merged commit e45e469 into master May 24, 2026
8 checks 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.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.