Fix normal-state point tracking during terminal output in evil-ghostel#529
Merged
Conversation
The #454 anchor veto compares point against ghostel--cursor-char-pos after the render, when the cursor has already advanced past output that the buffer had not rendered when point was last placed - during streaming output the comparison always differs, the anchor is permanently vetoed, and point strands in scrollback (the #228 symptom, reintroduced by 0a539fb after a6c0500 dropped the original last-cursor-line heuristic). Sample the parked check pre-render in evil-ghostel--around-redraw instead: while point sits exactly at the previous frame's cursor in normal/motion state (semi-char, window following), snap it to the new cursor after the render. The window check is pre-render too - a multi-line burst un-anchors the window until point snaps - and the snap targets ghostel--cursor-char-pos directly, since move-to-column can diverge from the terminal's cell widths on wide glyphs and would disengage tracking. Point moved off the cursor still stays put, and the anchor veto then keeps the viewport from being yanked back (#454). Fixes #228.
Exact-position tracking disengages when point sits one char off the cursor on the same row - most commonly evil's normal-state EOL adjust after a keypress at a quiet prompt - and async output (background jobs, agents streaming without a fresh RET) then strands point in scrollback. Follow the cursor row-wise when point is elsewhere on its row: ride to the new cursor's row and restore the user's column instead of snapping onto the cursor. Row membership is sampled pre-render alongside the parked check. Off the cursor's row point still stays put, and the anchor veto still keeps the viewport from being yanked back (#454); the viewport follows via redisplay in the row-roaming case. The tracking matrix's esc-clamp group flips from xfail to pass, and a new row-roam group pins the kept-column behavior against a background burst.
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
#228 regressed (reported in the latest comment): in evil normal state, point parked at the prompt stopped following the live cursor during output and stranded in scrollback.
Regression chain:
6a96954fixed Cursor goes up with output in pi coding agent in normal state #228 with alast-cursor-lineheuristic in the redraw advice.a6c0500(command-remap rewrite) dropped it; tracking fell to the core anchor, which over-tracked and caused Cleaner extension point for evil/normal-state roaming over an animated terminal (anchor + wheel scroll)? #454.0a539fb(Cleaner extension point for evil/normal-state roaming over an animated terminal (anchor + wheel scroll)? #454 fix) added the anchor veto comparing(point)againstghostel--cursor-char-pos— but after the render, when the cursor has already advanced while point stayed at its old text position. During streaming output the comparison always differs, the anchor is permanently vetoed, and point strands.Fix
Commit 1 — parked tracking. Sample the parked check pre-render in
evil-ghostel--around-redraw, where point andghostel--cursor-char-posare still same-frame values (no skew). While parked, snap point to the new cursor withgoto-char ghostel--cursor-char-pos(exact by construction; column geometry can diverge on wide glyphs). The window-anchored guard is sampled pre-render too — a multi-line burst un-anchors the window until point snaps, which otherwise latches tracking off. Point moved off the cursor still stays put, and the veto keeps the viewport from being yanked back (#454 contract).Commit 2 — row-wise tracking. Point elsewhere on the cursor's row (most commonly evil's EOL adjust parking point at cursor−1 after a keypress at a quiet prompt) follows row-wise: it rides to the new cursor's row and keeps its column. This closes the async-output gap (background jobs / agents streaming without a fresh RET) and matches the "prompt line" behavior discussed in #228.
Tests
test/elate/matrix/tracking-ghostel.json(7 groups: parked stream/burst, roamed, re-engage, esc-clamp, row-roam) — the operator matrix never exercises redraw-time point placement, which is why it stayed green through the regression. Verified red on the pre-fix code (3 groups fail) and fully green with both commits.make -j8 allgreen.