feat: Improve filtering ideas for sorters.
This commit is contained in:
@@ -394,6 +394,10 @@ function Picker:find()
|
|||||||
|
|
||||||
local prompt = vim.trim(vim.api.nvim_buf_get_lines(prompt_bufnr, first_line, last_line, false)[1]:sub(#prompt_prefix))
|
local prompt = vim.trim(vim.api.nvim_buf_get_lines(prompt_bufnr, first_line, last_line, false)[1]:sub(#prompt_prefix))
|
||||||
|
|
||||||
|
if self.sorter then
|
||||||
|
self.sorter:_start(prompt)
|
||||||
|
end
|
||||||
|
|
||||||
-- TODO: Statusbar possibilities here.
|
-- TODO: Statusbar possibilities here.
|
||||||
-- vim.api.nvim_buf_set_virtual_text(prompt_bufnr, 0, 1, { {"hello", "Error"} }, {})
|
-- vim.api.nvim_buf_set_virtual_text(prompt_bufnr, 0, 1, { {"hello", "Error"} }, {})
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ local ngram_highlighter = function(ngram_len, prompt, display)
|
|||||||
return highlights
|
return highlights
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local FILTERED = -1
|
||||||
|
|
||||||
|
|
||||||
local Sorter = {}
|
local Sorter = {}
|
||||||
Sorter.__index = Sorter
|
Sorter.__index = Sorter
|
||||||
@@ -39,12 +41,68 @@ function Sorter:new(opts)
|
|||||||
state = {},
|
state = {},
|
||||||
scoring_function = opts.scoring_function,
|
scoring_function = opts.scoring_function,
|
||||||
highlighter = opts.highlighter,
|
highlighter = opts.highlighter,
|
||||||
|
discard = opts.discard,
|
||||||
|
_discard_state = {
|
||||||
|
filtered = {},
|
||||||
|
prompt = '',
|
||||||
|
},
|
||||||
}, Sorter)
|
}, Sorter)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO: We could make this a bit smarter and cache results "as we go" and where they got filtered.
|
||||||
|
-- Then when we hit backspace, we don't have to re-caculate everything.
|
||||||
|
-- Prime did a lot of the hard work already, but I don't want to copy as much memory around
|
||||||
|
-- as he did in his example.
|
||||||
|
-- Example can be found in ./scratch/prime_prompt_cache.lua
|
||||||
|
function Sorter:_start(prompt)
|
||||||
|
if not self.discard then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local previous = self._discard_state.prompt
|
||||||
|
local len_previous = #previous
|
||||||
|
|
||||||
|
if #prompt < len_previous then
|
||||||
|
log.debug("Reset discard because shorter prompt")
|
||||||
|
self._discard_state.filtered = {}
|
||||||
|
elseif string.sub(prompt, 1, len_previous) ~= previous then
|
||||||
|
log.debug("Reset discard no match")
|
||||||
|
self._discard_state.filtered = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
self._discard_state.prompt = prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: Consider doing something that makes it so we can skip the filter checks
|
||||||
|
-- if we're not discarding. Also, that means we don't have to check otherwise as well :)
|
||||||
function Sorter:score(prompt, entry)
|
function Sorter:score(prompt, entry)
|
||||||
if not entry or not entry.ordinal then return -1 end
|
if not entry or not entry.ordinal then return -1 end
|
||||||
return self:scoring_function(prompt or "", entry.ordinal, entry)
|
|
||||||
|
local ordinal = entry.ordinal
|
||||||
|
|
||||||
|
if self:_was_discarded(prompt, ordinal) then
|
||||||
|
return FILTERED
|
||||||
|
end
|
||||||
|
|
||||||
|
local score = self:scoring_function(prompt or "", ordinal, entry)
|
||||||
|
|
||||||
|
if score == FILTERED then
|
||||||
|
self:_mark_discarded(prompt, ordinal)
|
||||||
|
end
|
||||||
|
|
||||||
|
return score
|
||||||
|
end
|
||||||
|
|
||||||
|
function Sorter:_was_discarded(prompt, ordinal)
|
||||||
|
return self.discard and self._discard_state.filtered[ordinal]
|
||||||
|
end
|
||||||
|
|
||||||
|
function Sorter:_mark_discarded(prompt, ordinal)
|
||||||
|
if not self.discard then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self._discard_state.filtered[ordinal] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function sorters.new(...)
|
function sorters.new(...)
|
||||||
@@ -313,6 +371,8 @@ sorters.get_fzy_sorter = function()
|
|||||||
local OFFSET = -fzy.get_score_floor()
|
local OFFSET = -fzy.get_score_floor()
|
||||||
|
|
||||||
return sorters.Sorter:new{
|
return sorters.Sorter:new{
|
||||||
|
discard = true,
|
||||||
|
|
||||||
scoring_function = function(_, prompt, line)
|
scoring_function = function(_, prompt, line)
|
||||||
-- Check for actual matches before running the scoring alogrithm.
|
-- Check for actual matches before running the scoring alogrithm.
|
||||||
if not fzy.has_match(prompt, line) then
|
if not fzy.has_match(prompt, line) then
|
||||||
|
|||||||
138
scratch/prime_prompt_cache.lua
Normal file
138
scratch/prime_prompt_cache.lua
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
local log = require('telescope.log')
|
||||||
|
|
||||||
|
local PromptCache = {}
|
||||||
|
|
||||||
|
function getFirstByteDiffIdx(a, b)
|
||||||
|
local idx = 1
|
||||||
|
local max_idx = #a
|
||||||
|
while a:byte(idx) == b:byte(idx) and idx <= max_idx do
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return idx
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:new(opts)
|
||||||
|
self.__index = self
|
||||||
|
local obj = setmetatable({
|
||||||
|
current_line = nil,
|
||||||
|
cached_results = {},
|
||||||
|
cache_round = 0
|
||||||
|
}, self)
|
||||||
|
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:set_cache(prompt, item_to_cache)
|
||||||
|
self.results = item_to_cache
|
||||||
|
self:_complete(prompt)
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:_complete(prompt)
|
||||||
|
if #prompt == 0 then
|
||||||
|
self:_reset()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local cached_lines = self.results
|
||||||
|
|
||||||
|
local idx = 1
|
||||||
|
if self.current_line ~= nil then
|
||||||
|
idx = getFirstByteDiffIdx(self.current_line, prompt)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ABC
|
||||||
|
-- ABDC
|
||||||
|
-- IDX = 3
|
||||||
|
-- cr = 3
|
||||||
|
-- diff = 1
|
||||||
|
local diff = #self.cached_results - (idx - 1)
|
||||||
|
while diff > 0 do
|
||||||
|
table.remove(self.cached_results)
|
||||||
|
diff = diff - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ABC
|
||||||
|
-- ADBC
|
||||||
|
-- diff = 2
|
||||||
|
for i = idx, #prompt do
|
||||||
|
if #self.cached_results < (#prompt - 1) then
|
||||||
|
local last_cache = self:get_last_cache()
|
||||||
|
table.insert(self.cached_results, last_cache)
|
||||||
|
else
|
||||||
|
table.insert(self.cached_results, cached_lines)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.current_line = prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:start_round(cache_round)
|
||||||
|
self.cache_round = cache_round
|
||||||
|
log.trace("start_round (had this", self.results and #self.results or nil, "for past results)", self.cache_round)
|
||||||
|
self.results = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:add_to_round(cache_round, line, score)
|
||||||
|
if cache_round < self.cache_round or score == -1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(self.results, line)
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:get_last_cache()
|
||||||
|
local last_cache = nil
|
||||||
|
|
||||||
|
for idx = 1, #self.cached_results do
|
||||||
|
local cache = self.cached_results[idx]
|
||||||
|
if cache then
|
||||||
|
last_cache = cache
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return last_cache
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:complete_round(cache_round, prompt)
|
||||||
|
if cache_round ~= self.cache_round then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self:_complete(prompt)
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:get_cache(prompt)
|
||||||
|
if self.current_line == nil or #prompt == 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local idx = getFirstByteDiffIdx(self.current_line, prompt)
|
||||||
|
|
||||||
|
if idx == 1 then
|
||||||
|
self:_reset()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if we are off, then we simply need to prune the cache or let complete do
|
||||||
|
-- that
|
||||||
|
local results = nil
|
||||||
|
repeat
|
||||||
|
results = self.cached_results[idx - 1]
|
||||||
|
idx = idx - 1
|
||||||
|
until idx <= 1 or results
|
||||||
|
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
function PromptCache:_reset()
|
||||||
|
self.current_line = nil
|
||||||
|
self.cached_results = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
PromptCache = PromptCache
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user