diff --git a/lua/snacks/picker/config/sources.lua b/lua/snacks/picker/config/sources.lua index bafd1886..29deef16 100644 --- a/lua/snacks/picker/config/sources.lua +++ b/lua/snacks/picker/config/sources.lua @@ -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 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 `` ---@class snacks.picker.git.branches.Config: snacks.picker.git.Config ---@field all? boolean show all branches, including remote diff --git a/lua/snacks/picker/source/git.lua b/lua/snacks/picker/source/git.lua index bdc062a9..a4a9e4ae 100644 --- a/lua/snacks/picker/source/git.lua +++ b/lua/snacks/picker/source/git.lua @@ -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 `` + +---@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)