Did you check docs and existing issues?
Neovim version (nvim -v)
NVIM v0.12.4
Operating system/version
macOS 14.4
Describe the bug
Snacks.win.resolve(...) gives precedence to its last argument:
Snacks.win.resolve({ wo = { winhighlight = "A" } }, { wo = { winhighlight = "B" } }).wo.winhighlight
--> "B"
win.lua:257 relies on that ordering — M.resolve(Snacks.config.get("win", defaults), opts) — defaults first, user opts last, so user config wins.
The picker's list and input windows call it the other way around:
picker/core/list.lua:71 — Snacks.win.resolve(picker.opts.win.list, { --[[ defaults ]] })
picker/core/input.lua:22 — Snacks.win.resolve(picker.opts.win.input, { --[[ defaults ]] })
So every key those default tables set is unconfigurable through win.list / win.input — globally, per-source, or per-call. The user value isn't merged and losing on a sub-key; it's dropped entirely. wo.winhighlight is the one I hit, but the same applies to wo.cursorline, bo.filetype, minimal, on_win, and the rest.
The box windows and the preview window are constructed differently and aren't affected.
For context on why this isn't just cosmetic: there's no other injection point for these windows either. Mutating win.opts.wo after construction is undone by layout.lua:472, which rebuilds win.opts from the deep copy layout.lua:105 took when the layout was built. Writing the live vim.wo option is undone by win:update() (win.lua:806) on the next layout update, which runs under eventignore = "all" (layout.lua:283-289) so no autocmd can react to it. So for these two windows the defaults are effectively final.
My use case is theming: I want the explorer source, which uses a sidebar layout flush against the terminal edge, to paint on a different background than the floating pickers. They share SnacksPickerList / SnacksPickerInput, and per-source win config is the natural lever.
Steps To Reproduce
nvim -u repro.lua
- The files picker opens and prints the configured vs. actual
winhighlight.
configured: NormalFloat:ErrorMsg
actual : FloatFooter:SnacksPickerListFooter,CursorLine:SnacksPickerListCursorLine,NormalFloat:SnacksPickerList,FloatBorder:SnacksPickerListBorder,FloatTitle:SnacksPickerListTitle
Expected Behavior
win.list.wo.winhighlight overrides the built-in default, the way win config does everywhere else in snacks.
Swapping the arguments at those two call sites — Snacks.win.resolve({ --[[ defaults ]] }, picker.opts.win.list) — lines them up with win.lua:257. Happy to open a PR if you'd like it that way.
Repro
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
require("lazy.minit").repro({
spec = {
{ "folke/snacks.nvim", opts = { picker = {} } },
},
})
vim.defer_fn(function()
Snacks.picker.files({
win = { list = { wo = { winhighlight = "NormalFloat:ErrorMsg" } } },
on_show = function(p)
print("configured: NormalFloat:ErrorMsg")
print("actual : " .. p.list.win.opts.wo.winhighlight)
end,
})
end, 500)
Did you check docs and existing issues?
Neovim version (nvim -v)
NVIM v0.12.4
Operating system/version
macOS 14.4
Describe the bug
Snacks.win.resolve(...)gives precedence to its last argument:win.lua:257relies on that ordering —M.resolve(Snacks.config.get("win", defaults), opts)— defaults first, user opts last, so user config wins.The picker's list and input windows call it the other way around:
picker/core/list.lua:71—Snacks.win.resolve(picker.opts.win.list, { --[[ defaults ]] })picker/core/input.lua:22—Snacks.win.resolve(picker.opts.win.input, { --[[ defaults ]] })So every key those default tables set is unconfigurable through
win.list/win.input— globally, per-source, or per-call. The user value isn't merged and losing on a sub-key; it's dropped entirely.wo.winhighlightis the one I hit, but the same applies towo.cursorline,bo.filetype,minimal,on_win, and the rest.The box windows and the preview window are constructed differently and aren't affected.
For context on why this isn't just cosmetic: there's no other injection point for these windows either. Mutating
win.opts.woafter construction is undone bylayout.lua:472, which rebuildswin.optsfrom the deep copylayout.lua:105took when the layout was built. Writing the livevim.wooption is undone bywin:update()(win.lua:806) on the next layout update, which runs undereventignore = "all"(layout.lua:283-289) so no autocmd can react to it. So for these two windows the defaults are effectively final.My use case is theming: I want the
explorersource, which uses a sidebar layout flush against the terminal edge, to paint on a different background than the floating pickers. They shareSnacksPickerList/SnacksPickerInput, and per-sourcewinconfig is the natural lever.Steps To Reproduce
nvim -u repro.luawinhighlight.Expected Behavior
win.list.wo.winhighlightoverrides the built-in default, the waywinconfig does everywhere else in snacks.Swapping the arguments at those two call sites —
Snacks.win.resolve({ --[[ defaults ]] }, picker.opts.win.list)— lines them up withwin.lua:257. Happy to open a PR if you'd like it that way.Repro