Add fuzzy git file finderZ
This commit is contained in:
@@ -4,28 +4,36 @@ A collection of builtin pipelines for telesceope.
|
||||
Meant for both example and for easy startup.
|
||||
--]]
|
||||
|
||||
local Finder = require('telescope.finder')
|
||||
local pickers = require('telescope.pickers')
|
||||
|
||||
local builtin = {}
|
||||
|
||||
builtin.rg_vimgrep = setmetatable({}, {
|
||||
__call = function(t, ...)
|
||||
-- builtin.rg_vimgrep("--type lua function")
|
||||
print(t, ...)
|
||||
end
|
||||
})
|
||||
builtin.git_files = function(_)
|
||||
-- TODO: Auto select bottom row
|
||||
-- TODO: filter out results when they don't match at all anymore.
|
||||
|
||||
builtin.rg_vimgrep.finder = Finder:new {
|
||||
fn_command = function(prompt)
|
||||
return string.format('rg --vimgrep %s', prompt)
|
||||
end,
|
||||
local telescope = require('telescope')
|
||||
|
||||
responsive = false
|
||||
}
|
||||
local file_finder = telescope.finders.new {
|
||||
static = true,
|
||||
|
||||
builtin.rg_vimgrep.picker = pickers.new {
|
||||
}
|
||||
fn_command = function() return 'git ls-files' end,
|
||||
}
|
||||
|
||||
local file_previewer = telescope.previewers.vim_buffer
|
||||
|
||||
local file_picker = telescope.pickers.new {
|
||||
previewer = file_previewer
|
||||
}
|
||||
|
||||
-- local file_sorter = telescope.sorters.get_ngram_sorter()
|
||||
-- local file_sorter = require('telescope.sorters').get_levenshtein_sorter()
|
||||
local file_sorter = telescope.sorters.get_norcalli_sorter()
|
||||
|
||||
file_picker:find {
|
||||
prompt = 'Simple File',
|
||||
finder = file_finder,
|
||||
sorter = file_sorter,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
return builtin
|
||||
|
||||
@@ -8,6 +8,7 @@ local pickers = require('telescope.pickers')
|
||||
local previewers = require('telescope.previewers')
|
||||
local sorters = require('telescope.sorters')
|
||||
local state = require('telescope.state')
|
||||
local builtin = require('telescope.builtin')
|
||||
|
||||
local telescope = {
|
||||
-- <module>.new { }
|
||||
@@ -17,6 +18,8 @@ local telescope = {
|
||||
sorters = sorters,
|
||||
|
||||
state = state,
|
||||
|
||||
builtin = builtin,
|
||||
}
|
||||
|
||||
function __TelescopeOnLeave(prompt_bufnr)
|
||||
|
||||
@@ -148,6 +148,11 @@ function Picker:find(opts)
|
||||
function(index, line)
|
||||
local row = self.max_results - index + 1
|
||||
|
||||
-- If it's less than 0, then we don't need to show it at all.
|
||||
if row < 0 then
|
||||
return
|
||||
end
|
||||
|
||||
log.trace("Setting row", row, "with value", line)
|
||||
vim.api.nvim_buf_set_lines(results_bufnr, row, row + 1, false, {line})
|
||||
end
|
||||
@@ -161,8 +166,17 @@ function Picker:find(opts)
|
||||
log.trace("Processing result... ", line)
|
||||
|
||||
local sort_score = 0
|
||||
local sort_ok
|
||||
if sorter then
|
||||
sort_score = sorter:score(prompt, line)
|
||||
sort_ok, sort_score = pcall(function ()
|
||||
return sorter:score(prompt, line)
|
||||
end)
|
||||
|
||||
if not sort_ok then
|
||||
log.warn("Sorting failed with:", prompt, line, sort_score)
|
||||
return
|
||||
end
|
||||
|
||||
if sort_score == -1 then
|
||||
log.trace("Filtering out result: ", line)
|
||||
return
|
||||
@@ -347,7 +361,7 @@ pickers.line_manager = function(max_results, set_line)
|
||||
-- line = ...
|
||||
-- metadata ? ...
|
||||
-- }
|
||||
local state = {}
|
||||
local line_state = {}
|
||||
|
||||
set_line = set_line or function() end
|
||||
|
||||
@@ -355,7 +369,7 @@ pickers.line_manager = function(max_results, set_line)
|
||||
add_result = function(self, score, line)
|
||||
score = score or 0
|
||||
|
||||
for index, item in ipairs(state) do
|
||||
for index, item in ipairs(line_state) do
|
||||
if item.score > score then
|
||||
return self:insert(index, {
|
||||
score = score,
|
||||
@@ -378,17 +392,17 @@ pickers.line_manager = function(max_results, set_line)
|
||||
insert = function(self, index, item)
|
||||
if item == nil then
|
||||
item = index
|
||||
index = #state + 1
|
||||
index = #line_state + 1
|
||||
end
|
||||
|
||||
-- To insert something, we place at the next available index (or specified index)
|
||||
-- and then shift all the corresponding items one place.
|
||||
local next_item
|
||||
repeat
|
||||
next_item = state[index]
|
||||
next_item = line_state[index]
|
||||
|
||||
set_line(index, item.line)
|
||||
state[index] = item
|
||||
line_state[index] = item
|
||||
|
||||
index = index + 1
|
||||
item = next_item
|
||||
@@ -396,11 +410,11 @@ pickers.line_manager = function(max_results, set_line)
|
||||
end,
|
||||
|
||||
num_results = function()
|
||||
return #state
|
||||
return #line_state
|
||||
end,
|
||||
|
||||
_get_state = function()
|
||||
return state
|
||||
return line_state
|
||||
end,
|
||||
}, {
|
||||
-- insert =
|
||||
|
||||
@@ -81,7 +81,6 @@ previewers.vim_buffer_or_bat = previewers.new {
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
previewers.Previewer = Previewer
|
||||
|
||||
return previewers
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
local ceil = math.ceil
|
||||
|
||||
local log = require('telescope.log')
|
||||
local util = require('telescope.utils')
|
||||
|
||||
@@ -70,4 +72,80 @@ sorters.get_levenshtein_sorter = function()
|
||||
}
|
||||
end
|
||||
|
||||
sorters.get_norcalli_sorter = function()
|
||||
local ngramlen = 2
|
||||
|
||||
local cached_ngrams = {}
|
||||
|
||||
local function overlapping_ngrams(s, n)
|
||||
if cached_ngrams[s] and cached_ngrams[s][n] then
|
||||
return cached_ngrams[s][n]
|
||||
end
|
||||
|
||||
local R = {}
|
||||
for i = 1, s:len() - n + 1 do
|
||||
R[#R+1] = s:sub(i, i+n-1)
|
||||
end
|
||||
|
||||
if not cached_ngrams[s] then
|
||||
cached_ngrams[s] = {}
|
||||
end
|
||||
|
||||
cached_ngrams[s][n] = R
|
||||
|
||||
return R
|
||||
end
|
||||
|
||||
return Sorter:new {
|
||||
scoring_function = function(_, prompt, line)
|
||||
if prompt == 0 or #prompt < ngramlen then
|
||||
return 0
|
||||
end
|
||||
|
||||
local prompt_ngrams = overlapping_ngrams(prompt, ngramlen)
|
||||
|
||||
local prompt_lower = prompt:lower()
|
||||
local line_lower = line:lower()
|
||||
|
||||
local N = #prompt
|
||||
|
||||
local contains_string = line_lower:find(prompt_lower, 1, true)
|
||||
|
||||
local consecutive_matches = 0
|
||||
local previous_match_index = 0
|
||||
local match_count = 0
|
||||
|
||||
for i = 1, #prompt_ngrams do
|
||||
local match_start = line_lower:find(prompt_ngrams[i], 1, true)
|
||||
if match_start then
|
||||
match_count = match_count + 1
|
||||
if match_start > previous_match_index then
|
||||
consecutive_matches = consecutive_matches + 1
|
||||
end
|
||||
|
||||
previous_match_index = match_start
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: Copied from ashkan.
|
||||
local denominator = (
|
||||
(10 * match_count / #prompt_ngrams)
|
||||
-- biases for shorter strings
|
||||
-- TODO(ashkan): this can bias towards repeated finds of the same
|
||||
-- subpattern with overlapping_ngrams
|
||||
+ 3 * match_count * ngramlen / #line
|
||||
+ consecutive_matches
|
||||
+ N / (contains_string or (2 * #line))
|
||||
-- + 30/(c1 or 2*N)
|
||||
)
|
||||
|
||||
if denominator == 0 or denominator ~= denominator then
|
||||
return -1
|
||||
end
|
||||
|
||||
return 1 / denominator
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
return sorters
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
require('plenary.test_harness'):setup_busted()
|
||||
|
||||
local log = require('telescope.log')
|
||||
-- log.use_console = false
|
||||
|
||||
local pickers = require('telescope.pickers')
|
||||
local utils = require('telescope.utils')
|
||||
|
||||
@@ -179,4 +182,20 @@ describe('Picker', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Sorters', function()
|
||||
describe('norcalli_sorter', function()
|
||||
it('sort matches well', function()
|
||||
local sorter = require('telescope.sorters').get_norcalli_sorter()
|
||||
|
||||
local exact_match = sorter:score('hello', 'hello')
|
||||
local no_match = sorter:score('abcdef', 'ghijkl')
|
||||
local ok_match = sorter:score('abcdef', 'ab')
|
||||
|
||||
assert(exact_match < no_match)
|
||||
assert(exact_match < ok_match)
|
||||
assert(ok_match < no_match)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user