feat(picker.git): allow passing extra args to other git pickers (#1205)

## Description

<!-- Describe the big picture of your changes to communicate to the
maintainers
  why we should accept this pull request. -->

This PR builds on
7122a03fdf
to provide a way to pass custom `args` to git command invocations.

An alternative (probably cleaner) way of doing this could be to add an
`args` field to `picker.sources.git`:

```yaml
      picker = {
        ---@class snacks.picker.previewers.Config
        previewers = {
          git = {
            args = git_opts(),
          },
        },
        ---@class snacks.picker.sources.Config
        sources = {
          git = {
            args = git_opts(),
          },
        },
```

## Related Issue(s)

<!--
  If this PR fixes any issues, please link to the issue here.
  - Fixes #<issue_number>
-->

Fixes #1184

## Screenshots

<!-- Add screenshots of the changes if applicable. -->

---------

Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
This commit is contained in:
Pedro Pombeiro 2025-02-18 21:07:50 +01:00 committed by GitHub
parent 7c382193ee
commit 4d46574b24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 25 deletions

View file

@ -207,6 +207,10 @@ M.files = {
supports_live = true,
}
---@class snacks.picker.git.Config: snacks.picker.Config
---@field args? string[] additional arguments to pass to `git ls-files`
---@type snacks.picker.git.Config
M.git_branches = {
finder = "git_branches",
format = "git_branch",
@ -220,6 +224,7 @@ M.git_branches = {
},
},
},
---@param picker snacks.Picker
on_show = function(picker)
for i, item in ipairs(picker:items()) do
if item.current then
@ -232,7 +237,7 @@ M.git_branches = {
}
-- Find git files
---@class snacks.picker.git.files.Config: snacks.picker.Config
---@class snacks.picker.git.files.Config: snacks.picker.git.Config
---@field untracked? boolean show untracked files
---@field submodules? boolean show submodule files
M.git_files = {
@ -244,8 +249,7 @@ M.git_files = {
}
-- Grep in git files
---@class snacks.picker.git.grep.Config: snacks.picker.Config
---@field args? string[] additional arguments to pass to `git grep`
---@class snacks.picker.git.grep.Config: snacks.picker.git.Config
---@field untracked? boolean search in untracked files
---@field submodules? boolean search in submodule files
---@field need_search? boolean require a search pattern
@ -261,7 +265,7 @@ M.git_grep = {
}
-- Git log
---@class snacks.picker.git.log.Config: snacks.picker.Config
---@class snacks.picker.git.log.Config: snacks.picker.git.Config
---@field follow? boolean track file history across renames
---@field current_file? boolean show current file log
---@field current_line? boolean show current line log
@ -302,7 +306,7 @@ M.git_stash = {
confirm = "git_stash_apply",
}
---@class snacks.picker.git.status.Config: snacks.picker.Config
---@class snacks.picker.git.status.Config: snacks.picker.git.Config
---@field ignored? boolean show ignored files
M.git_status = {
finder = "git_status",
@ -317,6 +321,7 @@ M.git_status = {
},
}
---@type snacks.picker.git.Config
M.git_diff = {
finder = "git_diff",
format = "file",

View file

@ -4,10 +4,20 @@ 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[]
for i = 1, select("#", ...) do
local arg = select(i, ...)
vim.list_extend(ret, type(arg) == "table" and arg or { arg })
end
return ret
end
---@param opts snacks.picker.git.files.Config
---@type snacks.picker.finder
function M.files(opts, ctx)
local args = { "-c", "core.quotepath=false", "ls-files", "--exclude-standard", "--cached" }
local args = git_args(opts.args, "ls-files", "--exclude-standard", "--cached")
if opts.untracked then
table.insert(args, "--others")
elseif opts.submodules then
@ -38,9 +48,7 @@ function M.grep(opts, ctx)
if opts.need_search ~= false and ctx.filter.search == "" then
return function() end
end
local args = { "-c", "core.quotepath=false" }
vim.list_extend(args, opts.args or {})
vim.list_extend(args, { "grep", "--line-number", "--column", "--no-color", "-I" })
local args = git_args(opts.args, "grep", "--line-number", "--column", "--no-color", "-I")
if opts.untracked then
table.insert(args, "--untracked")
elseif opts.submodules then
@ -80,7 +88,8 @@ end
---@param opts snacks.picker.git.log.Config
---@type snacks.picker.finder
function M.log(opts, ctx)
local args = {
local args = git_args(
opts.args,
"log",
"--pretty=format:%h %s (%ch)",
"--abbrev-commit",
@ -88,8 +97,8 @@ function M.log(opts, ctx)
"--date=short",
"--color=never",
"--no-show-signature",
"--no-patch",
}
"--no-patch"
)
local file ---@type string?
if opts.current_line then
@ -161,13 +170,7 @@ end
---@param opts snacks.picker.git.status.Config
---@type snacks.picker.finder
function M.status(opts, ctx)
local args = {
"--no-pager",
"status",
"-uall",
"--porcelain=v1",
"-z",
}
local args = git_args(opts.args, "--no-pager", "status", "-uall", "--porcelain=v1", "-z")
if opts.ignored then
table.insert(args, "--ignored=matching")
end
@ -201,10 +204,10 @@ function M.status(opts, ctx)
}, ctx)
end
---@param opts snacks.picker.Config
---@param opts snacks.picker.git.Config
---@type snacks.picker.finder
function M.diff(opts, ctx)
local args = { "--no-pager", "diff", "--no-color", "--no-ext-diff" }
local args = git_args(opts.args, "--no-pager", "diff", "--no-color", "--no-ext-diff")
local file, line ---@type string?, number?
local header, hunk = {}, {} ---@type string[], string[]
local header_len = 4
@ -253,10 +256,10 @@ function M.diff(opts, ctx)
end
end
---@param opts snacks.picker.Config
---@param opts snacks.picker.git.Config
---@type snacks.picker.finder
function M.branches(opts, ctx)
local args = { "--no-pager", "branch", "--no-color", "-vvl" }
local args = git_args(opts.args, "--no-pager", "branch", "--no-color", "-vvl")
local cwd = vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
cwd = Snacks.git.get_root(cwd)
@ -297,10 +300,10 @@ function M.branches(opts, ctx)
}, ctx)
end
---@param opts snacks.picker.Config
---@param opts snacks.picker.git.Config
---@type snacks.picker.finder
function M.stash(opts, ctx)
local args = { "--no-pager", "stash", "list" }
local args = git_args(opts.args, "--no-pager", "stash", "list")
local cwd = vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
cwd = Snacks.git.get_root(cwd)