feat(bufdelete): added wipe option. Closes #38

This commit is contained in:
Folke Lemaitre 2024-11-09 15:01:10 +01:00
parent 9b9777ec3b
commit 5914cb1010
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
3 changed files with 96 additions and 69 deletions

View file

@ -3,7 +3,7 @@
============================================================================== ==============================================================================
Table of Contents *snacks-bufdelete-table-of-contents* Table of Contents *snacks-bufdelete-table-of-contents*
1. Config |snacks-bufdelete-config| 1. Types |snacks-bufdelete-types|
2. Module |snacks-bufdelete-module| 2. Module |snacks-bufdelete-module|
- Snacks.bufdelete() |snacks-bufdelete-module-snacks.bufdelete()| - Snacks.bufdelete() |snacks-bufdelete-module-snacks.bufdelete()|
- Snacks.bufdelete.all() |snacks-bufdelete-module-snacks.bufdelete.all()| - Snacks.bufdelete.all() |snacks-bufdelete-module-snacks.bufdelete.all()|
@ -16,15 +16,14 @@ discard.
============================================================================== ==============================================================================
1. Config *snacks-bufdelete-config* 1. Types *snacks-bufdelete-types*
>lua >lua
---@class snacks.bufdelete.Opts ---@class snacks.bufdelete.Opts
---@field buf? number Buffer to delete. If not provided, the current buffer is deleted ---@field buf? number Buffer to delete. Defaults to the current buffer
---@field force? boolean Delete the buffer even if it is modified ---@field force? boolean Delete the buffer even if it is modified
---@field filter? fun(buf: number): boolean Filter buffers to delete ---@field filter? fun(buf: number): boolean Filter buffers to delete
---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`) ---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`)
{}
< <
@ -35,7 +34,7 @@ discard.
SNACKS.BUFDELETE() *snacks-bufdelete-module-snacks.bufdelete()* SNACKS.BUFDELETE() *snacks-bufdelete-module-snacks.bufdelete()*
>lua >lua
---@type fun(buf?: number) ---@type fun(buf?: number|snacks.bufdelete.Opts)
Snacks.bufdelete() Snacks.bufdelete()
< <
@ -45,7 +44,8 @@ SNACKS.BUFDELETE.ALL() *snacks-bufdelete-module-snacks.bufdelete.all()*
Delete all buffers Delete all buffers
>lua >lua
Snacks.bufdelete.all() ---@param opts? snacks.bufdelete.Opts
Snacks.bufdelete.all(opts)
< <
@ -56,8 +56,8 @@ buffer `buf` if it is a number - or every buffer for which `buf` returns true
if it is a function if it is a function
>lua >lua
---@param buf? number | fun(buf: number): boolean ---@param opts? number|snacks.bufdelete.Opts
Snacks.bufdelete.delete(buf) Snacks.bufdelete.delete(opts)
< <
@ -66,7 +66,8 @@ SNACKS.BUFDELETE.OTHER() *snacks-bufdelete-module-snacks.bufdelete.other()*
Delete all buffers except the current one Delete all buffers except the current one
>lua >lua
Snacks.bufdelete.other() ---@param opts? snacks.bufdelete.Opts
Snacks.bufdelete.other(opts)
< <
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc> Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>

View file

