Skip to content

Follow live output while point rides the live edge (Emacs and line mode)#550

Open
dakra wants to merge 2 commits into
mainfrom
feat/emacs-mode-follow-output
Open

Follow live output while point rides the live edge (Emacs and line mode)#550
dakra wants to merge 2 commits into
mainfrom
feat/emacs-mode-follow-output

Conversation

@dakra

@dakra dakra commented Jul 19, 2026

Copy link
Copy Markdown
Owner

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:

  • Follows while window-point sits exactly on the live cursor (or at point-max), indefinitely.
  • Stops the moment point moves off the cursor — one C-p, an isearch, or activating the region freezes the view exactly where you are while the buffer keeps growing.
  • Resumes when point returns to the cursor: 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-start overshot 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:

  • Follows while point sits in the prompt's input region (composing), or on the terminal cursor / point-max while a command runs; after RET the collapsed input region keeps the follow alive through the whole stream.
  • Stops instantly when point leaves the live edge — no drift, no overshoot, no snap.
  • Resumes via M->, clicking the prompt, or simply typing (self-insert snaps point into the input region).
  • Windows not selected in their frame keep the old geometric rule — their window-point carries no user intent, so a background make split keeps scrolling to the bottom.
  • The redraw restore no longer moves a point parked outside the input region, so async output can't yank point back to the prompt.

Implementation notes

  • The per-mode follow decision is centralized in 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.
  • The follow decision is made by the pre-render snapshot in ghostel--redraw-now and carried past the native render via a FOLLOWING argument to ghostel--anchor-window — post-render, the cursor has already advanced away from the preserved window-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 parked between the cursor and 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.
  • Composes with the cursor-clamp anchoring from 7aa53db.

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 on C-p mid-stream with window-start/window-point frozen while point-max grows, M-> resume, post-RET follow through a full stream, and geometric follow of the non-selected split window — all sampled structurally, no drift/jolt/teleport observed.

@dakra
dakra force-pushed the feat/emacs-mode-follow-output branch from c154692 to ca7027d Compare July 19, 2026 21:10
@dakra dakra changed the title Make Emacs mode follow live output while point rides the cursor Follow live output while point rides the live edge (Emacs and line mode) Jul 19, 2026
@dakra
dakra force-pushed the feat/emacs-mode-follow-output branch from ca7027d to e242144 Compare July 19, 2026 21:24
dakra added 2 commits July 25, 2026 12:19
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
dakra force-pushed the feat/emacs-mode-follow-output branch 2 times, most recently from 13a25d2 to 8bb3ece Compare July 25, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant