Skip to content

Conversation

@ThomasK33
Copy link
Member

Fixes #150.

When diff_opts.keep_terminal_focus = true and the Claude terminal is a floating window (e.g. Snacks position="float"), opening a diff no longer steals focus to the hidden diff split.

Changes

  • Allow find_claudecode_terminal_window() to fall back to floating windows (still preferring split terminals)
  • Avoid resizing floating terminals when restoring terminal widths
  • Add a unit regression test for floating-terminal focus

Tests

  • make check
  • make test

📋 Implementation Plan

Plan: Investigate + fix #150 (keep_terminal_focus skips floating terminal windows)

Context / Why

Issue #150 reports that when diff_opts.keep_terminal_focus = true and the Claude terminal is displayed as a floating window (e.g. via Snacks snacks_win_opts = { position = "float" }), opening a diff steals focus to the diff split behind the float. Because focus never returns to the terminal, user input goes to the hidden diff window and the UX breaks.

Goal: confirm whether this is a bug (vs expected behavior) and, if so, outline a safe fix + regression coverage.

Evidence (what was verified)

  • GitHub issue [BUG] keep_terminal_focus = true skips floating windows #150 text explicitly points to find_claudecode_terminal_window() in lua/claudecode/diff.lua as skipping floats.
  • lua/claudecode/diff.lua:
    • find_claudecode_terminal_window() currently returns the terminal window only if it is not floating (checks win_config.relative).
    • setup_new_buffer() uses this helper under diff_opts.keep_terminal_focus to restore focus after opening a diff.
  • Config intent: lua/claudecode/config.lua documents diff_opts.keep_terminal_focus as “moves focus back to terminal after diff opens”, with no caveat about floating windows.

Bug assessment

Confirmed bug.

With keep_terminal_focus = true, the plugin intends to refocus the Claude terminal after creating the diff window. When the terminal lives in a floating window, find_claudecode_terminal_window() returns nil, so the scheduled refocus never happens. This matches the issue report and is inconsistent with the documented meaning of keep_terminal_focus.

Implementation plan (fix + prove)

1) Add a regression test that fails on current main

Add a unit test that simulates a floating terminal window:

  • Test location: add to an existing diff blocking spec (e.g. tests/unit/diff_mcp_spec.lua) or create a focused new spec (e.g. tests/unit/diff_keep_terminal_focus_float_spec.lua).
  • Arrange:
    • diff.setup({ diff_opts = { keep_terminal_focus = true } }).
    • Stub package.loaded["claudecode.terminal"] = { get_active_terminal_bufnr = function() return TERM_BUF end }.
    • Create a terminal buffer in the vim mock (vim.api.nvim_create_buf) and a floating window entry for it by setting vim._windows[TERM_WIN].config = { relative = "editor" } and ensuring TERM_WIN is in vim._tab_windows[current_tab].
  • Act: call diff.open_diff_blocking(...) inside a coroutine and coroutine.resume once (it should suspend after setup).
  • Assert: after the first resume, vim.api.nvim_get_current_win() (or vim._current_window) should equal TERM_WIN.
    • This fails today because the float is filtered out.

Optional: add a second assertion for the non-floating case to ensure we don’t regress existing behavior.

2) Fix find_claudecode_terminal_window() to support floats

In lua/claudecode/diff.lua, update the helper so that it can return floating windows:

  • Preferred behavior:
    • If multiple windows show the terminal buffer, prefer a non-floating window.
    • Otherwise, fall back to the floating window.

This preserves the original intent (prefer split terminals) while making keep_terminal_focus work for floats.

Fix sketch (for the implementer)
  • Iterate windows; when buf == terminal_bufnr:
    • If win_config.relative is empty/nil → return immediately.
    • Else store as floating_fallback.
  • After loop: return floating_fallback.

3) Ensure terminal-resize code remains sane for floats

find_claudecode_terminal_window() is also used in diff cleanup and terminal width restoration paths.

  • Decide whether resizing should apply to floats:
    • If yes: do nothing special (current width logic is “percentage of columns” and is valid for floats too).
    • If no: gate nvim_win_set_width calls behind win_config.relative == "".

Whichever behavior is chosen, add/adjust a test so the behavior is explicit.

4) Validate locally

  • Run: make test, make check.
  • Manual sanity check:
    • Configure Snacks terminal as float and diff_opts.keep_terminal_focus = true.
    • Trigger a diff (via Claude suggestion / openDiff tool).
    • Confirm focus stays/returns to the float terminal and typing goes to the terminal, not the hidden diff.

5) Close the loop on the issue


Generated with mux • Model: openai:gpt-5.2 • Thinking: xhigh

Fixes #150 by allowing terminal focus restoration when the Claude terminal is shown in a floating window (e.g. Snacks).

Adds a regression test and avoids resizing floating terminals when restoring widths.

Change-Id: I24229878842c383624e3e7e51ab7c7c5f02f3c60
Signed-off-by: Thomas Kosiewski <tk@coder.com>
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.

[BUG] keep_terminal_focus = true skips floating windows

1 participant