From a6a2eca2b5de9af22a82aedbdaec0fcc6c129ee0 Mon Sep 17 00:00:00 2001 From: Murari007 Date: Thu, 4 Dec 2025 12:59:57 +0530 Subject: [PATCH 1/2] fix: terminate CLI process and cleanup buffer on close --- lua/gemini/init.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lua/gemini/init.lua b/lua/gemini/init.lua index 8b6d07c..498a000 100644 --- a/lua/gemini/init.lua +++ b/lua/gemini/init.lua @@ -17,6 +17,12 @@ local function close_gemini_window() if state.winnr and vim.api.nvim_win_is_valid(state.winnr) then vim.api.nvim_win_close(state.winnr, true) end + if state.chan_id then + vim.fn.jobstop(state.chan_id) + end + if state.bufnr and vim.api.nvim_buf_is_valid(state.bufnr) then + vim.api.nvim_buf_delete(state.bufnr, { force = true }) + end state.winnr = nil state.bufnr = nil state.chan_id = nil @@ -138,7 +144,7 @@ end function M.setup(opts) -- Merge user config with defaults config = vim.tbl_deep_extend("force", default_config, opts or {}) - + if vim.fn.executable("gemini") == 1 then vim.api.nvim_set_keymap( "n", @@ -166,5 +172,4 @@ function M.setup(opts) end end end - -return M \ No newline at end of file +return M From 84352a77e31b64b91450eb192c689e0b2ca3039c Mon Sep 17 00:00:00 2001 From: Murari007 Date: Sun, 7 Dec 2025 03:55:26 +0530 Subject: [PATCH 2/2] Add keybindings to focus to gemini chat window and imporved user interaction --- lua/gemini/init.lua | 89 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 19 deletions(-) diff --git a/lua/gemini/init.lua b/lua/gemini/init.lua index 498a000..36b299e 100644 --- a/lua/gemini/init.lua +++ b/lua/gemini/init.lua @@ -41,27 +41,37 @@ local function open_gemini_window() else vim.cmd("vsplit") end - vim.cmd("enew") - vim.cmd("setlocal buftype=nofile bufhidden=hide noswapfile") + state.winnr = vim.api.nvim_get_current_win() - state.bufnr = vim.api.nvim_get_current_buf() - vim.api.nvim_buf_set_name(state.bufnr, "gemini_cli") - - state.chan_id = vim.fn.termopen("gemini", { - env = { ["EDITOR"] = "nvim" }, - on_exit = function() - -- Check if the window is still valid before trying to close it - if state.winnr and vim.api.nvim_win_is_valid(state.winnr) then - local buf_in_win = vim.api.nvim_win_get_buf(state.winnr) - if buf_in_win == state.bufnr then - vim.api.nvim_win_close(state.winnr, true) + + -- Reuse existing buffer if valid and process is alive + if state.bufnr and vim.api.nvim_buf_is_valid(state.bufnr) and state.chan_id then + vim.api.nvim_win_set_buf(state.winnr, state.bufnr) + else + vim.cmd("enew") + vim.cmd("setlocal buftype=nofile bufhidden=hide noswapfile") + state.bufnr = vim.api.nvim_get_current_buf() + vim.api.nvim_buf_set_name(state.bufnr, "gemini_cli") + + -- Map Esc to exit terminal mode in the Gemini buffer + vim.api.nvim_buf_set_keymap(state.bufnr, "t", "", "", { noremap = true, silent = true }) + + state.chan_id = vim.fn.termopen("gemini", { + env = { ["EDITOR"] = "nvim" }, + on_exit = function() + -- Check if the window is still valid before trying to close it + if state.winnr and vim.api.nvim_win_is_valid(state.winnr) then + local buf_in_win = vim.api.nvim_win_get_buf(state.winnr) + if buf_in_win == state.bufnr then + vim.api.nvim_win_close(state.winnr, true) + end end - end - state.bufnr = nil - state.winnr = nil - state.chan_id = nil - end, - }) + state.bufnr = nil + state.winnr = nil + state.chan_id = nil + end, + }) + end end function M.toggle_gemini_cli() @@ -141,11 +151,40 @@ function M.send_to_gemini() end end +function M.gemini_chat_focus(mode) + if state.winnr and vim.api.nvim_win_is_valid(state.winnr) then + local current_win = vim.api.nvim_get_current_win() + local win_tab = vim.api.nvim_win_get_tabpage(state.winnr) + local current_tab = vim.api.nvim_get_current_tabpage() + + if win_tab ~= current_tab then + vim.api.nvim_set_current_tabpage(win_tab) + vim.api.nvim_set_current_win(state.winnr) + pcall(vim.cmd, "startinsert") + return + end + + if current_win == state.winnr then + if mode == "t" then + vim.cmd("wincmd p") + else + pcall(vim.cmd, "startinsert") + end + else + vim.api.nvim_set_current_win(state.winnr) + pcall(vim.cmd, "startinsert") + end + else + open_gemini_window() + end +end + function M.setup(opts) -- Merge user config with defaults config = vim.tbl_deep_extend("force", default_config, opts or {}) if vim.fn.executable("gemini") == 1 then + vim.cmd('command! GeminiChatFocus lua require("gemini").gemini_chat_focus()') vim.api.nvim_set_keymap( "n", "og", @@ -158,6 +197,18 @@ function M.setup(opts) ':lua require("gemini").send_to_gemini()', { noremap = true, silent = true, desc = "Send selection to Gemini" } ) + vim.api.nvim_set_keymap( + "n", + "gc", + 'lua require("gemini").gemini_chat_focus("n")', + { noremap = true, silent = true, desc = "Focus Gemini Chat" } + ) + vim.api.nvim_set_keymap( + "t", + "gc", + 'lua require("gemini").gemini_chat_focus("t")', + { noremap = true, silent = true, desc = "Focus Gemini Chat" } + ) else local answer = vim.fn.input("Gemini CLI not found. Install it now? (y/n): ") if answer:lower() == "y" then