feat(select): allow configuring options for specific vim.ui.select kinds

This commit is contained in:
Folke Lemaitre 2025-10-23 18:52:39 +02:00
parent 8625e4bd72
commit bca5b05838
No known key found for this signature in database
GPG key ID: 9B52594D560070AB
4 changed files with 31 additions and 11 deletions

View file

@ -40,7 +40,9 @@ function M.fix_keys(opts)
return opts
end
---@param opts? snacks.picker.Config
---@generic T:snacks.picker.Config
---@param opts? T
---@return T
function M.get(opts)
M.setup()
opts = M.fix_keys(opts)

View file

@ -837,6 +837,8 @@ M.search_history = {
--- Config used by `vim.ui.select`.
--- Not meant to be used directly.
---@class snacks.picker.select.Config: snacks.picker.Config
---@field kinds? table<string, snacks.picker.Config|{}> custom snacks picker configs for specific `vim.ui.select` kinds
M.select = {
items = {}, -- these are set dynamically
main = { current = true },

View file

@ -350,7 +350,7 @@ function M.ui_select(opts)
ret[#ret + 1] = { " " }
ret[#ret + 1] = { ("[%s]"):format(client.name), "SnacksPickerSpecial" }
end
elseif opts.kind == "snacks" and opts.format_item then
elseif opts.format_item then
local t = opts.format_item(item.item, true)
if type(t) == "string" then
ret[#ret + 1] = { t }
@ -358,7 +358,7 @@ function M.ui_select(opts)
vim.list_extend(ret, t)
end
else
ret[#ret + 1] = { item.formatted }
ret[#ret + 1] = { tostring(item.item) }
end
return ret
end

View file

@ -1,10 +1,16 @@
local M = {}
---@alias snacks.picker.ui_select fun(items: any[], opts?: {prompt?: string, format_item?: (fun(item: any): string), kind?: string}, on_choice: fun(item?: any, idx?: number))
---@class vim.ui.select.Opts
---@field prompt? string
---@field format_item? fun(item: any): string
---@field kind? string
---@alias vim.ui.select.on_choice fun(item?: any, idx?: number)
---@alias snacks.picker.ui_select fun(items: any[], opts?: vim.ui.select.Opts, on_choice: vim.ui.select.on_choice)
---@class snacks.picker.ui_select.Opts: vim.ui.select.Opts
---@field format_item? fun(item: any, is_snacks: boolean):(string|snacks.picker.Highlight[])
---@field picker? snacks.picker.Config
---@field format_item? fun(item: any, supports_chunks: boolean):(string|snacks.picker.Highlight[])
---@field snacks? snacks.picker.Config
---@generic T
---@param items T[] Arbitrary items
@ -17,9 +23,8 @@ function M.select(items, opts, on_choice)
local title = opts.prompt or "Select"
title = title:gsub("^%s*", ""):gsub("[%s:]*$", "")
local completed = false
opts.kind = opts.kind or (opts.picker and "snacks") or opts.kind
---@type snacks.picker.Config
---@type snacks.picker.select.Config
local picker_opts = {
source = "select",
finder = function()
@ -29,7 +34,6 @@ function M.select(items, opts, on_choice)
local text = (opts.format_item or tostring)(item)
---@type snacks.picker.finder.Item
local it = type(item) == "table" and setmetatable({}, { __index = item }) or {}
it.formatted = text
it.text = idx .. " " .. text
it.item = item
it.idx = idx
@ -69,9 +73,21 @@ function M.select(items, opts, on_choice)
vim.schedule(on_choice)
end,
}
if opts.picker then
picker_opts = Snacks.config.merge({}, vim.deepcopy(picker_opts), opts.picker)
-- merge custom picker options
if opts.snacks then
picker_opts = Snacks.config.merge({}, vim.deepcopy(picker_opts), opts.snacks)
end
-- get full picker config
picker_opts = Snacks.picker.config.get(picker_opts)
-- merge kind options
local kind_opts = picker_opts.kinds and picker_opts.kinds[opts.kind]
if kind_opts then
picker_opts = Snacks.config.merge({}, picker_opts, kind_opts)
end
return Snacks.picker.pick(picker_opts)
end