Follow live output while point rides the live edge (Emacs and line mode)#550
Open
dakra wants to merge 2 commits into
Open
Follow live output while point rides the live edge (Emacs and line mode)#550dakra wants to merge 2 commits into
dakra wants to merge 2 commits into
Conversation
dakra
force-pushed
the
feat/emacs-mode-follow-output
branch
from
July 19, 2026 21:10
c154692 to
ca7027d
Compare
dakra
force-pushed
the
feat/emacs-mode-follow-output
branch
from
July 19, 2026 21:24
ca7027d to
e242144
Compare
Emacs mode windows now scroll with new terminal output as long as window-point sits on the live cursor (and no region is active); any navigation off the cursor stops the following and the window stays where the user put it. The redraw path decides "was following" before the native render advances the cursor away from the preserved window-point and passes that decision to the anchor as a new FOLLOWING argument; all other anchor call sites self-check at anchor time.
Line mode's selected window now stops following live output the moment point leaves the live edge — the input region while composing, or the terminal cursor / end of output while a command runs — instead of drifting until the reading position hits the top of the window. M->, clicking the prompt, or typing resumes the follow. Windows not selected in their frame carry no user intent in their window-point and keep the geometric follow rule. The per-mode follow decision is centralized in the new ghostel--window-follows-p, used by both the pre-render anchored snapshot and the anchor gate. The line-mode restore no longer moves a point parked outside the input region, so async output cannot teleport point back to the prompt while reading scrollback. The Emacs-mode region veto now also covers a window whose buffer is not shown in the selected window (its selection would otherwise be dragged by the anchor); a non-selected window sharing the selected window's buffer still rides. The line-mode prompt-lost message is only emitted when pending input was actually forwarded.
dakra
force-pushed
the
feat/emacs-mode-follow-output
branch
2 times, most recently
from
July 25, 2026 10:41
13a25d2 to
8bb3ece
Compare
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.
Two commits: the same two-state follow rule ("follow while point rides the live edge, stop the moment it leaves") for Emacs mode and for line mode.
Emacs mode
Emacs mode (
C-c C-e) is read-only but live, yet the window never followed new output — entering it mid-stream froze the viewport while output piled up below the fold.Now an Emacs-mode window scrolls with the live output for as long as its point rides the terminal cursor, matching what semi-char users see at the prompt:
window-pointsits exactly on the live cursor (or atpoint-max), indefinitely.C-p, an isearch, or activating the region freezes the view exactly where you are while the buffer keeps growing.M->(ghostel-readonly-end-of-buffer) now lands on the cursor whenever the cursor sits past the last non-whitespace character (in copy mode too), so an end-of-buffer jump picks the follow back up.Line mode
Line mode had the same problem in a different shape: its follow rule was purely geometric, so moving point up during streaming produced drift-then-jolt — the view kept scrolling while your line drifted toward the top,
window-startovershot past point, redisplay snapped your line to the top row, and the follow died. Separately, with pending typed input, every redraw's restore teleported point back to the prompt while you were reading scrollback.Now the selected line-mode window follows only while point rides the live edge:
point-maxwhile a command runs; afterRETthe collapsed input region keeps the follow alive through the whole stream.M->, clicking the prompt, or simply typing (self-insertsnaps point into the input region).window-pointcarries no user intent, so a backgroundmakesplit keeps scrolling to the bottom.Implementation notes
ghostel--window-follows-p(Emacs → point on cursor, selected line-mode window → point on live edge, everything else → follows), used by both the pre-render window snapshot and the anchor gate.ghostel--redraw-nowand carried past the native render via aFOLLOWINGargument toghostel--anchor-window— post-render, the cursor has already advanced away from the preservedwindow-point, so a late check would always fail. All other anchor call sites self-check at anchor time, which keeps minibuffer-driven jumps (e.g.consult-line) from being yanked back.point-max(prompt tail behind a moved-back readline cursor, TUI rows below the cursor) does not count as riding, so it is never stomped. An active region vetoes the follow except in a non-selected window sharing the selected window's buffer (where the anchor cannot drag the region), so a selection is never silently extended by live output — including in a window you switched away from.Verification
New ERT tests for both modes (follow self-sustains across redraws, stop/resume, riding-position semantics, per-window independence, non-selected line-mode window keeps following, restore keeps an away-point,
M->landing incl. narrowing) plus live end-to-end sessions for each mode. The line-mode live matrix: composing at the prompt during background redraws (point and input untouched), instant stop onC-pmid-stream withwindow-start/window-pointfrozen whilepoint-maxgrows,M->resume, post-RETfollow through a full stream, and geometric follow of the non-selected split window — all sampled structurally, no drift/jolt/teleport observed.