From 59497d664086c4c7aa24a15a1c3b9ccf718ce9c7 Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Thu, 8 Oct 2020 22:31:44 -0400 Subject: [PATCH] feat: Do a bit better sorting for command history To be honest, I'm not 100% sure this is fantastic, but it's definitely a step in the right direction for command history. Closes: #150 --- lua/telescope/builtin.lua | 10 ++----- lua/telescope/entry_manager.lua | 2 +- lua/telescope/finders.lua | 9 ++++-- lua/telescope/pickers.lua | 8 +++-- lua/telescope/pickers/layout_strategies.lua | 33 ++++++++++++--------- lua/telescope/sorters.lua | 26 +++++++++++++++- 6 files changed, 59 insertions(+), 29 deletions(-) diff --git a/lua/telescope/builtin.lua b/lua/telescope/builtin.lua index 6b51036..c483a7b 100644 --- a/lua/telescope/builtin.lua +++ b/lua/telescope/builtin.lua @@ -79,7 +79,6 @@ builtin.commands = function() entry_maker = function(line) return { valid = line ~= "", - entry_type = make_entry.types.GENERIC, value = line, ordinal = line.name, display = line.name @@ -233,7 +232,6 @@ builtin.lsp_code_actions = function(opts) entry_maker = function(line) return { valid = line ~= nil, - entry_type = make_entry.types.GENERIC, value = line, ordinal = line.idx .. line.title, display = line.idx .. ': ' .. line.title @@ -382,7 +380,7 @@ builtin.command_history = function(opts) local history_list = vim.split(history_string, "\n") local results = {} - for i = 3, #history_list do + for i = #history_list, 3, -1 do local item = history_list[i] local _, finish = string.find(item, "%d+ +") table.insert(results, string.sub(item, finish + 1)) @@ -391,7 +389,7 @@ builtin.command_history = function(opts) pickers.new(opts, { prompt = 'Command History', finder = finders.new_table(results), - sorter = sorters.get_generic_fuzzy_sorter(), + sorter = sorters.fuzzy_with_index_bias(), attach_mappings = function(_, map) map('i', '', actions.set_command_line) @@ -399,12 +397,8 @@ builtin.command_history = function(opts) -- TODO: Find a way to insert the text... it seems hard. -- map('i', '', actions.insert_value, { expr = true }) - -- Please add the default mappings for me for the rest of the keys. return true end, - - -- TODO: Adapt `help` to this. - -- previewer = previewers.cat, }):find() end diff --git a/lua/telescope/entry_manager.lua b/lua/telescope/entry_manager.lua index 532cca2..d53586e 100644 --- a/lua/telescope/entry_manager.lua +++ b/lua/telescope/entry_manager.lua @@ -113,7 +113,7 @@ function EntryManager:insert(picker, index, entry) self.info.inserted = self.info.inserted + 1 next_entry = self.entry_state[index] - self.set_entry(picker, index, entry.entry) + self.set_entry(picker, index, entry.entry, entry.score) self.entry_state[index] = entry last_score = entry.score diff --git a/lua/telescope/finders.lua b/lua/telescope/finders.lua index a9222e7..a3ca097 100644 --- a/lua/telescope/finders.lua +++ b/lua/telescope/finders.lua @@ -33,7 +33,7 @@ local JobFinder = _callable_obj() function JobFinder:new(opts) opts = opts or {} - assert(not opts.results, "`results` should be used with finder.new_table") +> assert(not opts.results, "`results` should be used with finder.new_table") assert(not opts.static, "`static` should be used with finder.new_oneshot_job") local obj = setmetatable({ @@ -238,8 +238,11 @@ function StaticFinder:new(opts) assert(type(input_results) == 'table', "self.results must be a table") local results = {} - for _, v in ipairs(input_results) do - table.insert(results, entry_maker(v)) + for k, v in ipairs(input_results) do + local entry = entry_maker(v) + entry.index = k + + table.insert(results, entry) end return setmetatable({ results = results }, self) diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index f28ae6a..3dc0caa 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -741,7 +741,7 @@ function Picker:set_selection(row) end -function Picker:entry_adder(index, entry) +function Picker:entry_adder(index, entry, score) local row = self:get_row(index) -- If it's less than 0, then we don't need to show it at all. @@ -764,7 +764,11 @@ function Picker:entry_adder(index, entry) -- This is the two spaces to manage the '> ' stuff. -- Maybe someday we can use extmarks or floaty text or something to draw this and not insert here. -- until then, insert two spaces - display = ' ' .. display + if TELESCOPE_DEBUG then + display = ' ' .. score .. display + else + display = ' ' .. display + end self:_increment("displayed") diff --git a/lua/telescope/pickers/layout_strategies.lua b/lua/telescope/pickers/layout_strategies.lua index b43466c..390c748 100644 --- a/lua/telescope/pickers/layout_strategies.lua +++ b/lua/telescope/pickers/layout_strategies.lua @@ -75,17 +75,22 @@ layout_strategies.horizontal = function(self, max_columns, max_lines) end)(self, max_columns, max_lines) local picker_height = max_lines - 2 * height_padding - preview.width = resolve.resolve_width(layout_config.preview_width or function(_, cols) - if not self.previewer or cols < self.preview_cutoff then - return 0 - elseif cols < 150 then - return math.floor(cols * 0.4) - elseif cols < 200 then - return 80 - else - return 120 - end - end)(self, picker_width, max_lines) + if self.previewer then + preview.width = resolve.resolve_width(layout_config.preview_width or function(_, cols) + if not self.previewer or cols < self.preview_cutoff then + return 0 + elseif cols < 150 then + return math.floor(cols * 0.4) + elseif cols < 200 then + return 80 + else + return 120 + end + end)(self, picker_width, max_lines) + else + preview.width = 0 + end + results.width = picker_width - preview.width prompt.width = picker_width - preview.width @@ -114,7 +119,7 @@ layout_strategies.horizontal = function(self, max_columns, max_lines) end return { - preview = preview.width > 0 and preview, + preview = self.previewer and preview.width > 0 and preview, results = results, prompt = prompt } @@ -174,7 +179,7 @@ layout_strategies.center = function(self, columns, lines) preview.col = results.col return { - preview = self.previewer and preview, + preview = self.previewer and preview.width > 0 and preview, results = results, prompt = prompt } @@ -246,7 +251,7 @@ layout_strategies.vertical = function(self, max_columns, max_lines) end return { - preview = preview.width > 0 and preview, + preview = self.previewer and preview.width > 0 and preview, results = results, prompt = prompt } diff --git a/lua/telescope/sorters.lua b/lua/telescope/sorters.lua index 3f9844d..4088ce0 100644 --- a/lua/telescope/sorters.lua +++ b/lua/telescope/sorters.lua @@ -198,7 +198,7 @@ end sorters.get_generic_fuzzy_sorter = function(opts) opts = opts or {} - local ngram_len = 2 + local ngram_len = opts.ngram_len or 2 local function overlapping_ngrams(s, n) if TelescopeCachedNgrams[s] and TelescopeCachedNgrams[s][n] then @@ -283,6 +283,30 @@ sorters.get_generic_fuzzy_sorter = function(opts) } end +sorters.fuzzy_with_index_bias = function(opts) + opts = opts or {} + opts.ngram_len = 2 + + -- TODO: Probably could use a better sorter here. + local fuzzy_sorter = sorters.get_generic_fuzzy_sorter(opts) + + return Sorter:new { + scoring_function = function(_, prompt, _, entry) + local base_score = fuzzy_sorter:score(prompt, entry) + + if base_score == -1 then + return -1 + end + + if base_score == 0 then + return entry.index + else + return math.min(math.pow(entry.index, 0.25), 2) * base_score + end + end + } +end + -- Bad & Dumb Sorter sorters.get_levenshtein_sorter = function() return Sorter:new {