mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 10:49:08 +00:00
feat(picker.matcher): new opts.matcher.file_pos
which defaults to true
to support patterns like file:line:col
or file:line
. Closes #517. Closes #496. Closes #651
This commit is contained in:
parent
01b70b9f01
commit
5e00b0ab27
5 changed files with 38 additions and 3 deletions
|
@ -109,6 +109,7 @@ local defaults = {
|
|||
ignorecase = true, -- use ignorecase
|
||||
sort_empty = false, -- sort results when the search string is empty
|
||||
filename_bonus = true, -- give bonus for matching file names (last part of the path)
|
||||
file_pos = true, -- support patterns like `file:line:col` and `file:line`
|
||||
},
|
||||
sort = {
|
||||
-- default sort is by score, text length and index
|
||||
|
|
|
@ -205,6 +205,7 @@ function M:clear()
|
|||
self.topk:clear()
|
||||
self.top, self.cursor = 1, 1
|
||||
self.items = {}
|
||||
self._current = nil
|
||||
self.dirty = true
|
||||
if next(self.items) == nil then
|
||||
return
|
||||
|
|
|
@ -10,6 +10,7 @@ local Async = require("snacks.picker.util.async")
|
|||
---@field live? boolean
|
||||
---@field score snacks.picker.Score
|
||||
---@field sorting? boolean
|
||||
---@field file? {path: string, pos: snacks.picker.Pos}
|
||||
local M = {}
|
||||
M.__index = M
|
||||
M.DEFAULT_SCORE = 1000
|
||||
|
@ -114,6 +115,7 @@ end
|
|||
function M:init(opts)
|
||||
opts = opts or {}
|
||||
self.tick = self.tick + 1
|
||||
self.file = nil
|
||||
local pattern = vim.trim(opts.pattern or self.pattern)
|
||||
self.mods = {}
|
||||
self.pattern = pattern
|
||||
|
@ -158,7 +160,29 @@ end
|
|||
function M:_prepare(pattern)
|
||||
---@type snacks.picker.matcher.Mods
|
||||
local mods = { pattern = pattern, entropy = 0, chars = {} }
|
||||
local field, p = pattern:match("^([%w_]+):(.*)$")
|
||||
|
||||
local file_patterns = {
|
||||
"^(.*[/\\].*):(%d*):(%d*)$",
|
||||
"^(.*[/\\].*):(%d*)$",
|
||||
"^(.+%.[a-z_]+):(%d*):(%d*)$",
|
||||
"^(.+%.[a-z_]+):(%d*)$",
|
||||
}
|
||||
|
||||
for _, p in ipairs(file_patterns) do
|
||||
local file, line, col = pattern:match(p)
|
||||
if file then
|
||||
mods.field = "file"
|
||||
mods.pattern = file .. "$"
|
||||
self.file = {
|
||||
path = file,
|
||||
pos = { tonumber(line) or 1, tonumber(col) or 0 },
|
||||
}
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- minimum two chars for field pattern
|
||||
local field, p = pattern:match("^([%w_][%w_]+):(.*)$")
|
||||
if field then
|
||||
mods.field = field
|
||||
mods.pattern = p
|
||||
|
@ -217,6 +241,9 @@ function M:update(item)
|
|||
if item.match_tick == self.tick then
|
||||
return false
|
||||
end
|
||||
if item.match_pos then
|
||||
item.pos = nil
|
||||
end
|
||||
local score = self:match(item)
|
||||
if score ~= 0 then
|
||||
if item.score_add then
|
||||
|
@ -225,6 +252,10 @@ function M:update(item)
|
|||
if item.score_mul then
|
||||
score = score * item.score_mul
|
||||
end
|
||||
if self.file and not item.pos then
|
||||
item.pos = self.file.pos
|
||||
item.match_pos = true
|
||||
end
|
||||
end
|
||||
item.match_tick, item.score = self.tick, score
|
||||
return true
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---@class snacks.picker.Preview
|
||||
---@field item? snacks.picker.Item
|
||||
---@field pos? snacks.picker.Pos
|
||||
---@field win snacks.win
|
||||
---@field preview snacks.picker.preview
|
||||
---@field state table<string, any>
|
||||
|
@ -101,11 +102,12 @@ end
|
|||
---@param picker snacks.Picker
|
||||
function M:show(picker)
|
||||
local item, prev = picker:current({ resolve = false }), self.item
|
||||
if self.item == item then
|
||||
if self.item == item and self.pos == (item and item.pos or nil) then
|
||||
return
|
||||
end
|
||||
Snacks.picker.util.resolve(item)
|
||||
self.item = item
|
||||
self.pos = item and item.pos or nil
|
||||
if item then
|
||||
local buf = self.win.buf
|
||||
local ok, err = pcall(
|
||||
|
|
|
@ -182,7 +182,7 @@ function M.parse(str)
|
|||
end
|
||||
|
||||
--- Resolves the item if it has a resolve function
|
||||
---@param item snacks.picker.Item
|
||||
---@param item snacks.picker.Item?
|
||||
function M.resolve(item)
|
||||
if item and item.resolve then
|
||||
item.resolve(item)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue