mirror of
https://github.com/folke/snacks.nvim
synced 2025-12-23 08:47:57 +00:00
This commit is contained in:
parent
471eb036c4
commit
2b9d52258d
4 changed files with 63 additions and 58 deletions
|
|
@ -587,6 +587,7 @@ M.lsp_references = {
|
|||
-- LSP document symbols
|
||||
---@class snacks.picker.lsp.symbols.Config: snacks.picker.Config
|
||||
---@field tree? boolean show symbol tree
|
||||
---@field keep_parents? boolean keep parent symbols when filtering
|
||||
---@field filter table<string, string[]|boolean>? symbol kind filter
|
||||
---@field workspace? boolean show workspace symbols
|
||||
M.lsp_symbols = {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ local Async = require("snacks.picker.util.async")
|
|||
---@field regex? boolean used internally for positions of sources that use regex
|
||||
---@field on_match? fun(matcher: snacks.picker.Matcher, item: snacks.picker.Item)
|
||||
---@field on_done? fun(matcher: snacks.picker.Matcher)
|
||||
---@field keep_parents? boolean
|
||||
---@field sort? boolean
|
||||
|
||||
---@class snacks.picker.Matcher
|
||||
---@field opts snacks.picker.matcher.Config
|
||||
|
|
@ -80,21 +82,64 @@ function M:close()
|
|||
self.task = Async.nop()
|
||||
end
|
||||
|
||||
---@param picker snacks.Picker
|
||||
---@param item snacks.picker.Item
|
||||
function M:on_match(picker, item)
|
||||
if self.opts.on_match then
|
||||
self.opts.on_match(self, item)
|
||||
end
|
||||
|
||||
if not self.opts.keep_parents or item.score == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local parent = item.parent
|
||||
item.child_match_only = false
|
||||
while parent and not parent.root do
|
||||
if parent.score == 0 or parent.match_tick ~= self.tick then
|
||||
parent.score = 1
|
||||
parent.child_match_only = true
|
||||
parent.match_tick = self.tick
|
||||
parent.match_topk = nil
|
||||
picker.list:add(parent, self.sorting)
|
||||
else
|
||||
break
|
||||
end
|
||||
parent = parent.parent
|
||||
end
|
||||
end
|
||||
|
||||
---@param picker snacks.Picker
|
||||
function M:on_done(picker)
|
||||
vim.schedule(function()
|
||||
if self.opts.on_done then
|
||||
self.opts.on_done(self)
|
||||
end
|
||||
if not self.opts.keep_parents or picker.closed then
|
||||
return
|
||||
end
|
||||
for item, idx in picker:iter() do
|
||||
if not item.child_match_only then
|
||||
picker.list:view(idx)
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@param picker snacks.Picker
|
||||
function M:run(picker)
|
||||
self.task:abort()
|
||||
picker.list:clear()
|
||||
|
||||
self.cwd = svim.fs.normalize(picker.opts.cwd or (vim.uv or vim.loop).cwd() or ".")
|
||||
self.sorting = not self:empty() or picker.opts.matcher.sort_empty
|
||||
self.sorting = self.opts.sort ~= false and (not self:empty() or picker.opts.matcher.sort_empty)
|
||||
|
||||
-- PERF: fast path for empty pattern
|
||||
if not (self.sorting or picker.finder.task:running()) then
|
||||
if not self.sorting and not picker.finder.task:running() and self:empty() then
|
||||
picker.list.items = picker.finder.items
|
||||
picker:update({ force = true })
|
||||
if self.opts.on_done then
|
||||
self.opts.on_done(self)
|
||||
end
|
||||
self:on_done(picker)
|
||||
return
|
||||
end
|
||||
|
||||
|
|
@ -105,7 +150,7 @@ function M:run(picker)
|
|||
---@async
|
||||
---@param item snacks.picker.Item
|
||||
local function check(item)
|
||||
if self:update(item) then
|
||||
if self:update(picker, item) then
|
||||
picker.list:add(item, self.sorting)
|
||||
end
|
||||
yield()
|
||||
|
|
@ -161,11 +206,7 @@ function M:run(picker)
|
|||
until idx >= #picker.finder.items and not picker.finder.task:running()
|
||||
|
||||
picker:update({ force = true })
|
||||
if self.opts.on_done then
|
||||
vim.schedule(function()
|
||||
self.opts.on_done(self)
|
||||
end)
|
||||
end
|
||||
self:on_done(picker)
|
||||
end)
|
||||
end
|
||||
|
||||
|
|
@ -307,9 +348,10 @@ function M:_prepare(pattern)
|
|||
return mods
|
||||
end
|
||||
|
||||
---@param picker snacks.Picker
|
||||
---@param item snacks.picker.Item
|
||||
---@return boolean matched
|
||||
function M:update(item)
|
||||
function M:update(picker, item)
|
||||
if item.match_pos then
|
||||
item.pos = nil
|
||||
end
|
||||
|
|
@ -339,9 +381,7 @@ function M:update(item)
|
|||
end
|
||||
end
|
||||
item.score = score
|
||||
if self.opts.on_match then
|
||||
self.opts.on_match(self, item)
|
||||
end
|
||||
self:on_match(picker, item)
|
||||
else
|
||||
item.score = 0
|
||||
end
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ end
|
|||
---@param opts snacks.picker.explorer.Config
|
||||
function M.setup(opts)
|
||||
local searching = false
|
||||
local ref ---@type snacks.Picker.ref
|
||||
return Snacks.config.merge(opts, {
|
||||
actions = {
|
||||
confirm = Actions.actions.confirm,
|
||||
|
|
@ -153,7 +152,6 @@ function M.setup(opts)
|
|||
---@param picker snacks.Picker
|
||||
---@param filter snacks.picker.Filter
|
||||
transform = function(picker, filter)
|
||||
ref = picker:ref()
|
||||
local s = not filter:is_empty()
|
||||
if searching ~= s then
|
||||
searching = s
|
||||
|
|
@ -162,46 +160,6 @@ function M.setup(opts)
|
|||
end
|
||||
end,
|
||||
},
|
||||
matcher = {
|
||||
--- Add parent dirs to matching items
|
||||
---@param matcher snacks.picker.Matcher
|
||||
---@param item snacks.picker.explorer.Item
|
||||
on_match = function(matcher, item)
|
||||
if not searching then
|
||||
return
|
||||
end
|
||||
local picker = ref.value
|
||||
if picker and item.score > 0 then
|
||||
local parent = item.parent
|
||||
while parent do
|
||||
if parent.score == 0 or parent.match_tick ~= matcher.tick then
|
||||
parent.score = 1
|
||||
parent.match_tick = matcher.tick
|
||||
parent.match_topk = nil
|
||||
picker.list:add(parent)
|
||||
else
|
||||
break
|
||||
end
|
||||
parent = parent.parent
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_done = function()
|
||||
if not searching then
|
||||
return
|
||||
end
|
||||
local picker = ref.value
|
||||
if not picker or picker.closed then
|
||||
return
|
||||
end
|
||||
for item, idx in picker:iter() do
|
||||
if not item.dir then
|
||||
picker.list:view(idx)
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
},
|
||||
formatters = {
|
||||
file = {
|
||||
filename_only = opts.tree,
|
||||
|
|
@ -223,7 +181,9 @@ end
|
|||
function M.explorer(opts, ctx)
|
||||
local state = M.get_state(ctx.picker)
|
||||
|
||||
ctx.picker.matcher.opts.keep_parents = false
|
||||
if state:setup(ctx) then
|
||||
ctx.picker.matcher.opts.keep_parents = true
|
||||
return M.search(opts, ctx)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ function M.results_to_items(client, results, opts)
|
|||
result.children = nil
|
||||
end
|
||||
|
||||
local root = { text = "" } ---@type snacks.picker.finder.Item
|
||||
local root = { text = "", root = true } ---@type snacks.picker.finder.Item
|
||||
---@type snacks.picker.finder.Item
|
||||
for _, result in ipairs(results) do
|
||||
add(result, root)
|
||||
|
|
@ -330,6 +330,10 @@ end
|
|||
---@param opts snacks.picker.lsp.symbols.Config
|
||||
---@type snacks.picker.finder
|
||||
function M.symbols(opts, ctx)
|
||||
if opts.keep_parents then
|
||||
ctx.picker.matcher.opts.keep_parents = true
|
||||
ctx.picker.matcher.opts.sort = false
|
||||
end
|
||||
local buf = ctx.filter.current_buf
|
||||
-- For unloaded buffers, load the buffer and
|
||||
-- refresh the picker on every LspAttach event
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue