Conversation
Fixes #992 When line wrapping is enabled and the file ends with a trailing newline, Ctrl+End moves the cursor to the correct byte position (document end) but the viewport didn't scroll far enough — the empty final line was hidden below the visible area. Root cause: ViewLineIterator intentionally skipped the trailing empty view line (produced after the last source newline), so the cursor at buffer_len had no corresponding view line. find_view_line_for_byte mapped it to the previous content line instead. Fix: - ViewLineIterator now emits one trailing empty ViewLine when the last token was a source newline (representing a real document line) - find_view_line_for_byte maps cursor positions past all source bytes to the trailing empty view line - Backward visual-row scan in ensure_visible uses prev() directly instead of prev()+next_line()+prev() to avoid pending_trailing_empty_line interference in LineIterator Co-Authored-By: Claude Opus 4.6 <[email protected]>
After Ctrl+End → Left → Down, the cursor should return to the empty trailing line. Without the ViewLineIterator fix this fails because the trailing empty line has no view line for the cursor to land on. Co-Authored-By: Claude Opus 4.6 <[email protected]>
After Ctrl+End → Left → Down, the cursor should reach the trailing empty line. At wider terminal sizes (135x37) with the real CSV content, Down does nothing — the cursor stays on the last visual row of the previous line. Uses the actual olney-book-1.csv to reproduce. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Two issues prevented the Down key from moving the cursor to the trailing empty line (after a file's final '\n') when line wrapping is on: 1. The trailing empty ViewLine got line_end_byte = prev_line_end_byte (the \n byte) instead of buffer_len. This made move_visual_line return the same position the cursor was already on — a no-op. Fix: detect LineStart::AfterSourceNewline and set line_end_byte to buffer_len. 2. When the screen is full and the trailing empty line isn't rendered, no ViewLineMapping existed for it, so move_visual_line returned None at the boundary. Fix: always push the mapping when the last rendered line ends with a newline. Co-Authored-By: Claude Opus 4.6 <[email protected]>
When the ViewLineIterator emits the trailing empty line (after a file's trailing '\n'), resolve_cursor_fallback placed the cursor at last_line_end.y + 1 — assuming the last rendered line was the content line before the empty line. But with the iterator fix, the trailing empty line IS the last rendered line, so + 1 overshoots to a tilde row. Fix: only add 1 when terminated_with_newline is true (last rendered line was the newline-terminated content line); use the position directly when the trailing empty line was already rendered. Co-Authored-By: Claude Opus 4.6 <[email protected]>
6bc6b82 to
4284952
Compare
…s in viewport slices ViewLineIterator unconditionally emitted a trailing empty ViewLine after the last source newline, even when the tokens represented a viewport window into the middle of a buffer. This broke tests that relied on exact line counts for mid-buffer views. Add an `at_buffer_end` parameter to ViewLineIterator::new(). Only emit the trailing empty line when the token stream actually covers the buffer end. Also reset next_line_start when tokens are exhausted without a Newline/Break so content like "\nX" doesn't spuriously trigger the trailing line. In the renderer, detect the iterator's trailing empty ViewLine and skip the duplicate implicit-line rendering, preserve last_line_end tracking, and fix the cursor-at-end fallback (use buffer.len() instead of 0 for empty lines). Co-Authored-By: Claude Opus 4.6 <[email protected]>
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.
Fixes #992
When line wrapping is enabled and the file ends with a trailing newline, Ctrl+End moves the cursor to the correct byte position (document end) but the viewport didn't scroll far enough — the empty final line was hidden below the visible area.
Root cause: ViewLineIterator intentionally skipped the trailing empty view line (produced after the last source newline), so the cursor at buffer_len had no corresponding view line. find_view_line_for_byte mapped it to the previous content line instead.
Fix: