mirror of
https://github.com/folke/snacks.nvim
synced 2025-12-23 08:47:57 +00:00
feat(picker): added custom options to vim.ui.select that snacks can use for a better select
This commit is contained in:
parent
5e0e869852
commit
264cab1380
2 changed files with 42 additions and 24 deletions
|
|
@ -312,18 +312,18 @@ function M.lsp_symbol(item, picker)
|
|||
return ret
|
||||
end
|
||||
|
||||
---@param kind? string
|
||||
---@param count number
|
||||
---@param opts snacks.picker.ui_select.Opts
|
||||
---@return snacks.picker.format
|
||||
function M.ui_select(kind, count)
|
||||
return function(item)
|
||||
function M.ui_select(opts)
|
||||
return function(item, picker)
|
||||
local count = picker:count()
|
||||
local ret = {} ---@type snacks.picker.Highlight[]
|
||||
local idx = tostring(item.idx)
|
||||
idx = (" "):rep(#tostring(count) - #idx) .. idx
|
||||
ret[#ret + 1] = { idx .. ".", "SnacksPickerIdx" }
|
||||
ret[#ret + 1] = { " " }
|
||||
|
||||
if kind == "codeaction" then
|
||||
if opts.kind == "codeaction" then
|
||||
---@type lsp.Command|lsp.CodeAction, lsp.HandlerContext
|
||||
local action, ctx = item.item.action, item.item.ctx
|
||||
local client = vim.lsp.get_client_by_id(ctx.client_id)
|
||||
|
|
@ -332,6 +332,13 @@ function M.ui_select(kind, count)
|
|||
ret[#ret + 1] = { " " }
|
||||
ret[#ret + 1] = { ("[%s]"):format(client.name), "SnacksPickerSpecial" }
|
||||
end
|
||||
elseif opts.kind == "snacks" and opts.format_item then
|
||||
local t = opts.format_item(item.item, true)
|
||||
if type(t) == "string" then
|
||||
ret[#ret + 1] = { t }
|
||||
elseif type(t) == "table" then
|
||||
vim.list_extend(ret, t)
|
||||
end
|
||||
else
|
||||
ret[#ret + 1] = { item.formatted }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,37 +2,44 @@ 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 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
|
||||
|
||||
---@generic T
|
||||
---@param items T[] Arbitrary items
|
||||
---@param opts? {prompt?: string, format_item?: (fun(item: T): string), kind?: string}
|
||||
---@param opts? snacks.picker.ui_select.Opts
|
||||
---@param on_choice fun(item?: T, idx?: number)
|
||||
function M.select(items, opts, on_choice)
|
||||
assert(type(on_choice) == "function", "on_choice must be a function")
|
||||
opts = opts or {}
|
||||
|
||||
---@type snacks.picker.finder.Item[]
|
||||
local finder_items = {}
|
||||
for idx, item in ipairs(items) do
|
||||
local text = (opts.format_item or tostring)(item)
|
||||
table.insert(finder_items, {
|
||||
formatted = text,
|
||||
text = idx .. " " .. text,
|
||||
item = item,
|
||||
idx = idx,
|
||||
})
|
||||
end
|
||||
|
||||
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.finder.Item[]
|
||||
return Snacks.picker.pick({
|
||||
---@type snacks.picker.Config
|
||||
local picker_opts = {
|
||||
source = "select",
|
||||
items = finder_items,
|
||||
format = Snacks.picker.format.ui_select(opts.kind, #items),
|
||||
finder = function()
|
||||
---@type snacks.picker.finder.Item[]
|
||||
local ret = {}
|
||||
for idx, item in ipairs(items) do
|
||||
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
|
||||
ret[#ret + 1] = it
|
||||
end
|
||||
return ret
|
||||
end,
|
||||
format = Snacks.picker.format.ui_select(opts),
|
||||
title = title,
|
||||
layout = {
|
||||
layout = opts.picker and opts.picker.layout or {
|
||||
preview = false,
|
||||
layout = {
|
||||
height = math.floor(math.min(vim.o.lines * 0.8 - 10, #items + 2) + 0.5),
|
||||
|
|
@ -57,7 +64,11 @@ function M.select(items, opts, on_choice)
|
|||
completed = true
|
||||
vim.schedule(on_choice)
|
||||
end,
|
||||
})
|
||||
}
|
||||
if opts.picker then
|
||||
picker_opts = Snacks.config.merge({}, vim.deepcopy(picker_opts), opts.picker)
|
||||
end
|
||||
return Snacks.picker.pick(picker_opts)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue