summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorTJ DeVries <devries.timothyj@gmail.com>2020-08-24 12:31:57 -0400
committerTJ DeVries <devries.timothyj@gmail.com>2020-08-24 12:31:57 -0400
commit1995ca53f38bb89f58a25b523cac59a07c09a0b8 (patch)
treea170df7448d40ba9f1ddf307cb5849ceb5697905 /lua
parentcfddae42f59eacbd792a8853be089f4711bbf4ba (diff)
Add fuzzy git file finderZ
Diffstat (limited to 'lua')
-rw-r--r--lua/telescope/builtin.lua42
-rw-r--r--lua/telescope/init.lua3
-rw-r--r--lua/telescope/pickers.lua30
-rw-r--r--lua/telescope/previewers.lua1
-rw-r--r--lua/telescope/sorters.lua78
-rw-r--r--lua/tests/telescope_spec.lua19
6 files changed, 147 insertions, 26 deletions
diff --git a/lua/telescope/builtin.lua b/lua/telescope/builtin.lua
index 7016b0a..ff5a16d 100644
--- a/lua/telescope/builtin.lua
+++ b/lua/telescope/builtin.lua
@@ -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.
+
+ local telescope = require('telescope')
+
+ local file_finder = telescope.finders.new {
+ static = true,
+
+ fn_command = function() return 'git ls-files' end,
+ }
+
+ local file_previewer = telescope.previewers.vim_buffer
-builtin.rg_vimgrep.finder = Finder:new {
- fn_command = function(prompt)
- return string.format('rg --vimgrep %s', prompt)
- end,
+ local file_picker = telescope.pickers.new {
+ previewer = file_previewer
+ }
- responsive = false
-}
+ -- 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()
-builtin.rg_vimgrep.picker = pickers.new {
-}
+ file_picker:find {
+ prompt = 'Simple File',
+ finder = file_finder,
+ sorter = file_sorter,
+ }
+end
return builtin
diff --git a/lua/telescope/init.lua b/lua/telescope/init.lua
index 75f6d38..22d3f83 100644
--- a/lua/telescope/init.lua
+++ b/lua/telescope/init.lua
@@ -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)
diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua
index f2acfac..d0785ae 100644
--- a/lua/telescope/pickers.lua
+++ b/lua/telescope/pickers.lua
@@ -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 =
diff --git a/lua/telescope/previewers.lua b/lua/telescope/previewers.lua
index ee99d11..91f0060 100644
--- a/lua/telescope/previewers.lua
+++ b/lua/telescope/previewers.lua
@@ -81,7 +81,6 @@ previewers.vim_buffer_or_bat = previewers.new {
end,
}
-
previewers.Previewer = Previewer
return previewers
diff --git a/lua/telescope/sorters.lua b/lua/telescope/sorters.lua
index 0299c91..d09b53b 100644
--- a/lua/telescope/sorters.lua
+++ b/lua/telescope/sorters.lua
@@ -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
diff --git a/lua/tests/telescope_spec.lua b/lua/tests/telescope_spec.lua
index c671579..9960772 100644
--- a/lua/tests/telescope_spec.lua
+++ b/lua/tests/telescope_spec.lua
@@ -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)
+