Add `Snacks.util.lsp.on()` to register handlers that fire when LSP clients
attach with specific capabilities. Supports filtering by:
- LSP method/capability
- Client name
- Buffer ID
- Any vim.lsp.get_clients() filter
Features:
- Handles both LspAttach and client/registerCapability events
- Ensures handlers only fire once per buffer
- Lazy-loaded via Snacks.util metatable
This provides a foundation for LSP-aware features like conditional keymaps.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Description
When a win is relative = "win" it should size itself relative to that
win's size. Currently this only happens correctly when the picker layout
is created. All subsequent updates, such as a toggle_preview action, can
potentially trigger calls to a function width/height opt with a
max_width and max_height smaller than was previously calculated. This
feeds into a recursive series of updates triggered by the WinResized
event triggering and updating with a yet smaller max_width or
max_height.
Additionally, because win.o.cols and win.o.lines is used,
relative/decimal dimensions would not calculate correctly in splits.
Screenshots are from a picker configured as
```
{
col = 1,
height = 0.9,
width = 0.9,
position = 'float',
relative = 'win',
}
```
**before**
<img width="1348" height="1358" alt="image"
src="https://github.com/user-attachments/assets/847b0565-afd0-4ca1-b44c-eb63e335afca"
/>
**after**
<img width="1354" height="1354" alt="image"
src="https://github.com/user-attachments/assets/064f25ae-ed17-42c8-8b34-f32652fab02d"
/>
- Add `trash` config option to use system trash when deleting files
- Implement trash support for Linux (gio, trash-cli, kioclient)
- Implement trash support for macOS (osascript/Finder)
- Implement trash support for Windows (PowerShell/RecycleBin)
- Add health check to verify trash command availability
- Gracefully fallback to permanent delete when trash unavailable
- Improve error messages with command details
Closes#982🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Converted scroll state management from procedural to OO approach:
- State is now a proper class with methods (get, stop, wo, valid, update, reset)
- Window options now managed per-state (_wo field) instead of global wo_backup table
- Centralized cleanup in State:stop() method
- Consolidated validation in State:valid() method
- Added is_enabled() helper for enable checks
- Simplified code throughout by using state methods
Benefits:
- Clearer state lifecycle management
- Better encapsulation and ownership
- Less code duplication
- More maintainable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The old code had a race condition where:
1. R:request() scheduled LSP request setup but immediately suspended
2. R:wait() checked #self.requests (still 0) and returned immediately
3. Finder completed and set running = false
4. Then scheduled function ran and LSP responses came back
5. Callbacks tried to yield items but finder was already done → error
The fix uses a pending counter to track when the scheduled setup function
is running, ensuring we wait for both the setup to complete AND all LSP
responses before the finder completes.
Also improved error handling by checking the err parameter in callbacks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When tmux has extended-keys enabled, Neovim's TermResponse autocmd doesn't fire,
causing terminal response sequences to leak as literal text into buffers.
Workaround: Detect this configuration and query tmux directly for the terminal
name using `tmux display-message -p "#{client_termname}"` instead of sending
escape sequences.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Description
Here are some small and hopefully uncontroversial tweaks to package
extraction from LaTeX preambles:
* Don't consider anything in comments
* Make sure that the extracted names are actually the arguments of
`\usepackage` and not some other macro on the same line
* Stop looking for packages at `\begin{document}`, where the preamble
ends and the body of the document begins (you can't load packages after
this, so any `\usepackage` beyond this point is content, not code. Also
saves a huge amount of work in large documents.)
Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
## Description
The scratch module uses `vim.ui.select` which misses the nice things
about the picker.
This implementation adds scratch picker with ability to create, grep and
delete scratch buffers.
Couldn't figure out how to prettify the scratch buffer's name so any
help would be appreciated.
## 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. -->
---------
Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
## Description
Update the winid (in the `win` variable) after `tab drop`.
## Related Issue(s)
Without this patch, when the user set `confirm` to `{ action =
"confirm", cmd = "tabdrop" }` and jump to a location in a different tab,
since the `win` is still pointing to the original window (tab), there'd
be a `Cursor position outside buffer` error.
Refactored picker resume functionality to support multiple picker states instead of just the last one. Each picker source now maintains its own resume state, allowing users to resume any previously opened picker.
Key improvements:
- Multi-state storage: Each picker source tracks its own state independently
- Flexible API: `Snacks.picker.resume({ source = "files" })` or with include/exclude options
- LSP caching: Cache LSP results for instant resume of LSP pickers
- Better UX: Can resume specific pickers by source name
Moved resume logic to dedicated `picker/resume.lua` module for better separation of concerns.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>