authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2025-08-21 01:57:32-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2025-08-21 01:57:32-07:00
logb34edc3a519a0efebb9f39e24b0998d98309c99c
tree55e78e2f38ff331eb94991423d51dcd58e92d6df
parent1052a1ccc3d91a32648090733bef9d1ae6819c55

feat(vim): Smart quit popup

space q will close the application if all buffers are saved, otherwise a dialog box shows up with the buffers that are not saved.

7 files changed, 157 insertions(+), 43 deletions(-)

modules/neovim/commands/FullscreenTerm.lua created+27
...@@ -0,0 +1,27 @@
1-- Ported from https://www.reddit.com/r/neovim/comments/vemydn
2vim.api.nvim_create_user_command("FullscreenTerm", function(opts)
3 vim.cmd("tab terminal " .. opts.args)
4 local laststatus = vim.o.laststatus
5 local showtabline = vim.o.showtabline
6 local cmdheight = vim.o.cmdheight
7 vim.o.laststatus = 0
8 vim.o.cmdheight = 0
9 vim.o.showtabline = 0
10 vim.wo.signcolumn = "no"
11 vim.wo.relativenumber = false
12 vim.wo.number = false
13 vim.cmd(
14 "autocmd! TermClose <buffer=abuf> "
15 .. "if !v:event.status"
16 .. " | exec 'bd! '..expand('<abuf>')"
17 .. " | endif"
18 .. " | checktime"
19 .. " | set laststatus="
20 .. laststatus
21 .. " | set cmdheight="
22 .. cmdheight
23 .. " | set showtabline="
24 .. showtabline
25 )
26 vim.cmd("startinsert")
27end, { nargs = "*" })
modules/neovim/commands/SmartQuit.lua created+96
...@@ -0,0 +1,96 @@
1vim.api.nvim_create_user_command("SmartQuit", function(opts)
2 -- scan all buffers for unsaved buffers
3 local unsaved = {}
4 local saved = {}
5 for _, buf in ipairs(vim.api.nvim_list_bufs()) do
6 if vim.api.nvim_buf_is_loaded(buf) and vim.api.nvim_buf_get_option(buf, "buflisted") then
7 if vim.api.nvim_buf_get_option(buf, "modified") then
8 table.insert(unsaved, buf)
9 else
10 table.insert(saved, buf)
11 end
12 end
13 end
14
15 if #unsaved == 0 then
16 vim.cmd("qa")
17 return
18 end
19
20 -- gui for resolving unsaved files
21 local lines = {}
22 for _, buf in ipairs(unsaved) do
23 local full_path = vim.api.nvim_buf_get_name(buf)
24 local name = full_path == "" and ("[No Name] #" .. buf) or vim.fn.fnamemodify(full_path, ":~:.")
25 table.insert(lines, " • " .. name)
26 end
27 table.insert(lines, "")
28 table.insert(lines, " s - Save all and quit")
29 table.insert(lines, " c - Close saved; leave unsaved open")
30 table.insert(lines, " d - DISCARD ALL")
31
32 local buf = vim.api.nvim_create_buf(false, true)
33 vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
34 vim.api.nvim_buf_set_option(buf, "readonly", true)
35 local width = math.max(unpack(vim.tbl_map(function(l) return #l end, lines)))
36 local height = #lines
37 local win = vim.api.nvim_open_win(buf, true, {
38 relative = "editor",
39 width = width + 1,
40 height = height,
41 row = (vim.o.lines - height) / 2 - 1,
42 col = (vim.o.columns - width) / 2,
43 style = "minimal",
44 border = "rounded",
45 title = {
46 { #unsaved .. " Unsaved Buffer" .. (#unsaved != 1 and "s" or "") .. "!", "ErrorMsg" },
47 },
48 title_pos = "center",
49 })
50
51 vim.wo[win].winhighlight = "Normal:Normal,FloatBorder:ErrorMsg"
52 vim.api.nvim_win_set_option(win, "cursorline", false)
53
54 local hl = vim.api.nvim_get_hl_by_name('Cursor', true)
55 hl.blend = 100
56 vim.api.nvim_set_hl(0, 'Cursor', hl)
57 vim.opt.guicursor:append('a:Cursor/lCursor')
58
59 function close()
60 local hl = vim.api.nvim_get_hl_by_name('Cursor', true)
61 hl.blend = 0
62 vim.api.nvim_set_hl(0, 'Cursor', hl)
63 vim.opt.guicursor:remove('a:Cursor/lCursor')
64 vim.api.nvim_win_close(win, true)
65 end
66
67 -- keyboard event handlers
68 vim.keymap.set("n", "s", function()
69 for _, buf in ipairs(unsaved) do
70 vim.api.nvim_buf_call(buf, function()
71 vim.cmd("write")
72 end)
73 end
74 close()
75 vim.cmd("qa")
76 end, { buffer = buf })
77 vim.keymap.set("n", "c", function()
78 for _, buf in ipairs(saved) do
79 vim.api.nvim_buf_delete(buf, {})
80 end
81 close()
82 end, { buffer = buf })
83 vim.keymap.set("n", "d", function()
84 vim.cmd("qa!")
85 end, { buffer = buf })
86 vim.keymap.set("n", "<esc>", function()
87 close()
88 end, { buffer = buf })
89
90 vim.api.nvim_create_autocmd({ 'WinLeave' }, {
91 buffer = buf,
92 callback = close,
93 })
94end, { nargs = 0 })
95
96vim.api.nvim_set_hl(0, "QuitPopUpBorder", { fg = "red" })
modules/neovim/default.nix+16-2
...@@ -20,7 +20,8 @@...@@ -20,7 +20,8 @@
20 # which allows user configurations to disable/override anything here.20 # which allows user configurations to disable/override anything here.
21 config.vim = lib.mkOverride 999 {21 config.vim = lib.mkOverride 999 {
22 extraLuaFiles = [22 extraLuaFiles = [
23 ./lib.lua23 ./commands/FullscreenTerm.lua
24 ./commands/SmartQuit.lua
24 ];25 ];
2526
26 theme = {27 theme = {
...@@ -57,7 +58,7 @@...@@ -57,7 +58,7 @@
57 lspkind.enable = config.vim.autocomplete.blink-cmp.enable;58 lspkind.enable = config.vim.autocomplete.blink-cmp.enable;
58 # Enables inlay hints (types info in rust and shit)59 # Enables inlay hints (types info in rust and shit)
59 inlayHints.enable = true;60 inlayHints.enable = true;
60 #Nice mappings that i use :361 # Nice mappings that I use :3
61 mappings = {62 mappings = {
62 codeAction = "<leader>ca";63 codeAction = "<leader>ca";
63 goToDeclaration = "gD";64 goToDeclaration = "gD";
...@@ -114,6 +115,19 @@...@@ -114,6 +115,19 @@
114 setupOpts = {115 setupOpts = {
115 enable_cursor_hijack = true;116 enable_cursor_hijack = true;
116 git_status_async = true;117 git_status_async = true;
118 close_if_last_window = true;
119 filesystem.filtered_items = {
120 # dotfiles are often used for project configuration
121 hide_dotfiles = false;
122 never_show = [
123 ".DS_Store" # macOS
124 "thumbs.db" # Windows
125 ];
126 never_show_by_pattern = [
127 ".*.swp"
128 "._*" # macOS
129 ];
130 };
117 };131 };
118 };132 };
119 fzf-lua = {133 fzf-lua = {
modules/neovim/keybind.nix+1
...@@ -21,6 +21,7 @@ in...@@ -21,6 +21,7 @@ in
21 toggle-explorer = keyCmd "n" "<leader>e" "Neotree toggle";21 toggle-explorer = keyCmd "n" "<leader>e" "Neotree toggle";
22 reveal-active-file = keyCmd "n" "<leader>E" "Neotree reveal<CR>:Neotree focus";22 reveal-active-file = keyCmd "n" "<leader>E" "Neotree reveal<CR>:Neotree focus";
23 lazygit = keyCmd "n" "<leader>gg" "FullscreenTerm ${pkgs.lazygit}/bin/lazygit";23 lazygit = keyCmd "n" "<leader>gg" "FullscreenTerm ${pkgs.lazygit}/bin/lazygit";
24 smart-quit = keyCmd "n" "<leader>q" "SmartQuit";
2425
25 # pickers26 # pickers
26 pick-file = keyCmd "n" "<leader><leader>" "FzfLua files";27 pick-file = keyCmd "n" "<leader><leader>" "FzfLua files";
modules/neovim/lib.lua deleted-27
...@@ -1,27 +0,0 @@
1-- Ported from https://www.reddit.com/r/neovim/comments/vemydn
2vim.api.nvim_create_user_command("FullscreenTerm", function(opts)
3 vim.cmd("tab terminal " .. opts.args)
4 local laststatus = vim.o.laststatus
5 local showtabline = vim.o.showtabline
6 local cmdheight = vim.o.cmdheight
7 vim.o.laststatus = 0
8 vim.o.cmdheight = 0
9 vim.o.showtabline = 0
10 vim.wo.signcolumn = "no"
11 vim.wo.relativenumber = false
12 vim.wo.number = false
13 vim.cmd(
14 "autocmd! TermClose <buffer=abuf> "
15 .. "if !v:event.status"
16 .. " | exec 'bd! '..expand('<abuf>')"
17 .. " | endif"
18 .. " | checktime"
19 .. " | set laststatus="
20 .. laststatus
21 .. " | set cmdheight="
22 .. cmdheight
23 .. " | set showtabline="
24 .. showtabline
25 )
26 vim.cmd("startinsert")
27end, { nargs = "*" })
users/clover/vim.nix+16-14
...@@ -1,20 +1,22 @@...@@ -1,20 +1,22 @@
1_: {1_: {
2 vim = {2 vim = {
3 options = {3 languages.lua.enable = false; # broken
4 linebreak = true;4 options.linebreak = true;
5 };5 git.gitsigns.setupOpts = {
6 git = {6 current_line_blame = false;
7 gitsigns.setupOpts = {7 current_line_blame_opts = {
8 current_line_blame = false;8 virt_text = true;
9 current_line_blame_opts = {9 virt_text_pos = "right_align";
10 virt_text = true;10 delay = 25;
11 virt_text_pos = "right_align";11 ignore_whitespace = true;
12 delay = 25;12 virt_text_priority = 100;
13 ignore_whitespace = true;13 use_focus = true;
14 virt_text_priority = 100;
15 use_focus = true;
16 };
17 };14 };
18 };15 };
16 # filetree.neo-tree.setupOpts.default_component_configs.indent = {
17 # padding = 0;
18 # indent_marker = "|";
19 # last_indent_marker = "+";
20 # };
19 };21 };
20}22}
users/natalie/vim/languages.nix+1
...@@ -11,6 +11,7 @@...@@ -11,6 +11,7 @@
11 python312Packages.pylatexenc11 python312Packages.pylatexenc
12 ];12 ];
13 languages = {13 languages = {
14 lua.lsp.enable = true;
14 lua.lsp.lazydev.enable = true;15 lua.lsp.lazydev.enable = true;
15 python = {16 python = {
16 format.type = "ruff";17 format.type = "ruff";