mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 18:58:12 +00:00
feat(picker): multi source picker. Combine multiple pickers (as opposed to just finders) in one picker
This commit is contained in:
parent
5e69fb83d5
commit
9434986ff1
3 changed files with 64 additions and 2 deletions
|
@ -15,6 +15,7 @@ local M = {}
|
|||
---@field buf? boolean|number only show items for the current or given buffer
|
||||
---@field paths? table<string, boolean> only show items that include or exclude the given paths
|
||||
---@field filter? fun(item:snacks.picker.finder.Item, filter:snacks.picker.Filter):boolean? custom filter function
|
||||
---@field transform? fun(picker:snacks.Picker, filter:snacks.picker.Filter):boolean? filter transform. Return `true` to force refresh
|
||||
|
||||
--- This is only used when using `opts.preview = "preview"`.
|
||||
--- It's a previewer that shows a preview based on the item data.
|
||||
|
@ -59,6 +60,7 @@ local M = {}
|
|||
---@field preview? snacks.win.Config|{} preview window config
|
||||
|
||||
---@class snacks.picker.Config
|
||||
---@field multi? (string|snacks.picker.Config)[]
|
||||
---@field source? string source name and config to use
|
||||
---@field pattern? string|fun(picker:snacks.Picker):string pattern used to filter items by the matcher
|
||||
---@field search? string|fun(picker:snacks.Picker):string search string used by finders
|
||||
|
|
|
@ -76,7 +76,58 @@ function M.get(opts)
|
|||
end
|
||||
|
||||
-- Merge the configs
|
||||
return Snacks.config.merge(unpack(todo))
|
||||
opts = Snacks.config.merge(unpack(todo))
|
||||
M.multi(opts)
|
||||
return opts
|
||||
end
|
||||
|
||||
---@param opts snacks.picker.Config
|
||||
function M.multi(opts)
|
||||
if not opts.multi then
|
||||
return opts
|
||||
end
|
||||
local Finder = require("snacks.picker.core.finder")
|
||||
|
||||
local finders = {} ---@type snacks.picker.finder[]
|
||||
local formats = {} ---@type snacks.picker.format[]
|
||||
local previews = {} ---@type snacks.picker.preview[]
|
||||
local confirms = {} ---@type snacks.picker.Action.spec[]
|
||||
|
||||
local sources = {} ---@type snacks.picker.Config[]
|
||||
for _, source in ipairs(opts.multi) do
|
||||
if type(source) == "string" then
|
||||
source = { source = source }
|
||||
end
|
||||
---@cast source snacks.picker.Config
|
||||
source = Snacks.config.merge({}, opts.sources[source.source], source) --[[@as snacks.picker.Config]]
|
||||
source.actions = source.actions or {}
|
||||
if source.confirm then
|
||||
source.actions.confirm = source.confirm
|
||||
end
|
||||
local finder = M.finder(source.finder)
|
||||
finders[#finders + 1] = function(fopts, filter, picker)
|
||||
fopts = Snacks.config.merge({}, vim.deepcopy(source), fopts)
|
||||
return finder(fopts, filter, picker)
|
||||
end
|
||||
confirms[#confirms + 1] = source.actions.confirm or "jump"
|
||||
previews[#previews + 1] = M.preview(source)
|
||||
formats[#formats + 1] = M.format(source)
|
||||
sources[#sources + 1] = source
|
||||
end
|
||||
|
||||
opts.finder = opts.finder or Finder.multi(finders)
|
||||
opts.format = opts.format or function(item, picker)
|
||||
return formats[item.fid](item, picker)
|
||||
end
|
||||
opts.preview = opts.preview or function(ctx)
|
||||
return previews[ctx.item.fid](ctx)
|
||||
end
|
||||
opts.confirm = opts.confirm
|
||||
or function(picker, item, action)
|
||||
return confirms[item.fid](picker, item, action)
|
||||
end
|
||||
end
|
||||
|
||||
---@param opts snacks.picker.Config
|
||||
function M.format(opts)
|
||||
local ret = type(opts.format) == "string" and Snacks.picker.format[opts.format]
|
||||
|
@ -86,6 +137,15 @@ function M.format(opts)
|
|||
return ret
|
||||
end
|
||||
|
||||
---@param opts snacks.picker.Config
|
||||
function M.transform(opts)
|
||||
local ret = type(opts.transform) == "string" and require("snacks.picker.transform")[opts.transform]
|
||||
or opts.transform
|
||||
or nil
|
||||
---@cast ret snacks.picker.transform?
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param opts snacks.picker.Config
|
||||
function M.preview(opts)
|
||||
local preview = opts.preview or Snacks.picker.preview.file
|
||||
|
|
|
@ -63,7 +63,7 @@ function M.pick(source, opts)
|
|||
opts = opts or {}
|
||||
opts.source = source or opts.source
|
||||
-- Show pickers if no source, items or finder is provided
|
||||
if not (opts.source or opts.items or opts.finder) then
|
||||
if not (opts.source or opts.items or opts.finder or opts.multi) then
|
||||
opts.source = "pickers"
|
||||
return M.pick(opts)
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue