fix(editor): keep caret at end-of-line on Up/Down navigation#12674
Open
VictorVow wants to merge 2 commits into
Open
fix(editor): keep caret at end-of-line on Up/Down navigation#12674VictorVow wants to merge 2 commits into
VictorVow wants to merge 2 commits into
Conversation
When the caret was at the end of a block's line and the user pressed Up/Down to move to the adjacent block, cross-boundary navigation captured only the numeric column offset and replayed it verbatim in the target block. If the target line was longer than that column, the caret landed mid-line instead of staying at the end of the line. Add a `cursor/end-of-line?` predicate (symmetric with the existing `beginning-of-line?`). `move-cross-boundary-up-down` now passes an `:end` sentinel instead of the column when the source caret is at end-of-line, and `text-range-by-lst-fst-line` maps `:end` to the whole content (`:up` -> end of the target's last line) or its first line (`:down` -> end of the target's first line). The numeric-`pos` path is unchanged, so mid-line up/down still preserves the column. Add unit coverage for `text-range-by-lst-fst-line` over both directions, the `:end` sentinel, and a numeric-pos non-regression case.
Multi-line blocks lost end-of-line stickiness when navigating Up/Down between hard lines inside the same block: the pixel/mock-text based next-cursor-pos-up-down only matches the nearest horizontal position, so from the end of one line the caret landed mid-line on a longer adjacent line instead of at its end. This "If EOL, always move cursor to previous/next EOL" behavior existed in the original newline-arithmetic implementation but was dropped in 237857a when up/down moved to pixel-position navigation (which was needed for soft-wrapped rows and proportional/wide glyphs). Restore it as a targeted guard rather than a revert: add a pure cursor/adjacent-line-end-pos helper and, in move-cursor-up-down, when the caret is at end-of-line jump to the end of the adjacent hard line; otherwise fall back to the existing pixel navigation so soft-wrap and mid-line movement are unchanged. select-up-down is untouched. Add frontend.util.cursor-test covering adjacent-line-end-pos across both directions, no-adjacent-line cases, single-line content, and the land-at-end-regardless-of-length case. Companion to e49f5ad, which fixed the same behavior across block boundaries.
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.
Summary
Details
cursor/end-of-line?predicate, symmetric with the existingbeginning-of-line?.handler/editor.cljsmove-cross-boundary-up-down→handler/block.cljstext-range-by-lst-fst-line): pass an:endsentinel when the source caret is at EOL, so it lands at the end of the adjacent block's edge line (last line for:up, first line for:down). The numeric-column path is unchanged.util/cursor.cljsmove-cursor-up-down): when at EOL, jump to the end of the adjacent hard line via the new pureadjacent-line-end-pos; otherwise fall back to the existing pixel/mock-text navigation, so soft-wrapped rows and mid-line movement are unchanged.select-up-downis untouched.Test plan
frontend.handler.block-test,frontend.util-test, and newfrontend.util.cursor-test— 12 tests / 74 assertions, 0 failures, 0 errors.clj-kondoclean on all changed files; node-test build compiles with 0 warnings.