vim.api.nvim_create_user_command("SmartQuit", function(opts) -- scan all buffers for unsaved buffers local unsaved = {} local saved = {} for _, buf in ipairs(vim.api.nvim_list_bufs()) do if vim.api.nvim_buf_is_loaded(buf) and vim.api.nvim_buf_get_option(buf, "buflisted") then if vim.api.nvim_buf_get_option(buf, "modified") then table.insert(unsaved, buf) else table.insert(saved, buf) end end end if #unsaved == 0 then vim.cmd("qa") return end -- gui for resolving unsaved files local lines = {} for _, buf in ipairs(unsaved) do local full_path = vim.api.nvim_buf_get_name(buf) local name = full_path == "" and ("[No Name] #" .. buf) or vim.fn.fnamemodify(full_path, ":~:.") table.insert(lines, " • " .. name) end table.insert(lines, "") table.insert(lines, " s - Save all and quit") table.insert(lines, " c - Close saved; leave unsaved open") table.insert(lines, " d - DISCARD ALL") local buf = vim.api.nvim_create_buf(false, true) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) vim.api.nvim_buf_set_option(buf, "readonly", true) local width = math.max(unpack(vim.tbl_map(function(l) return #l end, lines))) local height = #lines local win = vim.api.nvim_open_win(buf, true, { relative = "editor", width = width + 1, height = height, row = (vim.o.lines - height) / 2 - 1, col = (vim.o.columns - width) / 2, style = "minimal", border = "rounded", title = { { #unsaved .. " Unsaved Buffer" .. (#unsaved != 1 and "s" or "") .. "!", "ErrorMsg" }, }, title_pos = "center", }) vim.wo[win].winhighlight = "Normal:Normal,FloatBorder:ErrorMsg" vim.api.nvim_win_set_option(win, "cursorline", false) local hl = vim.api.nvim_get_hl_by_name('Cursor', true) hl.blend = 100 vim.api.nvim_set_hl(0, 'Cursor', hl) vim.opt.guicursor:append('a:Cursor/lCursor') function close() local hl = vim.api.nvim_get_hl_by_name('Cursor', true) hl.blend = 0 vim.api.nvim_set_hl(0, 'Cursor', hl) vim.opt.guicursor:remove('a:Cursor/lCursor') vim.api.nvim_win_close(win, true) end -- keyboard event handlers vim.keymap.set("n", "s", function() for _, buf in ipairs(unsaved) do vim.api.nvim_buf_call(buf, function() vim.cmd("write") end) end close() vim.cmd("qa") end, { buffer = buf }) vim.keymap.set("n", "c", function() for _, buf in ipairs(saved) do vim.api.nvim_buf_delete(buf, {}) end close() end, { buffer = buf }) vim.keymap.set("n", "d", function() vim.cmd("qa!") end, { buffer = buf }) vim.keymap.set("n", "", function() close() end, { buffer = buf }) vim.api.nvim_create_autocmd({ 'WinLeave' }, { buffer = buf, callback = close, }) end, { nargs = 0 }) vim.api.nvim_set_hl(0, "QuitPopUpBorder", { fg = "red" })