fix(terminal): stop Snacks climbing cursor on hide/show toggle (#240, #183)#271
Conversation
|
@codex review |
|
@claude review |
…183) Hiding and re-showing the Claude panel with the Snacks provider left the terminal cursor one row above Claude's prompt, so typed text landed on the wrong line and the prompt box corrupted. Root cause: Snacks hides by closing the window and shows by recreating it via open_win(); that recreate shifts the cursor anchor Claude (Ink) re-renders against on the focus-in event Neovim sends on show. It is not a pty resize. Manage hide/show without destroying the window: - float: park via nvim_win_set_config({hide=true/false}) (needs nvim-0.10) - split: close on hide, recreate with vsplit + nvim_win_set_buf on show, like the native provider (which does not drift); set full height, re-apply Snacks' window-local options, and keep the buffer so the <S-CR> map survives Also monkeypatch the Snacks instance hide/show/toggle so user-wired Snacks keymaps (e.g. self:hide()) get the fix, and make is_terminal_visible() treat a config-hidden window as not visible so ensure_visible/diff/send re-show a parked float. Splits are fixed on all supported Neovim versions; the float fix requires nvim-0.10 (pre-0.10 floats keep prior behavior). Adds tests/unit/terminal/snacks_toggle_spec.lua covering the float/split hide-show paths, config-hidden visibility, E444-safe close, and the externally-closed-float-reopens-as-float case. Change-Id: I71c521935460fc9fec0eaa45823a2c91002b4d8d Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
Self-contained agent-tty reproduction of the Snacks climbing-cursor bug: - init.lua: minimal LazyVim-style Snacks fixture (provider/position/cmd env knobs) - box.py: auth-free instrument that enables focus reporting and logs every input byte + SIGWINCH, proving the trigger is focus churn on window recreate, not a pty resize - agent-repro.sh: drives a real Claude CLI and prints the cursor-vs-prompt delta per toggle for snacks (split & float) vs native - README.md: verdict, root-cause chain, and measured results Change-Id: I2596d57c56b22d937e744e6be56f42a7735666fa Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0f4d156b84
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0f4d156 to
b258097
Compare
…eview) cc_show recreated every split as a vsplit driven by split_side, so a snacks_win_opts.position = "top"/"bottom" terminal silently turned into a left/right vertical split after the first hide/show. Recreate now honors the resolved Snacks position: left/right -> vertical split, top/bottom -> horizontal split sized from snacks_win_opts.height; float and any other position delegate back to Snacks (which owns that geometry). Adds resolve_split_size and unit tests for the horizontal-split and unsupported-position paths. Change-Id: I2087a82e04bd56cc85977051102aa722ba67bdcf Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@claude review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
What
Fixes the "climbing cursor" in the Snacks terminal: hiding and re-showing the Claude panel left the terminal cursor one row above Claude's
❯prompt, so typed text landed on the wrong line and the box visually corrupted.Closes #240 (vertical split)
Closes #183 (floating window — same root cause)
Root cause
Instrumented end-to-end (real Claude CLI driven via agent-tty). The trigger is not a pty resize — there is zero
SIGWINCHon toggle. Instead:nvim_win_close) and shows by recreating it (open_win).ESC[I) to the child (Claude enables DECSET?1004).Controls confirm the layering: focus change alone (no hide/show) does not drift, and an absolute-positioning TUI does not drift under the same churn — only Claude does, consistent with the community report that downgrading Claude to
2.0.76makes it disappear. The native provider does not exhibit it.The fix
Manage hide/show without destroying the window, preserving the cursor anchor:
nvim_win_set_config({ hide = true/false })(window kept alive; requires Neovim ≥ 0.10).vsplit+nvim_win_set_bufon show — the native-provider path, which doesn't drift. Sets full height, re-applies Snacks' window-local options, and reuses the buffer so the<S-CR>newline map survives. Works on all supported Neovim versions.hide/show/toggleare monkeypatched so user-wired Snacks keymaps (e.g.self:hide()) also benefit.is_terminal_visible()now treats a config-hidden window as not visible, soensure_visible/ diff /@-mention-send re-show a parked float.Verification
fixtures/cursor-toggle-repro/agent-repro.sh, real Claude 2.1.x): cursor-vs-promptdeltaafter each toggle — snacks split 0→0 (was 0→1), snacks float 0→0 + panel truly hides, native unchanged.mise run all: 494 tests / 0 failures, luacheck + treefmt clean.tests/unit/terminal/snacks_toggle_spec.lua): float/split hide-show, config-hidden visibility, E444-safe close, externally-closed-float-reopens-as-float, open-reuse.Review
Ran a multi-dimension adversarial review (correctness / Snacks API / regression / portability / style) over the diff; applied the confirmed findings: float-reopens-as-float, E444-safe split close, full-height parity, fixbuf-autocmd ordering, re-applying window-local options, buffer-identity check, per-branch debug logging, plus this CHANGELOG entry. Re-gated green afterwards.
Notes / scope
fixtures/cursor-toggle-repro/is included as reproduction evidence (auth-free instrument + real-Claude harness), mirroring the existingpaste-repro/snacks-explorerfixtures.🤖 Generated with Claude Code