Add OSC 133 imenu integration; fix line-mode scrollback navigation#243
Merged
Conversation
`consult-line', `consult-imenu', and any `goto-char' jump in line mode appeared to land on the target line and then snap back to the live cursor. `isearch' worked because it advances `window-start' as it scrolls. The minibuffer that consult opens resizes the ghostel window twice (open + close). Each resize forces a redraw with `ghostel--redraw-resize-active' = t. The predicate's resize branch classified a window as anchored whenever it was absent from `ghostel--scroll-positions', which was meant to cover Emacs's own `keep-point-visible' drift on `window-start' but ignored `window-point' entirely. After the user navigated point into scrollback, no plain redraw ran while the minibuffer was open, so `ghostel--scroll-positions' stayed empty; the closing resize then re-anchored the window and `ghostel--anchor-window' yanked `window-point' back to the live cursor. The fix is a `(>= window-point anchor)' guard on the resize branch. The drifted-`window-start' case still passes (point stays in the live viewport), the scrollback-jump case no longer does.
Each shell prompt with OSC 133 'A'/'B'/'C' markers becomes an imenu entry of the form "<cwd> <command>", with the target landing on the prompt prefix's start. Composes with `consult-imenu', `imenu-list', evil's `]m'/`[m', etc. The cwd is captured at OSC 133 'C' (command-start) and pushed onto a chronological list. Reading `default-directory' lazily at index time would mis-attribute every prior prompt to the current cwd after a `cd'. Position-based tracking (text properties or markers) does not survive: the renderer's per-row delete+reinsert wipes ad-hoc text properties on dirty rows, and `eraseBuffer' (resize-cols, force-full redraw, scrollback edge cases) collapses every marker to `point-min'. Pairing chronological cwds with the `ghostel-prompt' regions in buffer order at index time is robust to both: resize reflows the grid but preserves prompt order, and scrollback eviction is detected as (cwd-count > region-count) and trims the oldest cwds. Selecting an entry leaves line and copy modes untouched (the user is already free to navigate); only semi-char and char modes switch to emacs mode so point can move at all.
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
Two related changes — the second was discovered while testing the first.
1. Stop resize redraw from re-anchoring scrollback in line mode
consult-line,consult-imenu, and anygoto-charjump in line mode appeared to land on the target and then snap back to the live cursor.isearchworked because it advanceswindow-startas it scrolls.The minibuffer that consult opens resizes the ghostel window twice (open + close). Each resize forces a redraw with
ghostel--redraw-resize-active= t. The predicate's resize branch classified a window as anchored whenever it was absent fromghostel--scroll-positions— meant to cover Emacs's ownkeep-point-visibledrift onwindow-startbut ignoredwindow-pointentirely. After the user navigated point into scrollback, no plain redraw ran while the minibuffer was open, soghostel--scroll-positionsstayed empty; the closing resize then re-anchored the window and yankedwindow-pointback to the live cursor.Fix: a
window-point >= anchorguard on the resize branch. The drifted-window-startcase still passes; the scrollback-jump case no longer does.2. Add OSC 133 imenu integration
Each shell prompt with OSC 133 'A'/'B'/'C' markers becomes an imenu entry of the form
<cwd> <command>, target landing on the prompt prefix's start. Composes withconsult-imenu,imenu-list, evil's]m/[m, etc.The cwd is captured at OSC 133 'C' (command-start) and pushed onto a chronological list; reading
default-directorylazily at index time would mis-attribute every prior prompt to the current cwd after acd.Position-based tracking (text properties or markers) does not survive: the renderer's per-row delete+reinsert wipes ad-hoc text properties on dirty rows, and
eraseBuffer(resize-cols, force-full redraw, scrollback edge cases) collapses every marker topoint-min. Pairing chronological cwds with theghostel-promptregions in buffer order at index time is robust to both: resize reflows the grid but preserves prompt order; scrollback eviction is detected as(cwd-count > region-count)and trims the oldest cwds.Selecting an entry leaves line and copy modes untouched (the user is already free to navigate); only semi-char and char modes switch to emacs mode so point can move at all.
Test plan
make -j4 all— 331 elisp + 138 native tests pass; lint cleanghostel-test-redraw-resize-preserves-scrollback-jumpcovers the consult-line scenarioconsult-line,consult-imenu, plainimenuall stick on the target line in line mode