From a876a827b493e43f6af2262f7e0ae7b479e2e41c Mon Sep 17 00:00:00 2001
From: Luca Bilke <luca@asmara.fritz.box>
Date: Thu, 25 Jan 2024 01:25:00 +0100
Subject: [PATCH] get back old buf_kill, add todo

---
 .config/nvim/lua/config/keymaps.lua |  1 -
 .config/nvim/lua/funcs.lua          | 72 +++++++++++++++++++++++++++--
 .config/nvim/todo                   |  2 +-
 3 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/.config/nvim/lua/config/keymaps.lua b/.config/nvim/lua/config/keymaps.lua
index 04d00c39..81c6f0d0 100644
--- a/.config/nvim/lua/config/keymaps.lua
+++ b/.config/nvim/lua/config/keymaps.lua
@@ -28,7 +28,6 @@ maps.n["\\"] = { "<cmd>split<cr>", desc = "Horizontal split" }
 maps.v["<"] = { "<gv", desc = "Unindent line" }
 maps.v[">"] = { ">gv", desc = "Indent line" }
 maps.n["<Leader>q"] = { f.buf_close, desc = "Close buffer" }
-maps.n["<Leader>Q"] = { function() f.buf_close(0, true) end, desc = "Force close buffer" }
 maps.n["<C-b>"] = { "<C-a>" }
 maps.n["<C-f>"] = { "<Nop>" }
 maps.i["<C-h>"] = { "<C-W>" }
diff --git a/.config/nvim/lua/funcs.lua b/.config/nvim/lua/funcs.lua
index 39799717..e8a77bcc 100644
--- a/.config/nvim/lua/funcs.lua
+++ b/.config/nvim/lua/funcs.lua
@@ -16,9 +16,73 @@ function M.set_title()
 end
 
 function M.buf_close(bufnr, force)
-    if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
-    local buftype = vim.api.nvim_get_option_value("buftype", { buf = bufnr })
-    vim.cmd(("silent! %s %d"):format((force or buftype == "terminal") and "bdelete!" or "confirm bdelete", bufnr))
+    local kill_command = "bd"
+
+    local bo = vim.bo
+    local api = vim.api
+    local fnamemodify = vim.fn.fnamemodify
+
+    if bufnr == 0 or bufnr == nil then
+        bufnr = api.nvim_get_current_buf()
+    end
+
+    local bufname = api.nvim_buf_get_name(bufnr)
+
+    if not force then
+        local warning
+        if bo[bufnr].modified then
+            warning = string.format([[No write since last change for (%s)]], fnamemodify(bufname, ":t"))
+        elseif api.nvim_buf_get_option(bufnr, "buftype") == "terminal" then
+            warning = string.format([[Terminal %s will be killed]], bufname)
+        end
+        if warning then
+            vim.ui.input({
+                prompt = string.format([[%s. Close it anyway? [y]es or [n]o (default: no): ]], warning),
+            }, function(choice)
+                if choice:match "ye?s?" then force = true end
+            end)
+            if not force then return end
+        end
+    end
+
+    -- Get list of window IDs with the buffer to close
+    local windows = vim.tbl_filter(function(win)
+        return api.nvim_win_get_buf(win) == bufnr
+    end, api.nvim_list_wins())
+
+    if #windows == 0 then return end
+
+    if force then
+        kill_command = kill_command .. "!"
+    end
+
+    -- Get list of active buffers
+    local buffers = vim.tbl_filter(function(buf)
+        return api.nvim_buf_is_valid(buf) and bo[buf].buflisted
+    end, api.nvim_list_bufs())
+
+    -- If there is only one buffer (which has to be the current one), vim will
+    -- create a new buffer on :bd.
+    -- For more than one buffer, pick the previous buffer (wrapping around if necessary)
+    if #buffers > 1 then
+        for i, v in ipairs(buffers) do
+            if v == bufnr then
+                local prev_buf_idx = i == 1 and (#buffers - 1) or (i - 1)
+                local prev_buffer = buffers[prev_buf_idx]
+                for _, win in ipairs(windows) do
+                    api.nvim_win_set_buf(win, prev_buffer)
+                end
+            end
+        end
+    else
+        vim.cmd('q!')
+    end
+
+    -- Check if buffer still exists, to ensure the target buffer wasn't killed
+    -- due to options like bufhidden=wipe.
+    if api.nvim_buf_is_valid(bufnr) and bo[bufnr].buflisted then
+        vim.cmd(string.format("%s %d", kill_command, bufnr))
+    end
 end
 
 function M.is_available(plugin)
@@ -147,6 +211,8 @@ local function has_capability(capability, filter)
 end
 
 -- NOTE: LSP Keymaps here
+-- TODO: Optimize these lookups with a fucking table jesus
+-- https://stackoverflow.com/a/37493047
 function M.lsp_on_attach(client, bufnr)
     vim.fn.system("echo fuck >/home/luca/test")
     local lsp_mappings = M.empty_map_table()
diff --git a/.config/nvim/todo b/.config/nvim/todo
index c096469e..c47aa3f8 100644
--- a/.config/nvim/todo
+++ b/.config/nvim/todo
@@ -1,4 +1,4 @@
 Continue checking for old keymaps
-Configure Todo Telescope integration
+Configure Todo Telescope integration etc.
 Figure out why the theme breaks when you install a plugin
 Indicate if various lsp toggles are active