Skip to content

Commit d6af885

Browse files
committed
refactor: improve terminal toggle logic
1 parent c1cdcd5 commit d6af885

File tree

1 file changed

+54
-47
lines changed

1 file changed

+54
-47
lines changed

lua/claudecode/terminal.lua

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -354,36 +354,6 @@ local function get_claude_command_and_env()
354354
return cmd_string, env_table
355355
end
356356

357-
--- Find any existing Claude Code terminal buffer by checking terminal job command
358-
-- @local
359-
-- @return number|nil Buffer number if found, nil otherwise
360-
local function find_existing_claude_terminal()
361-
local buffers = vim.api.nvim_list_bufs()
362-
for _, buf in ipairs(buffers) do
363-
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_option(buf, "buftype") == "terminal" then
364-
-- Check if this is a Claude Code terminal by examining the buffer name or terminal job
365-
local buf_name = vim.api.nvim_buf_get_name(buf)
366-
-- Terminal buffers often have names like "term://..." that include the command
367-
if buf_name:match("claude") then
368-
-- Additional check: see if there's a window displaying this buffer
369-
local windows = vim.api.nvim_list_wins()
370-
for _, win in ipairs(windows) do
371-
if vim.api.nvim_win_get_buf(win) == buf then
372-
require("claudecode.logger").debug(
373-
"terminal",
374-
"Found existing Claude terminal in buffer",
375-
buf,
376-
"window",
377-
win
378-
)
379-
return buf, win
380-
end
381-
end
382-
end
383-
end
384-
end
385-
return nil, nil
386-
end
387357

388358
--- Opens or focuses the Claude terminal.
389359
-- @param opts_override table (optional) Overrides for terminal appearance (split_side, split_width_percentage).
@@ -516,26 +486,15 @@ function M.toggle(opts_override)
516486
local current_neovim_win_id = vim.api.nvim_get_current_win()
517487

518488
if claude_term_neovim_win_id == current_neovim_win_id then
519-
close_fallback_terminal()
489+
vim.api.nvim_win_hide(claude_term_neovim_win_id)
520490
else
521-
focus_fallback_terminal() -- This already calls startinsert
491+
vim.api.nvim_set_current_win(claude_term_neovim_win_id)
492+
vim.cmd("startinsert")
522493
end
523494
else
524-
-- Check if there's an existing Claude terminal we lost track of
525-
local existing_buf, existing_win = find_existing_claude_terminal()
526-
if existing_buf and existing_win then
527-
-- Recover the existing terminal
528-
managed_fallback_terminal_bufnr = existing_buf
529-
managed_fallback_terminal_winid = existing_win
530-
require("claudecode.logger").debug("terminal", "Recovered existing Claude terminal in toggle")
531-
532-
-- Check if we're currently in this terminal
533-
local current_neovim_win_id = vim.api.nvim_get_current_win()
534-
if existing_win == current_neovim_win_id then
535-
close_fallback_terminal()
536-
else
537-
focus_fallback_terminal()
538-
end
495+
local existing_buf = find_existing_terminal_buffer_by_name()
496+
if existing_buf then
497+
open_window_for_buffer(existing_buf, effective_config)
539498
else
540499
if not open_fallback_terminal(cmd_string, claude_env_table, effective_config) then
541500
vim.notify("Failed to open Claude terminal using native fallback (toggle).", vim.log.levels.ERROR)
@@ -570,4 +529,52 @@ function M.get_active_terminal_bufnr()
570529
return nil
571530
end
572531

532+
--- Opens a window for an existing buffer.
533+
-- @local
534+
-- @param bufnr number The buffer number to open.
535+
-- @param effective_term_config table Configuration for split_side and split_width_percentage.
536+
local function open_window_for_buffer(bufnr, effective_term_config)
537+
local original_win = vim.api.nvim_get_current_win()
538+
539+
local width = math.floor(vim.o.columns * effective_term_config.split_width_percentage)
540+
local full_height = vim.o.lines
541+
local placement_modifier
542+
543+
if effective_term_config.split_side == "left" then
544+
placement_modifier = "topleft "
545+
else
546+
placement_modifier = "botright "
547+
end
548+
549+
vim.cmd(placement_modifier .. width .. "vsplit")
550+
551+
local new_winid = vim.api.nvim_get_current_win()
552+
553+
vim.api.nvim_win_set_height(new_winid, full_height)
554+
555+
vim.api.nvim_win_set_buf(new_winid, bufnr)
556+
557+
managed_fallback_terminal_winid = new_winid
558+
managed_fallback_terminal_bufnr = bufnr
559+
560+
vim.api.nvim_set_current_win(managed_fallback_terminal_winid)
561+
vim.cmd("startinsert")
562+
end
563+
573564
return M
565+
566+
--- Finds the existing Claude terminal buffer, even if it's not in a window.
567+
-- @local
568+
-- @return number|nil The buffer number if found, otherwise nil.
569+
local function find_existing_terminal_buffer_by_name()
570+
local buffers = vim.api.nvim_list_bufs()
571+
for _, buf in ipairs(buffers) do
572+
if vim.api.nvim_buf_is_valid(buf) and vim.bo[buf].buftype == 'terminal' then
573+
local buf_name = vim.api.nvim_buf_get_name(buf)
574+
if buf_name:match("claude") then
575+
return buf
576+
end
577+
end
578+
end
579+
return nil
580+
end

0 commit comments

Comments
 (0)