fix(picker.list): include search filter for highlighting items (live search). See #474

This commit is contained in:
Folke Lemaitre 2025-01-15 10:12:47 +01:00
parent e23d15623e
commit 1693fbb0dc
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
2 changed files with 13 additions and 6 deletions

View file

@ -13,6 +13,7 @@
---@field reverse? boolean
---@field selected snacks.picker.Item[]
---@field selected_map table<string, snacks.picker.Item>
---@field matcher snacks.picker.Matcher matcher for formatting list items
local M = {}
M.__index = M
@ -35,6 +36,7 @@ function M.new(picker)
self.picker = picker
self.selected = {}
self.selected_map = {}
self.matcher = require("snacks.picker.core.matcher").new(picker.opts.matcher)
local win_opts = Snacks.win.resolve(picker.opts.win.list, {
show = false,
enter = false,
@ -374,7 +376,7 @@ function M:format(item)
end
end
local str = table.concat(parts, ""):gsub("\n", " ")
local _, positions = self.picker.matcher:match({ text = str:gsub("%s*$", ""), idx = 1, score = 0 }, {
local _, positions = self.matcher:match({ text = str:gsub("%s*$", ""), idx = 1, score = 0 }, {
positions = true,
force = true,
})
@ -424,6 +426,13 @@ function M:render()
local lines = vim.split(string.rep("\n", self.state.height), "\n")
vim.api.nvim_buf_set_lines(self.win.buf, 0, -1, false, lines)
-- matcher for highlighting should include the search filter
local pattern = vim.trim(self.picker.input.filter.pattern .. " " .. self.picker.input.filter.search)
if self.matcher.pattern ~= pattern then
self.matcher:init({ pattern = pattern })
end
-- render items
for i = self.top, math.min(self:count(), self.top + height - 1) do
local item = assert(self:get(i), "item not found")
local row = self:idx2row(i)

View file

@ -52,7 +52,6 @@ function M.new(opts)
self.min_score = 0
self.task = Async.nop()
self.mods = {}
self.live = false
self.tick = 0
return self
end
@ -118,7 +117,7 @@ function M:run(picker, opts)
end)
end
---@param opts? {pattern?: string, live?: boolean}
---@param opts? {pattern?: string}
function M:init(opts)
opts = opts or {}
self.tick = self.tick + 1
@ -128,7 +127,6 @@ function M:init(opts)
self.pattern = pattern
self:abort()
self.one = nil
self.live = opts.live
if pattern == "" then
return
end
@ -227,11 +225,11 @@ function M:update(item)
end
---@param item snacks.picker.Item
---@param opts? {positions: boolean, force?: boolean}
---@param opts? {positions: boolean}
---@return number score, number[]? positions
function M:match(item, opts)
opts = opts or {}
if self:empty() or (self.live and not opts.force) then
if self:empty() then
return M.DEFAULT_SCORE -- empty pattern matches everything
end
local score = 0