## Description
This is in place of the rejected PR #2178. Please consider the following
reasons for merging.
This PR adds the possibility to specify pathspec patterns to the `git
grep .... -- <patchspec>` command. This is necessary for ignoring large
git-tracked files (that cannot be added to `.gitignore`) from the git
grep search. git-grepping in some large files with very long lines can
freeze Neovim and make `Snacks.picker.git_grep` completely unusable.
Without this change the picker cannot be configured to use some
pathspecs by default. They can be added dynamically in live mode but
re-typing the same pathspecs every time one needs to use
`Snacks.picker.git_grep` would be silly.
In reply to the [question if cmd_args can be used for
this](https://github.com/folke/snacks.nvim/pull/2178#discussion_r2448762906):
No. The "pathspecs" need to be specified *last* (optionally after `--`).
When configuring Snacks.picker like this:
```lua
sources = {
git_grep = {
cmd_args = { ':!*.min.js', ':!*.min.css', ':!uv.lock' },
},
}
```
then the `cmd_args` are inserted in front of the search pattern and `git
grep` doesn't find anything. The following config can't be used either
because that will cause the [search
pattern](c9fa6f7b07/lua/snacks/picker/source/git.lua (L76))
to be treated as one of the pathspecs.
```lua
git_grep = {
cmd_args = { '--', ':!*.min.js', ':!*.min.css', ':!uv.lock' },
},
```
## Description
<!-- Describe the big picture of your changes to communicate to the
maintainers
why we should accept this pull request. -->
Currently, I'm able to perform a search on a YADM repo by passing the
args `{ "--git-dir", "/Users/pedro/.local/share/yadm/repo.git",
"--work-tree", "/Users/pedro" }` to `picker.previewers.git.args`.
Unfortunately, the `git_show` previewer is currently not using this
configuration, so constantly fails to show the preview with an error
message. This MR fixes the problem by leveraging the existing `git`
local function.
## Related Issue(s)
<!--
If this PR fixes any issues, please link to the issue here.
- Fixes #<issue_number>
-->
## Screenshots
<!-- Add screenshots of the changes if applicable. -->
<img width="1582" alt="image"
src="https://github.com/user-attachments/assets/6f7c3960-cfc0-4c0c-a264-105a721cd9a8"
/>
Previewer working inside a YADM repo.
## Description
Currently in the picker you cant filter git log pickers by author, the
only option to do that right now is to pass it into the opts when you
call it like lua Snacks.picker.git_log({ author="test" }) but most of
the time I would like to filter interactively and also use the field
filtering offered by snacks like file:lua$ and with this new change,
author:test.
## Related Issue(s)
<!--
If this PR fixes any issues, please link to the issue here.
- Fixes #<issue_number>
-->
## Screenshots
<img width="760" height="842" alt="Screenshot 2025-10-13 at 11 03 28 PM"
src="https://github.com/user-attachments/assets/e57278aa-0fcd-4513-981d-fe8cfe078c64"
/>
<!-- Add screenshots of the changes if applicable. -->
---------
Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
After cb6bf052, occationally I get this error when attach snacks.image
in fzf-lua previewer
vim.schedule callback: runtime/lua/vim/fs.lua:737:
ENOENT: no such file or directory:
/home/phan/.cache/nvim/snacks/image/56bd7d4f-img.shields.io-badge-Made-with-Lua-blueviolet.svg.data
stack traceback:
[C]: in function 'error'
runtime/lua/vim/fs.lua:737: in function 'rm'
snacks.nvim/lua/snacks/image/convert.lua:66: in function 'on_error'
snacks.nvim/lua/snacks/image/convert.lua:340: in function 'on_step'
snacks.nvim/lua/snacks/image/convert.lua:434: in function
<snacks.nvim/lua/snacks/image/convert.lua:433>
When opening Neovim with a directory argument (e.g., `nvim .`), the
explorer's preview window was not being shown automatically. This was
because the WinEnter autocmd in the picker was triggering during the
startup sequence before VimEnter, interfering with the initialization.
The fix adds a check for `vim.v.vim_did_enter == 0` to skip the window
management logic during startup, allowing the explorer to properly
initialize with its preview window enabled.
Fixes#2257 (second issue)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When using `preview="main"`, the preview window floats over the main
editor window. Set its z-index to 40 (lower than the default 50) to
ensure input and help windows remain on top and visible.
Fixes#2257 (first issue)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds a git_restore action that discards changes to files in the
git_status picker. Includes confirmation prompt before discarding
changes to prevent accidental data loss.
Usage:
- `<C-r>` in git_status picker to restore selected file(s)
- Works with multi-select (select multiple files and restore all)
- Shows different confirmation messages for single vs multiple files
Implementation:
- Added git_restore() action in actions.lua
- Bound to <C-r> in git_status picker
- Supports both single and multi-select
- Uses Snacks.picker.select for confirmation
- Refreshes picker and returns to insert mode after restore
Closes#2298🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Uses ripgrep's --replace feature to mark exact match positions with
separators (__snacks__${0}__snacks__), then parses these positions
for precise highlighting.
Benefits:
- Exact match highlighting in list, preview, and file formatter
- Works with any grep pattern (regex, fixed-string, case-insensitive)
- No need for pattern parsing or vim.regex workarounds
- Positions are provided directly by ripgrep, guaranteed accurate
Implementation:
- Added item.positions field to track match character indices
- New highlight.matches() helper for creating match extmarks
- Modified grep source to parse and extract positions from rg output
- Updated list, preview, and format to use positions when available
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Description
Allows passing extra Git arguments (like `--git-dir` or `--work-tree`)
to the rename detection logic inside `M.log` in `picker/source/git.lua`.
Previously, these extra arguments from `opts.args` were applied to the
main `git log` command but ignored during rename detection. This caused
errors or incorrect results when working in non-standard repo setups.
This change uses `git_args(...)` to build the rename detection command,
ensuring consistent argument handling throughout `M.log`.
## Description
This uses `vim.treesitter.foldexpr` to get the start of a foldlevel,
because `vim.fn.foldlevel()` will return the same number in adjacent
foldlevels, thus making the open fold markers inconsistent.
This will however introduce a dependency on `vim.treesitter.foldexpr`
and I haven't seen any other computations based on `vim.treesitter`, so
maybe this is not desirable?
Unfortunately, I wasn't able to come up with a better solution, so feel
free to disregard.
PS: I came across #1445 and this PR reverts those changes I realize. But
I fail to find a good way for both to co-exist. I tried checking the
value with `vim.api.nvim_get_option_value("foldexpr", {})`, but this
will only work if `vim.opt.foldexpr` will be set directly into one of
the 2. If it's set to another function that is required like in LazyVim,
I'm not able to distinguish what value `foldexpr` is actually set to.
PS2: I'm guessing the same thing happens when `foldexpr` is set to
`vim.lsp.foldexpr` and the ideal would be some way to distinguish which
one is currently active and then use either
`vim.treesitter.foldexpr(lnum):sub(1, 1) == ">"` or
`vim.lsp.foldexpr(lnum):sub(1, 1) == ">"` respectively.
<!-- Describe the big picture of your changes to communicate to the
maintainers
why we should accept this pull request. -->
## Related Issue(s)
Fixes#1533
<!--
If this PR fixes any issues, please link to the issue here.
- Fixes #<issue_number>
-->
## Screenshots
Before

After

<!-- Add screenshots of the changes if applicable. -->
---------
Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
## Description
Add option for `ignorecase` for `git_grep`
<!-- Describe the big picture of your changes to communicate to the
maintainers
why we should accept this pull request. -->
## Related Issue(s)
Fixes#1627
<!--
If this PR fixes any issues, please link to the issue here.
- Fixes #<issue_number>
-->
## Screenshots
<!-- Add screenshots of the changes if applicable. -->
PR #2296 had the conditionals in the wrong order and with an "or"
instead of an "and". This should finally fix the issue and pass
stylelua.
## Description
The correct condition for correcting the off-by-one is:
```
if
(Snacks.config.styles.snacks_image.relative ~= "editor")
and ((vim.o.showtabline == 2) or (vim.o.showtabline == 1 and vim.fn.tabpagenr("$") > 1))
then
```
This patch gets the conditional in the right order
In PR 1560, @phanen reported an additional case that was not handled by
that fix when the style is set to `relative = "editor"`. This new patch
adds a check to handle that case.
## Description ##
This patch adds a check for `Snacks.config.styles.snacks_image.relative
~= "editor"` to the conditional in render_fallback that handles the
off-by-one error. The previous patch fixed the relative = "cursor" case,
but introduced a regression in the relative = "editor" case.
## Description
This PR builds on top of #743 to add flexible filename formatting in the
picker.
### Changes:
- **Flexible path truncation**: Added support for different truncation
strategies (`left`, `center`, `right`) instead of just a fixed number
- `left`: truncates the beginning of the path (e.g.,
`…/path/to/file.lua`)
- `center`: truncates the middle of the path (default behavior, e.g.,
`~/pro…/file.lua`)
- `right`: truncates the end of the path (e.g., `~/projects/long…`)
- **Dynamic width calculation**: The filename formatter now adapts to
available window width using a resolve function
- **Enhanced truncate utility**: Updated `M.truncate()` to support
left-side truncation
### Implementation:
The filename formatter now uses a `resolve` function that receives
context including the picker, item, current offset, and maximum
available width. This allows the formatter to make intelligent decisions
about how to display the path based on actual available space.
## Related Issue(s)
- Based on #743
- Addresses dynamic path formatting needs
## Technical Details
The implementation introduces:
1. `snacks.picker.format.ctx` - context passed to resolve functions
2. `snacks.picker.format.resolve` - callback type for dynamic formatting
3. `Snacks.picker.highlight.resolve()` - resolves flex text elements in
highlight arrays
---------
Co-authored-by: qw457812 <37494864+qw457812@users.noreply.github.com>