mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-05 03:08:13 +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 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 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 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"`.
|
--- This is only used when using `opts.preview = "preview"`.
|
||||||
--- It's a previewer that shows a preview based on the item data.
|
--- 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
|
---@field preview? snacks.win.Config|{} preview window config
|
||||||
|
|
||||||
---@class snacks.picker.Config
|
---@class snacks.picker.Config
|
||||||
|
---@field multi? (string|snacks.picker.Config)[]
|
||||||
---@field source? string source name and config to use
|
---@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 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
|
---@field search? string|fun(picker:snacks.Picker):string search string used by finders
|
||||||
|
|
|
@ -76,7 +76,58 @@ function M.get(opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Merge the configs
|
-- 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
|
---@param opts snacks.picker.Config
|
||||||
function M.format(opts)
|
function M.format(opts)
|
||||||
local ret = type(opts.format) == "string" and Snacks.picker.format[opts.format]
|
local ret = type(opts.format) == "string" and Snacks.picker.format[opts.format]
|
||||||
|
@ -86,6 +137,15 @@ function M.format(opts)
|
||||||
return ret
|
return ret
|
||||||
end
|
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
|
---@param opts snacks.picker.Config
|
||||||
function M.preview(opts)
|
function M.preview(opts)
|
||||||
local preview = opts.preview or Snacks.picker.preview.file
|
local preview = opts.preview or Snacks.picker.preview.file
|
||||||
|
|
|
@ -63,7 +63,7 @@ function M.pick(source, opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
opts.source = source or opts.source
|
opts.source = source or opts.source
|
||||||
-- Show pickers if no source, items or finder is provided
|
-- 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"
|
opts.source = "pickers"
|
||||||
return M.pick(opts)
|
return M.pick(opts)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue