feat(nvim): auto-quit when only NERDTree/dadbod/Claude Code remain

After closing the file you were working on, if every remaining window
in the (only) tab is NERDTree, the dadbod-ui browser, or the Claude
Code terminal, there's nothing left to edit — a WinClosed autocmd
force-quits (qa!) rather than leaving you staring at bare utility
sidebars. qa! also bypasses the "terminal job still running" prompt
for the live Claude Code process; nothing there is a real file buffer.

Verified live: closing a file while another real file window remains
does not quit; closing the last real file with only utility windows
left (individually tested with NERDTree, dadbod-ui, and a
claude-named terminal buffer) does.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
main
Amir Alexander Abdelbaki 2026-07-23 11:31:59 +02:00
parent f769ed5e7d
commit a8b98166cf
2 changed files with 39 additions and 0 deletions

View File

@ -97,6 +97,12 @@ Claude Code can write files outside `claudecode.nvim`'s diff-review pipeline (pl
Unmodified buffers reload silently; buffers with unsaved local edits still get Vim's normal "changed outside Vim" (`W11`) prompt instead of being clobbered. Unmodified buffers reload silently; buffers with unsaved local edits still get Vim's normal "changed outside Vim" (`W11`) prompt instead of being clobbered.
### Auto-Quit When Only Utility Windows Remain
A `WinClosed` autocmd checks, after every window close, whether every window left in the (only) tab is one of NERDTree, the dadbod-ui browser, or the Claude Code terminal. If so — nothing left to edit — it runs `:qa!` outright, including skipping the "terminal job still running" confirmation that would otherwise block quitting while Claude Code's process is alive.
Scoped to just those three; a real file window anywhere in the tab (or a second tab) always blocks the auto-quit.
### Keybindings ### Keybindings
All custom bindings live in `nvim/init.lua`. Leader is `<Space>` (`vim.g.mapleader = " "`) — Space otherwise duplicates `l` (move right) in normal mode, so it was free to claim. All custom bindings live in `nvim/init.lua`. Leader is `<Space>` (`vim.g.mapleader = " "`) — Space otherwise duplicates `l` (move right) in normal mode, so it was free to claim.

View File

@ -191,6 +191,39 @@ vim.api.nvim_create_autocmd("User", {
command = "checktime", command = "checktime",
}) })
-- quit outright once only plugin/utility windows remain ─────────────────────
-- After closing the file you were working on, if NERDTree, the dadbod-ui
-- browser, and/or the Claude Code terminal are the only windows left in the
-- (only) tab, there's nothing left to edit. qa! also skips the "terminal job
-- still running" confirmation for the Claude Code process; nothing here is a
-- real file buffer, so there's nothing to lose.
local function _is_utility_win(win)
local buf = vim.api.nvim_win_get_buf(win)
local ft = vim.bo[buf].filetype
if ft == "nerdtree" or ft == "dbui" then
return true
end
if vim.bo[buf].buftype == "terminal" then
return vim.api.nvim_buf_get_name(buf):match("claude") ~= nil
end
return false
end
vim.api.nvim_create_autocmd("WinClosed", {
callback = function()
-- defer: the closed window is still mid-teardown when WinClosed fires
vim.schedule(function()
if vim.fn.tabpagenr("$") > 1 then return end
local wins = vim.api.nvim_tabpage_list_wins(0)
if #wins == 0 then return end
for _, w in ipairs(wins) do
if not _is_utility_win(w) then return end
end
vim.cmd("qa!")
end)
end,
})
-- calendar.vim steals <C-hjkl> for month nav; restore window movement -- calendar.vim steals <C-hjkl> for month nav; restore window movement
-- The plugin sets buffer-local mappings on FileType calendar, so we override -- The plugin sets buffer-local mappings on FileType calendar, so we override
-- them with { buffer = true } mappings of our own that fire after the plugin's. -- them with { buffer = true } mappings of our own that fire after the plugin's.