Skip to content

Commit bcf7e43

Browse files
committed
fix: address Copilot feedback on terminal focus behavior
- Add optional focus parameter to both snacks and native provider open() methods - Extract shared logic into ensure_terminal_visible_no_focus() helper function - Fix ensure_visible() to truly not focus by passing focus=false to providers - Fix toggle_open_no_focus() to use the same consistent no-focus behavior - Maintain backward compatibility by defaulting focus parameter to true - Return to original window in native provider when focus=false Addresses feedback about ensure_visible() contradicting its intent by calling provider.open() which always focused the terminal. Change-Id: I11635699095df7284232b7c959ade1e11c41dbc4 Signed-off-by: Thomas Kosiewski <[email protected]>
1 parent ff08290 commit bcf7e43

File tree

5 files changed

+70
-51
lines changed

5 files changed

+70
-51
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ For most users, the default configuration is sufficient:
283283
-- Connection Management
284284
connection_wait_delay = 200, -- Wait time after connection before sending queued @ mentions (ms)
285285
connection_timeout = 10000, -- Max time to wait for Claude Code connection (ms)
286-
queue_timeout = 3000, -- Max time to keep @ mentions in queue (ms)
286+
queue_timeout = 5000, -- Max time to keep @ mentions in queue (ms)
287287

