feat(git): allow configuring extra git args and git cmd args for all git sources. See #2178

This commit is contained in:
Folke Lemaitre 2025-10-21 17:17:14 +02:00
parent f324f96bea
commit 5782b5cda0
No known key found for this signature in database
GPG key ID: 9B52594D560070AB
2 changed files with 39 additions and 18 deletions

View file

@ -208,8 +208,12 @@ M.files = {
supports_live = true,
}
---@class snacks.picker.git.Config: snacks.picker.Config
---@field args? string[] additional arguments to pass to `git ls-files`
--- Git arguments are use like this:
--- * git [<cmd_args>] <cmd> [<args>]
--- * cmd may be `status`, `log`, `diff`, etc.
---@class snacks.picker.git.Config: snacks.picker.Config,snacks.picker.git.Args
---@field args? string[] additional arguments to pass to `git`
---@field cmd_args? string[] additional arguments to pass to the `git <cmd>``
---@class snacks.picker.git.branches.Config: snacks.picker.git.Config
---@field all? boolean show all branches, including remote

View file

@ -4,20 +4,36 @@ local uv = vim.uv or vim.loop
local commit_pat = ("[a-z0-9]"):rep(7)
---@param ... (string|string[]|nil)
local function git_args(...)
local ret = { "-c", "core.quotepath=false" } ---@type string[]
---@class snacks.picker.git.Args
---@field args? string[] additional arguments to pass to `git`
---@field cmd_args? string[] additional arguments to pass to the `git <cmd>``
---@param cmd string
---@param ... string|snacks.picker.git.Args
function M.git(cmd, ...)
local args, cmd_args = {}, {} ---@type string[], string[]
for i = 1, select("#", ...) do
local arg = select(i, ...)
vim.list_extend(ret, type(arg) == "table" and arg or { arg })
if type(arg) == "string" then
cmd_args[#cmd_args + 1] = arg
else
vim.list_extend(args, arg.args or {})
vim.list_extend(cmd_args, arg.cmd_args or {})
end
end
local ret = { "-c", "core.quotepath=false" } ---@type string[]
vim.list_extend(ret, args)
ret[#ret + 1] = cmd
vim.list_extend(ret, cmd_args)
return ret
end
---@param opts snacks.picker.git.files.Config
---@type snacks.picker.finder
function M.files(opts, ctx)
local args = git_args(opts.args, "ls-files", "--exclude-standard", "--cached")
local args = M.git("ls-files", "--exclude-standard", "--cached", opts)
if opts.untracked then
table.insert(args, "--others")
elseif opts.submodules then
@ -48,7 +64,7 @@ function M.grep(opts, ctx)
if opts.need_search ~= false and ctx.filter.search == "" then
return function() end
end
local args = git_args(opts.args, "grep", "--line-number", "--column", "--no-color", "-I")
local args = M.git("grep", "--line-number", "--column", "--no-color", "-I", opts)
if opts.untracked then
table.insert(args, "--untracked")
elseif opts.submodules then
@ -91,8 +107,7 @@ end
---@param opts snacks.picker.git.log.Config
---@type snacks.picker.finder
function M.log(opts, ctx)
local args = git_args(
opts.args,
local args = M.git(
"log",
"--pretty=format:%h %s (%ch) <%an>",
"--abbrev-commit",
@ -100,7 +115,8 @@ function M.log(opts, ctx)
"--date=short",
"--color=never",
"--no-show-signature",
"--no-patch"
"--no-patch",
opts
)
if opts.author then
@ -137,8 +153,7 @@ function M.log(opts, ctx)
Proc.proc({
cmd = "git",
cwd = cwd,
args = git_args(
opts.args,
args = M.git(
"log",
"-z",
"--follow",
@ -146,7 +161,8 @@ function M.log(opts, ctx)
"--pretty=format:''",
"--diff-filter=R",
"--",
file
file,
opts
),
}, ctx)(function(item)
for _, text in ipairs(vim.split(item.text, "\0")) do
@ -189,7 +205,7 @@ end
---@param opts snacks.picker.git.status.Config
---@type snacks.picker.finder
function M.status(opts, ctx)
local args = git_args(opts.args, "--no-pager", "status", "-uall", "--porcelain=v1", "-z")
local args = M.git("status", "-uall", "--porcelain=v1", "-z", { args = { "--no-pager" } }, opts)
if opts.ignored then
table.insert(args, "--ignored=matching")
end
@ -226,7 +242,8 @@ end
---@param opts snacks.picker.git.Config
---@type snacks.picker.finder
function M.diff(opts, ctx)
local args = git_args(opts.args, "-c", "diff.noprefix=false", "--no-pager", "diff", "--no-color", "--no-ext-diff")
local args =
M.git("diff", "--no-color", "--no-ext-diff", { args = { "-c", "diff.noprefix=false", "--no-pager" } }, opts)
local file, line ---@type string?, number?
local header, hunk = {}, {} ---@type string[], string[]
local header_len = 4
@ -284,7 +301,7 @@ end
---@param opts snacks.picker.git.branches.Config
---@type snacks.picker.finder
function M.branches(opts, ctx)
local args = git_args(opts.args, "--no-pager", "branch", "--no-color", "-vvl")
local args = M.git("branch", "--no-color", "-vvl", { args = { "--no-pager" } }, opts)
if opts.all then
table.insert(args, "--all")
end
@ -334,7 +351,7 @@ end
---@param opts snacks.picker.git.Config
---@type snacks.picker.finder
function M.stash(opts, ctx)
local args = git_args(opts.args, "--no-pager", "stash", "list")
local args = M.git("stash", "list", { args = { "--no-pager" } }, opts)
local cwd = svim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
cwd = Snacks.git.get_root(cwd)