Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 37 additions & 50 deletions lua/claudecode/terminal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -129,31 +129,17 @@ end
-- Cleans up state if invalid.
-- @local
-- @return boolean True if valid, false otherwise.
local function is_fallback_terminal_valid()
-- First check if we have a valid buffer
if not managed_fallback_terminal_bufnr or not vim.api.nvim_buf_is_valid(managed_fallback_terminal_bufnr) then
cleanup_fallback_terminal_state()
local function is_fallback_terminal_window_valid()
if not managed_fallback_terminal_winid or not vim.api.nvim_win_is_valid(managed_fallback_terminal_winid) then
return false
end
return true
end

-- If buffer is valid but window is invalid, try to find a window displaying this buffer
if not managed_fallback_terminal_winid or not vim.api.nvim_win_is_valid(managed_fallback_terminal_winid) then
-- Search all windows for our terminal buffer
local windows = vim.api.nvim_list_wins()
for _, win in ipairs(windows) do
if vim.api.nvim_win_get_buf(win) == managed_fallback_terminal_bufnr then
-- Found a window displaying our terminal buffer, update the tracked window ID
managed_fallback_terminal_winid = win
require("claudecode.logger").debug("terminal", "Recovered terminal window ID:", win)
return true
end
end
-- Buffer exists but no window displays it
cleanup_fallback_terminal_state()
local function is_fallback_terminal_buffer_valid()
if not managed_fallback_terminal_bufnr or not vim.api.nvim_buf_is_valid(managed_fallback_terminal_bufnr) then
return false
end

-- Both buffer and window are valid
return true
end

Expand All @@ -164,7 +150,7 @@ end
-- @param effective_term_config table Configuration for split_side and split_width_percentage.
-- @return boolean True if successful, false otherwise.
local function open_fallback_terminal(cmd_string, env_table, effective_term_config)
if is_fallback_terminal_valid() then -- Should not happen if called correctly, but as a safeguard
if is_fallback_terminal_window_valid() then -- Should not happen if called correctly, but as a safeguard
vim.api.nvim_set_current_win(managed_fallback_terminal_winid)
vim.cmd("startinsert")
return true
Expand Down Expand Up @@ -254,7 +240,7 @@ end
--- Closes the managed fallback terminal if it's open and valid.
-- @local
local function close_fallback_terminal()
if is_fallback_terminal_valid() then
if is_fallback_terminal_window_valid() then
-- Closing the window should trigger on_exit of the job if the process is still running,
-- which then calls cleanup_fallback_terminal_state.
-- If the job already exited, on_exit would have cleaned up.
Expand All @@ -267,7 +253,7 @@ end
--- Focuses the managed fallback terminal if it's open and valid.
-- @local
local function focus_fallback_terminal()
if is_fallback_terminal_valid() then
if is_fallback_terminal_window_valid() then
vim.api.nvim_set_current_win(managed_fallback_terminal_winid)
vim.cmd("startinsert")
end
Expand Down Expand Up @@ -424,7 +410,9 @@ function M.close()
-- managed_snacks_terminal will be set to nil by the on_close callback
end
elseif provider == "native" then
close_fallback_terminal()
if is_fallback_terminal_window_valid() then
close_fallback_terminal()
end
end
end

Expand Down Expand Up @@ -481,7 +469,7 @@ function M.toggle(opts_override)
end
end
elseif provider == "native" then
if is_fallback_terminal_valid() then
if is_fallback_terminal_window_valid() then
local claude_term_neovim_win_id = managed_fallback_terminal_winid
local current_neovim_win_id = vim.api.nvim_get_current_win()

Expand All @@ -491,14 +479,11 @@ function M.toggle(opts_override)
vim.api.nvim_set_current_win(claude_term_neovim_win_id)
vim.cmd("startinsert")
end
elseif is_fallback_terminal_buffer_valid() then
open_window_for_buffer(managed_fallback_terminal_bufnr, effective_config)
else
local existing_buf = find_existing_terminal_buffer_by_name()
if existing_buf then
open_window_for_buffer(existing_buf, effective_config)
else
if not open_fallback_terminal(cmd_string, claude_env_table, effective_config) then
vim.notify("Failed to open Claude terminal using native fallback (toggle).", vim.log.levels.ERROR)
end
if not open_fallback_terminal(cmd_string, claude_env_table, effective_config) then
vim.notify("Failed to open Claude terminal using native fallback (toggle).", vim.log.levels.ERROR)
end
end
end
Expand All @@ -522,13 +507,32 @@ function M.get_active_terminal_bufnr()
end
end

if is_fallback_terminal_valid() then
if is_fallback_terminal_buffer_valid() then
return managed_fallback_terminal_bufnr
end

return nil
end




--- Finds the existing Claude terminal buffer, even if it's not in a window.
-- @local
-- @return number|nil The buffer number if found, otherwise nil.
local function find_existing_terminal_buffer_by_name()
local buffers = vim.api.nvim_list_bufs()
for _, buf in ipairs(buffers) do
if vim.api.nvim_buf_is_valid(buf) and vim.bo[buf].buftype == 'terminal' then
local buf_name = vim.api.nvim_buf_get_name(buf)
if buf_name:match("claude") then
return buf
end
end
end
return nil
end

--- Opens a window for an existing buffer.
-- @local
-- @param bufnr number The buffer number to open.
Expand Down Expand Up @@ -561,20 +565,3 @@ local function open_window_for_buffer(bufnr, effective_term_config)
vim.cmd("startinsert")
end

return M

--- Finds the existing Claude terminal buffer, even if it's not in a window.
-- @local
-- @return number|nil The buffer number if found, otherwise nil.
local function find_existing_terminal_buffer_by_name()
local buffers = vim.api.nvim_list_bufs()
for _, buf in ipairs(buffers) do
if vim.api.nvim_buf_is_valid(buf) and vim.bo[buf].buftype == 'terminal' then
local buf_name = vim.api.nvim_buf_get_name(buf)
if buf_name:match("claude") then
return buf
end
end
end
return nil
end
Loading