Never scroll the live cursor out of view when anchoring#548
Open
dakra wants to merge 1 commit into
Open
Conversation
On a fresh terminal (cursor near the top, trailing blank grid rows), a window-shrinking minibuffer deferred the terminal resize but still re-anchored: bottom-aligning point-max pushed the cursor row above window-start, redisplay clamped window-point off the cursor, and the minibuffer-exit check misread the pure point move as user navigation, flipping the buffer into copy mode and stomping the echo area. Fix the anchor instead of the check (no marker can distinguish redisplay's point clamp from a user jump): - ghostel--anchor-window computes one (START . VSCROLL) from the pixel or line-count path, clamps START to the cursor's line, and zeroes the vscroll whenever the cursor sits on the top line. A no-op whenever the cursor is at or below the bottom-aligned start. - ghostel--window-anchored-p also counts a window as anchored when window-start sits exactly on the (capped) cursor's line, so a clamped window keeps auto-following. The check is stateless, recomputed from live data on every call. - ghostel-semi-char-mode/ghostel-char-mode run goto-char before the forced anchor, so the anchor's point placement (the live cursor) wins and exiting copy mode cannot leave point off the cursor. - ghostel-maybe-leave-input compares point against the capped cursor position, so a stale cursor beyond point-max cannot fake a jump.
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.
Problem
On a fresh terminal (cursor near the top, trailing blank grid rows), any window-shrinking minibuffer (vertico/fido
M-x,find-file,read-string, …) misbehaved twice:Root cause:
ghostel--adjust-sizedefers the terminal resize during a minibuffer but still re-anchors. Bottom-aligningpoint-maxin the shrunken window pushed the cursor row abovewindow-start; redisplay then clamped window-point off the cursor — a pure point move no marker can track — and the deferred minibuffer-exit check misread it as user navigation.Fix
Fix the anchor rather than the check (redisplay's clamp is indistinguishable from a user jump):
ghostel--anchor-windowcomputes one(START . VSCROLL)from the pixel (GUI) or line-count (TTY) path, clampsSTARTto the live cursor's line, and zeroes the vscroll whenever the cursor sits on the top line. One-directional: a byte-for-byte no-op whenever the cursor is at or below the bottom-aligned start (normal streaming, TUIs, filled scrollback).ghostel--window-anchored-palso counts a window as anchored whenwindow-startsits exactly on the (capped) cursor's line, so a clamped window keeps auto-following. Stateless — recomputed from live data on every call, nothing to record or go stale.ghostel-semi-char-mode/ghostel-char-moderungoto-charbefore the forced anchor, so the anchor's point placement (the live cursor) wins and exiting copy mode cannot leave point off the cursor.ghostel-maybe-leave-inputcompares point against the capped cursor position, so a stale cursor beyondpoint-maxcannot fake a jump.Deliberate navigation (e.g.
goto-charafterread-string, leaving isearch away from the prompt) still enters copy mode; line mode and theghostel-inhibit-anchor-functionsveto (evil-ghostel) are untouched.Tests
Five new tests in
test/ghostel-modes-test.el(clamp, no-op at bottom, nil/stale cursor, anchored-p recognition, end-to-end no-flip regression), sharing a fixture macro the existing force-anchor test was ported onto.Verification
make -j8 allgreen; evil-ghostel 124/124.M-x text-modeshows the guard error with no copy flip;M-x ignorestays semi-char with the prompt visible andwindow-vscroll0 while the minibuffer is open; copy-mode exit lands point on the cursor; filled-scrollback, isearch, and auto-follow paths unchanged.