288288
-- Terminal Configuration
289289
terminal = {

dev-config.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ return {
4848
-- Connection Management
4949
-- connection_wait_delay = 200, -- Wait time after connection before sending queued @ mentions (ms)
5050
-- connection_timeout = 10000, -- Max time to wait for Claude Code connection (ms)
51-
-- queue_timeout = 3000, -- Max time to keep @ mentions in queue (ms)
51+
-- queue_timeout = 5000, -- Max time to keep @ mentions in queue (ms)
5252

5353
-- Diff Integration
5454
-- diff_opts = {

lua/claudecode/terminal.lua

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,27 @@ local function get_claude_command_and_env(cmd_args)
151151
return cmd_string, env_table
152152
end
153153

154+
--- Common helper to open terminal without focus if not already visible
155+
--- @param opts_override table|nil Optional config overrides
156+
--- @param cmd_args string|nil Optional command arguments
157+
--- @return boolean True if terminal was opened or already visible
158+
local function ensure_terminal_visible_no_focus(opts_override, cmd_args)
159+
local provider = get_provider()
160+
local active_bufnr = provider.get_active_bufnr()
161+
162+
if is_terminal_visible(active_bufnr) then
163+
-- Terminal is already visible, do nothing
164+
return true
165+
end
166+
167+
-- Terminal is not visible, open it without focus
168+
local effective_config = build_config(opts_override)
169+
local cmd_string, claude_env_table = get_claude_command_and_env(cmd_args)
170+
171+
provider.open(cmd_string, claude_env_table, effective_config, false) -- false = don't focus
172+
return true
173+
end
174+
154175
--- Configures the terminal module.
155176
-- Merges user-provided terminal configuration with defaults and sets the terminal command.
156177
-- @param user_term_config table (optional) Configuration options for the terminal.
@@ -240,39 +261,14 @@ end
240261
-- @param opts_override table (optional) Overrides for terminal appearance (split_side, split_width_percentage).
241262
-- @param cmd_args string|nil (optional) Arguments to append to the claude command.
242263
function M.toggle_open_no_focus(opts_override, cmd_args)
243-
local provider = get_provider()
244-
245-
-- Check if terminal is already visible
246-
local active_bufnr = provider.get_active_bufnr()
247-
if is_terminal_visible(active_bufnr) then
248-
-- Terminal is already visible, do nothing
249-
return
250-
end
251-
252-
-- Terminal is not visible, open it without focus
253-
local effective_config = build_config(opts_override)
254-
local cmd_string, claude_env_table = get_claude_command_and_env(cmd_args)
255-
256-
provider.open(cmd_string, claude_env_table, effective_config)
264+
ensure_terminal_visible_no_focus(opts_override, cmd_args)
257265
end
258266

259267
--- Ensures terminal is visible without changing focus. Creates if necessary, shows if hidden.
260268
-- @param opts_override table (optional) Overrides for terminal appearance (split_side, split_width_percentage).
261269
-- @param cmd_args string|nil (optional) Arguments to append to the claude command.
262270
function M.ensure_visible(opts_override, cmd_args)
263-
local provider = get_provider()
264-
local effective_config = build_config(opts_override)
265-
local cmd_string, claude_env_table = get_claude_command_and_env(cmd_args)
266-
267-
-- Check if terminal exists and is visible
268-
local active_bufnr = provider.get_active_bufnr()
269-
if is_terminal_visible(active_bufnr) then
270-
-- Terminal is already visible, do nothing
271-
return
272-
end
273-
274-
-- Terminal is not visible or doesn't exist, create/show it
275-
provider.open(cmd_string, claude_env_table, effective_config)
271+
ensure_terminal_visible_no_focus(opts_override, cmd_args)
276272
end
277273

278274
--- Toggles the Claude terminal open or closed (legacy function - use simple_toggle or focus_toggle).

lua/claudecode/terminal/native.lua

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,14 @@ local function is_valid()
4545
return true
4646
end
4747

48-
local function open_terminal(cmd_string, env_table, effective_config)
48+
local function open_terminal(cmd_string, env_table, effective_config, focus)
49+
focus = focus == nil and true or focus -- Default to true for backward compatibility
50+
4951
if is_valid() then -- Should not happen if called correctly, but as a safeguard
50-
vim.api.nvim_set_current_win(winid)
51-
vim.cmd("startinsert")
52+
if focus then
53+
vim.api.nvim_set_current_win(winid)
54+
vim.cmd("startinsert")
55+
end
5256
return true
5357
end
5458

@@ -121,8 +125,13 @@ local function open_terminal(cmd_string, env_table, effective_config)
121125
vim.bo[bufnr].bufhidden = "wipe" -- Wipe buffer when hidden (e.g., window closed)
122126
-- buftype=terminal is set by termopen
123127

124-
vim.api.nvim_set_current_win(winid)
125-
vim.cmd("startinsert")
128+
if focus then
129+
vim.api.nvim_set_current_win(winid)
130+
vim.cmd("startinsert")
131+
else
132+
-- Return to original window if not focusing
133+
vim.api.nvim_set_current_win(original_win)
134+
end
126135

127136
if config.show_native_term_exit_tip and not tip_shown then
128137
vim.notify("Native terminal opened. Press Ctrl-\\ Ctrl-N to return to Normal mode.", vim.log.levels.INFO)
@@ -251,9 +260,14 @@ end
251260
--- @param cmd_string string
252261
--- @param env_table table
253262
--- @param effective_config table
254-
function M.open(cmd_string, env_table, effective_config)
263+
--- @param focus boolean|nil
264+
function M.open(cmd_string, env_table, effective_config, focus)
265+
focus = focus == nil and true or focus -- Default to true for backward compatibility
266+
255267
if is_valid() then
256-
focus_terminal()
268+
if focus then
269+
focus_terminal()
270+
end
257271
else
258272
-- Check if there's an existing Claude terminal we lost track of
259273
local existing_buf, existing_win = find_existing_claude_terminal()
@@ -263,9 +277,11 @@ function M.open(cmd_string, env_table, effective_config)
263277
winid = existing_win
264278
-- Note: We can't recover the job ID easily, but it's less critical
265279
logger.debug("terminal", "Recovered existing Claude terminal")
266-
focus_terminal()
280+
if focus then
281+
focus_terminal()
282+
end
267283
else
268-
if not open_terminal(cmd_string, env_table, effective_config) then
284+
if not open_terminal(cmd_string, env_table, effective_config, focus) then
269285
vim.notify("Failed to open Claude terminal using native fallback.", vim.log.levels.ERROR)
270286
end
271287
end

lua/claudecode/terminal/snacks.lua

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ end
4343

4444
--- @param config table
4545
--- @param env_table table
46+
--- @param focus boolean|nil
4647
--- @return table
47-
local function build_opts(config, env_table)
48+
local function build_opts(config, env_table, focus)
49+
focus = focus == nil and true or focus -- Default to true for backward compatibility
4850
return {
4951
env = env_table,
50-
start_insert = true,
51-
auto_insert = true,
52+
start_insert = focus,
53+
auto_insert = focus,
5254
auto_close = false,
5355
win = {
5456
position = config.split_side,
@@ -66,27 +68,32 @@ end
6668
--- @param cmd_string string
6769
--- @param env_table table
6870
--- @param config table
69-
function M.open(cmd_string, env_table, config)
71+
--- @param focus boolean|nil
72+
function M.open(cmd_string, env_table, config, focus)
7073
if not is_available() then
7174
vim.notify("Snacks.nvim terminal provider selected but Snacks.terminal not available.", vim.log.levels.ERROR)
7275
return
7376
end
7477

78+
focus = focus == nil and true or focus -- Default to true for backward compatibility
79+
7580
if terminal and terminal:buf_valid() then
76-
terminal:focus()
77-
local term_buf_id = terminal.buf
78-
if term_buf_id and vim.api.nvim_buf_get_option(term_buf_id, "buftype") == "terminal" then
79-
-- Check if window is valid before calling nvim_win_call
80-
if terminal.win and vim.api.nvim_win_is_valid(terminal.win) then
81-
vim.api.nvim_win_call(terminal.win, function()
82-
vim.cmd("startinsert")
83-
end)
81+
if focus then
82+
terminal:focus()
83+
local term_buf_id = terminal.buf
84+
if term_buf_id and vim.api.nvim_buf_get_option(term_buf_id, "buftype") == "terminal" then
85+
-- Check if window is valid before calling nvim_win_call
86+
if terminal.win and vim.api.nvim_win_is_valid(terminal.win) then
87+
vim.api.nvim_win_call(terminal.win, function()
88+
vim.cmd("startinsert")
89+
end)
90+
end
8491
end
8592
end
8693
return
8794
end
8895

89-
local opts = build_opts(config, env_table)
96+
local opts = build_opts(config, env_table, focus)
9097
local term_instance = Snacks.terminal.open(cmd_string, opts)
9198
if term_instance and term_instance:buf_valid() then
9299
setup_terminal_events(term_instance, config)

0 commit comments

Comments
 (0)