8000 mini.nvim/lua/mini/fuzzy.lua at main · AgatZan/mini.nvim · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
376 lines (330 loc) · 14.3 KB

fuzzy.lua

File metadata and controls

376 lines (330 loc) · 14.3 KB
end
-- Actually compute best matched positions from best last letter match
local best_positions = { best_pos_last }
local rev_pos = n_candidate - best_pos_last + 1
for i = #letters - 1, 1, -1 do
rev_pos = rev_candidate:find(letters[i], rev_pos + 1)
-- For relatively small number of letters (around 10, which is main use
-- case) inserting to front seems to have better performance than
-- inserting at end and then reversing.
table.insert(best_positions, 1, n_candidate - rev_pos + 1)
end
return best_positions
end
-- Compute score of matched positions. Smaller values indicate better match
-- (i.e. like distance). Reasoning behind the score is for it to produce the
-- same ordering as with sequential comparison of match's width and first
-- position. So it shouldn't really be perceived as linear distance (difference
-- between scores don't really matter, only their comparison with each other).
--
-- Reasoning behind comparison logic (based on 'time' input):
-- - '_time' is better than 't_ime' (width is smaller).
-- - 'time_aa' is better than 'aa_time' (same width, first match is smaller).
--
-- Returns -1 if `positions` is `nil` or empty.
H.score_positions = function(positions)
if not positions or #positions == 0 then return -1 end
local first, last = positions[1], positions[#positions]
local cutoff = H.get_config().cutoff
return cutoff * math.min(last - first + 1, cutoff) + math.min(first, cutoff)
end
H.make_filter_indexes = function(word, candidate_array)
-- Precompute a table of word's letters
local letters = H.string_to_letters(word)
local res = {}
for i, cand in ipairs(candidate_array) do
local positions = H.find_best_positions(letters, cand)
if positions then table.insert(res, { index = i, score = H.score_positions(positions) }) end
end
return res
end
H.compare_filter_indexes = function(a, b)
if a.score < b.score then return true end
if a.score == b.score then
-- Make sorting stable by preserving index order
return a.index < b.index
end
return false
end
H.filter_by_indexes = function(candidate_array, ids)
local res, res_ids = {}, {}
for _, id in pairs(ids) do
table.insert(res, candidate_array[id.index])
table.insert(res_ids, id.index)
end
return res, res_ids
end
-- Utilities ------------------------------------------------------------------
H.string_to_letters = function(s) return vim.tbl_map(vim.pesc, vim.split(s, '')) end
return MiniFuzzy
0