@ -7,12 +7,22 @@ a prompt will be shown to save or discard.
<!-- docgen --> <!-- docgen -->
## 📚 Types
```lua
---@class snacks.bufdelete.Opts
---@field buf? number Buffer to delete. Defaults to the current buffer
---@field force? boolean Delete the buffer even if it is modified
---@field filter? fun(buf: number): boolean Filter buffers to delete
---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`)
```
## 📦 Module ## 📦 Module
### `Snacks.bufdelete()` ### `Snacks.bufdelete()`
```lua ```lua
---@type fun(buf?: number) ---@type fun(buf?: number|snacks.bufdelete.Opts)
Snacks.bufdelete() Snacks.bufdelete()
``` ```
@ -21,7 +31,8 @@ Snacks.bufdelete()
Delete all buffers Delete all buffers
```lua ```lua
Snacks.bufdelete.all() ---@param opts? snacks.bufdelete.Opts
Snacks.bufdelete.all(opts)
``` ```
### `Snacks.bufdelete.delete()` ### `Snacks.bufdelete.delete()`
@ -32,8 +43,8 @@ Delete a buffer:
- or every buffer for which `buf` returns true if it is a function - or every buffer for which `buf` returns true if it is a function
```lua ```lua
---@param buf? number | fun(buf: number): boolean ---@param opts? number|snacks.bufdelete.Opts
Snacks.bufdelete.delete(buf) Snacks.bufdelete.delete(opts)
``` ```
### `Snacks.bufdelete.other()` ### `Snacks.bufdelete.other()`
@ -41,5 +52,6 @@ Snacks.bufdelete.delete(buf)
Delete all buffers except the current one Delete all buffers except the current one
```lua ```lua
Snacks.bufdelete.other() ---@param opts? snacks.bufdelete.Opts
Snacks.bufdelete.other(opts)
``` ```

View file

@ -1,84 +1,98 @@
---@class snacks.bufdelete ---@class snacks.bufdelete
---@overload fun(buf?: number) ---@overload fun(buf?: number|snacks.bufdelete.Opts)
local M = setmetatable({}, { local M = setmetatable({}, {
__call = function(t, ...) __call = function(t, ...)
return t.delete(...) return t.delete(...)
end, end,
}) })
---@class snacks.bufdelete.Opts
---@field buf? number Buffer to delete. Defaults to the current buffer
---@field force? boolean Delete the buffer even if it is modified
---@field filter? fun(buf: number): boolean Filter buffers to delete
---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`)
--- Delete a buffer: --- Delete a buffer:
--- - either the current buffer if `buf` is not provided --- - either the current buffer if `buf` is not provided
--- - or the buffer `buf` if it is a number --- - or the buffer `buf` if it is a number
--- - or every buffer for which `buf` returns true if it is a function --- - or every buffer for which `buf` returns true if it is a function
---@param buf? number | fun(buf: number): boolean ---@param opts? number|snacks.bufdelete.Opts
function M.delete(buf) function M.delete(opts)
if type(buf) == "function" then opts = opts or {}
for _, b in ipairs(vim.api.nvim_list_bufs()) do opts = type(opts) == "number" and { buf = opts } or opts
if vim.bo[b].buflisted and buf(b) then opts = type(opts) == "function" and { filter = opts } or opts
M.delete(b) ---@cast opts snacks.bufdelete.Opts
if type(opts.filter) == "function" then
for _, b in ipairs(vim.tbl_filter(opts.filter, vim.api.nvim_list_bufs())) do
if vim.bo[b].buflisted then
M.delete(vim.tbl_extend("force", {}, opts, { buf = b, filter = false }))
end end
end end
return return
end end
buf = buf or 0 local buf = opts.buf or 0
buf = buf == 0 and vim.api.nvim_get_current_buf() or buf buf = buf == 0 and vim.api.nvim_get_current_buf() or buf
-- Ensure we always run in the target buffer vim.api.nvim_buf_call(buf, function()
if buf ~= vim.api.nvim_get_current_buf() then if vim.bo.modified and not opts.force then
return vim.api.nvim_buf_call(buf, M.delete) local choice = vim.fn.confirm(("Save changes to %q?"):format(vim.fn.bufname()), "&Yes\n&No\n&Cancel")
end if choice == 0 or choice == 3 then -- 0 for <Esc>/<C-c> and 3 for Cancel
return
if vim.bo.modified then end
local choice = vim.fn.confirm(("Save changes to %q?"):format(vim.fn.bufname()), "&Yes\n&No\n&Cancel") if choice == 1 then -- Yes
if choice == 0 or choice == 3 then -- 0 for <Esc>/<C-c> and 3 for Cancel vim.cmd.write()
return end
end end
if choice == 1 then -- Yes
vim.cmd.write() for _, win in ipairs(vim.fn.win_findbuf(buf)) do
vim.api.nvim_win_call(win, function()
if not vim.api.nvim_win_is_valid(win) or vim.api.nvim_win_get_buf(win) ~= buf then
return
end
-- Try using alternate buffer
local alt = vim.fn.bufnr("#")
if alt ~= buf and vim.fn.buflisted(alt) == 1 then
vim.api.nvim_win_set_buf(win, alt)
return
end
-- Try using previous buffer
local has_previous = pcall(vim.cmd, "bprevious")
if has_previous and buf ~= vim.api.nvim_win_get_buf(win) then
return
end
-- Create new listed buffer
local new_buf = vim.api.nvim_create_buf(true, false)
vim.api.nvim_win_set_buf(win, new_buf)
end)
end end
end if vim.api.nvim_buf_is_valid(buf) then
pcall(vim.cmd, opts.wipe and "bwipeout! " or "bdelete! " .. buf)
for _, win in ipairs(vim.fn.win_findbuf(buf)) do end
vim.api.nvim_win_call(win, function() end)
if not vim.api.nvim_win_is_valid(win) or vim.api.nvim_win_get_buf(win) ~= buf then
return
end
-- Try using alternate buffer
local alt = vim.fn.bufnr("#")
if alt ~= buf and vim.fn.buflisted(alt) == 1 then
vim.api.nvim_win_set_buf(win, alt)
return
end
-- Try using previous buffer
local has_previous = pcall(vim.cmd, "bprevious")
if has_previous and buf ~= vim.api.nvim_win_get_buf(win) then
return
end
-- Create new listed buffer
local new_buf = vim.api.nvim_create_buf(true, false)
vim.api.nvim_win_set_buf(win, new_buf)
end)
end
if vim.api.nvim_buf_is_valid(buf) then
pcall(vim.cmd, "bdelete! " .. buf)
end
end end
--- Delete all buffers --- Delete all buffers
function M.all() ---@param opts? snacks.bufdelete.Opts
return M.delete(function() function M.all(opts)
return true return M.delete(vim.tbl_extend("force", {}, opts or {}, {
end) filter = function()
return true
end,
}))
end end
--- Delete all buffers except the current one --- Delete all buffers except the current one
function M.other() ---@param opts? snacks.bufdelete.Opts
return M.delete(function(b) function M.other(opts)
return b ~= vim.api.nvim_get_current_buf() return M.delete(vim.tbl_extend("force", {}, opts or {}, {
end) filter = function(b)
return b ~= vim.api.nvim_get_current_buf()
end,
}))
end end
return M return M