refactor(git): scratch buffers wipe by default, consolidate factories in util

This commit is contained in:
2026-04-29 10:39:48 +02:00
parent 0766c7f11e
commit 18b198f293
6 changed files with 48 additions and 54 deletions
-1
View File
@@ -33,7 +33,6 @@ function M.commit(opts)
proxy_buf = buf proxy_buf = buf
proxy_win = win proxy_win = win
vim.bo[buf].buftype = "acwrite" vim.bo[buf].buftype = "acwrite"
vim.bo[buf].bufhidden = "wipe"
vim.bo[buf].modifiable = true vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.bo[buf].modified = false vim.bo[buf].modified = false
-29
View File
@@ -3,35 +3,6 @@ local util = require("git.util")
local M = {} local M = {}
---@class ow.Git.EmptyBufOpts
---@field name string?
---@field bufhidden ("hide"|"wipe")? defaults to "wipe"
---Build a read-only scratch buffer, optionally naming it. When `opts.name`
---is set and a loaded buffer with that name already exists, returns it
---instead of creating a duplicate.
---@param opts ow.Git.EmptyBufOpts?
---@return integer
function M.empty_buf(opts)
opts = opts or {}
if opts.name then
local existing = vim.fn.bufnr(opts.name)
if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then
return existing
end
end
local buf = vim.api.nvim_create_buf(false, true)
vim.bo[buf].buftype = "nofile"
vim.bo[buf].bufhidden = opts.bufhidden or "wipe"
vim.bo[buf].swapfile = false
vim.bo[buf].modifiable = false
vim.bo[buf].modified = false
if opts.name then
pcall(vim.api.nvim_buf_set_name, buf, opts.name)
end
return buf
end
---Name a buffer and re-run filetype detection from the (re-)set name. ---Name a buffer and re-run filetype detection from the (re-)set name.
---Wrapped in `pcall` because a buffer with that name may already exist ---Wrapped in `pcall` because a buffer with that name may already exist
---(E95). ---(E95).
+3 -1
View File
@@ -41,7 +41,9 @@ function M.show(opts)
return return
end end
local buf = util.new_scratch() -- `hide` keeps the log around when the user navigates into a commit
-- via `<CR>` (which replaces the current buffer); `<C-^>` jumps back.
local buf = util.new_scratch({ bufhidden = "hide" })
vim.b[buf].git_worktree = worktree vim.b[buf].git_worktree = worktree
vim.bo[buf].modifiable = true vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(buf, 0, -1, false, util.split_lines(stdout)) vim.api.nvim_buf_set_lines(buf, 0, -1, false, util.split_lines(stdout))
+2 -9
View File
@@ -229,10 +229,7 @@ end
local function blob_buf(worktree, blob, path, ref) local function blob_buf(worktree, blob, path, ref)
local revspec = ref .. ":" .. path local revspec = ref .. ":" .. path
if is_zero(blob) then if is_zero(blob) then
return diff.empty_buf({ return util.empty_buf({ name = util.uri(revspec) })
name = util.uri(revspec),
bufhidden = "hide",
})
end end
return M.buf_for(worktree, revspec) return M.buf_for(worktree, revspec)
end end
@@ -269,10 +266,7 @@ end
---@field split (false|"above"|"below"|"left"|"right")? forwarded to `util.new_scratch`. Default opens a new horizontal split. ---@field split (false|"above"|"below"|"left"|"right")? forwarded to `util.new_scratch`. Default opens a new horizontal split.
---Place a `git://<revspec>` URI buffer in a window per `opts.split`. ---Place a `git://<revspec>` URI buffer in a window per `opts.split`.
---`bufadd` dedups against existing buffers, so re-opening the same URI ---`bufadd` dedups against existing buffers; `bufload` no-ops if loaded.
---reuses the buffer (and `bufload` no-ops). `read_uri` defaults to
---`bufhidden=wipe` (right for diff sides), but navigation buffers
---should persist across window closes, so override to `hide`.
---@param worktree string ---@param worktree string
---@param uri string ---@param uri string
---@param sha string written to `b:git_ref` so `<CR>` navigation in the buffer can resolve relative paths ---@param sha string written to `b:git_ref` so `<CR>` navigation in the buffer can resolve relative paths
@@ -283,7 +277,6 @@ local function open_uri(worktree, uri, sha, opts, default_ft)
vim.b[buf].git_worktree = worktree vim.b[buf].git_worktree = worktree
vim.b[buf].git_ref = sha vim.b[buf].git_ref = sha
vim.fn.bufload(buf) vim.fn.bufload(buf)
vim.bo[buf].bufhidden = "hide"
if default_ft and vim.bo[buf].filetype == "" then if default_ft and vim.bo[buf].filetype == "" then
vim.bo[buf].filetype = default_ft vim.bo[buf].filetype = default_ft
end end
+2 -2
View File
@@ -495,7 +495,7 @@ end
---@return ow.Git.DiffSide ---@return ow.Git.DiffSide
local function absent_pane(worktree, path, kind) local function absent_pane(worktree, path, kind)
return { return {
buf = diff.empty_buf(), buf = util.empty_buf(),
name = string.format( name = string.format(
"[absent %s] %s", "[absent %s] %s",
kind, kind,
@@ -865,7 +865,7 @@ local function open(worktree)
end end
local previous_win = vim.api.nvim_get_current_win() local previous_win = vim.api.nvim_get_current_win()
local bufnr, win = util.new_scratch({ split = "left", bufhidden = "wipe" }) local bufnr, win = util.new_scratch({ split = "left" })
vim.bo[bufnr].filetype = "gitsidebar" vim.bo[bufnr].filetype = "gitsidebar"
vim.wo[win].number = false vim.wo[win].number = false
+41 -12
View File
@@ -44,6 +44,44 @@ function M.parse_revspec(revspec)
return { stage = nil, path = path } return { stage = nil, path = path }
end end
---@class ow.Git.ScratchOpts
---@field name string?
---@field bufhidden ("hide"|"wipe")? defaults to "wipe"
---Configure a fresh buffer as a read-only scratch and optionally name
---it. Shared by `empty_buf` and `new_scratch`; the public functions
---differ in whether they dedup-by-name or place the buffer in a window.
---@param buf integer
---@param opts ow.Git.ScratchOpts
local function setup_scratch(buf, opts)
vim.bo[buf].buftype = "nofile"
vim.bo[buf].bufhidden = opts.bufhidden or "wipe"
vim.bo[buf].swapfile = false
vim.bo[buf].modifiable = false
vim.bo[buf].modified = false
if opts.name then
pcall(vim.api.nvim_buf_set_name, buf, opts.name)
end
end
---Build a read-only scratch buffer, optionally naming it. When `opts.name`
---is set and a loaded buffer with that name already exists, returns it
---instead of creating a duplicate.
---@param opts ow.Git.ScratchOpts?
---@return integer
function M.empty_buf(opts)
opts = opts or {}
if opts.name then
local existing = vim.fn.bufnr(opts.name)
if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then
return existing
end
end
local buf = vim.api.nvim_create_buf(false, true)
setup_scratch(buf, opts)
return buf
end
---Place a buffer in the current window or a new split per `split`. ---Place a buffer in the current window or a new split per `split`.
---`false` replaces the current buffer (drops a `'` mark first so `''` ---`false` replaces the current buffer (drops a `'` mark first so `''`
---jumps back); a direction string opens a leftabove split; nil falls ---jumps back); a direction string opens a leftabove split; nil falls
@@ -62,12 +100,10 @@ function M.place_buf(buf, split)
}) })
end end
---@class ow.Git.NewScratchOpts ---@class ow.Git.NewScratchOpts : ow.Git.ScratchOpts
---@field name string?
---@field bufhidden ("hide"|"wipe")? defaults to "hide"
---@field split (false|"above"|"below"|"left"|"right")? defaults to splitbelow-aware horizontal. `false` places the buffer in the current window (drops a `'` mark first so the user can jump back). ---@field split (false|"above"|"below"|"left"|"right")? defaults to splitbelow-aware horizontal. `false` places the buffer in the current window (drops a `'` mark first so the user can jump back).
---Create a fresh non-modifiable scratch buffer and place it. Default split ---Create a fresh read-only scratch buffer and place it. Default split
---direction is horizontal, honouring `splitbelow`. Caller flips ---direction is horizontal, honouring `splitbelow`. Caller flips
---`modifiable`, fills the buffer, and sets `filetype` once content lands. ---`modifiable`, fills the buffer, and sets `filetype` once content lands.
---@param opts ow.Git.NewScratchOpts? ---@param opts ow.Git.NewScratchOpts?
@@ -76,14 +112,7 @@ end
function M.new_scratch(opts) function M.new_scratch(opts)
opts = opts or {} opts = opts or {}
local buf = vim.api.nvim_create_buf(false, true) local buf = vim.api.nvim_create_buf(false, true)
vim.bo[buf].buftype = "nofile" setup_scratch(buf, opts)
vim.bo[buf].bufhidden = opts.bufhidden or "hide"
vim.bo[buf].swapfile = false
vim.bo[buf].modifiable = false
vim.bo[buf].modified = false
if opts.name then
pcall(vim.api.nvim_buf_set_name, buf, opts.name)
end
return buf, M.place_buf(buf, opts.split) return buf, M.place_buf(buf, opts.split)
end end