mirror of
https://github.com/kristoferssolo/telescope-frecency.nvim.git
synced 2025-10-21 20:10:38 +00:00
fix: reflow results to show valid ones (#123)
* fix: clear non-matched results in results buffer * fix: show high-scored results in the first view This is for sorting_strategy = 'descending'
This commit is contained in:
parent
9b17c17744
commit
2ac311a266
@ -3,17 +3,20 @@ local async = require "plenary.async" --[[@as PlenaryAsync]]
|
|||||||
---@class FrecencyAsyncFinder
|
---@class FrecencyAsyncFinder
|
||||||
---@field closed boolean
|
---@field closed boolean
|
||||||
---@field entries FrecencyEntry[]
|
---@field entries FrecencyEntry[]
|
||||||
|
---@field reflowed boolean
|
||||||
---@field rx PlenaryAsyncControlChannelRx
|
---@field rx PlenaryAsyncControlChannelRx
|
||||||
|
---@field state FrecencyState
|
||||||
---@overload fun(_: string, process_result: (fun(entry: FrecencyEntry): nil), process_complete: fun(): nil): nil
|
---@overload fun(_: string, process_result: (fun(entry: FrecencyEntry): nil), process_complete: fun(): nil): nil
|
||||||
local AsyncFinder = {}
|
local AsyncFinder = {}
|
||||||
|
|
||||||
---@param fs FrecencyFS
|
---@param fs FrecencyFS
|
||||||
|
---@param state FrecencyState
|
||||||
---@param path string
|
---@param path string
|
||||||
---@param entry_maker fun(file: FrecencyFile): FrecencyEntry
|
---@param entry_maker fun(file: FrecencyFile): FrecencyEntry
|
||||||
---@param initial_results FrecencyFile[]
|
---@param initial_results FrecencyFile[]
|
||||||
---@return FrecencyAsyncFinder
|
---@return FrecencyAsyncFinder
|
||||||
AsyncFinder.new = function(fs, path, entry_maker, initial_results)
|
AsyncFinder.new = function(state, fs, path, entry_maker, initial_results)
|
||||||
local self = setmetatable({ closed = false, entries = {} }, {
|
local self = setmetatable({ closed = false, entries = {}, reflowed = false, state = state }, {
|
||||||
__index = AsyncFinder,
|
__index = AsyncFinder,
|
||||||
---@param self FrecencyAsyncFinder
|
---@param self FrecencyAsyncFinder
|
||||||
__call = function(self, ...)
|
__call = function(self, ...)
|
||||||
@ -47,6 +50,7 @@ AsyncFinder.new = function(fs, path, entry_maker, initial_results)
|
|||||||
table.insert(self.entries, entry)
|
table.insert(self.entries, entry)
|
||||||
tx.send(entry)
|
tx.send(entry)
|
||||||
if count % 1000 == 0 then
|
if count % 1000 == 0 then
|
||||||
|
self:reflow_results()
|
||||||
-- NOTE: This is needed not to lock text input.
|
-- NOTE: This is needed not to lock text input.
|
||||||
async.util.sleep(50)
|
async.util.sleep(50)
|
||||||
end
|
end
|
||||||
@ -88,4 +92,32 @@ function AsyncFinder:close()
|
|||||||
self.closed = true
|
self.closed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return nil
|
||||||
|
function AsyncFinder:reflow_results()
|
||||||
|
local picker = self.state:get()
|
||||||
|
if not picker then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local bufnr = picker.results_bufnr
|
||||||
|
local win = picker.results_win
|
||||||
|
if not bufnr or not win then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
picker:clear_extra_rows(bufnr)
|
||||||
|
if picker.sorting_strategy == "descending" then
|
||||||
|
local manager = picker.manager
|
||||||
|
if not manager then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local worst_line = picker:get_row(manager:num_results())
|
||||||
|
---@type WinInfo
|
||||||
|
local wininfo = vim.fn.getwininfo(win)[1]
|
||||||
|
local bottom = vim.api.nvim_buf_line_count(bufnr)
|
||||||
|
if not self.reflowed or worst_line > wininfo.botline then
|
||||||
|
self.reflowed = true
|
||||||
|
vim.api.nvim_win_set_cursor(win, { bottom, 0 })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return AsyncFinder
|
return AsyncFinder
|
||||||
|
|||||||
@ -27,11 +27,12 @@ end
|
|||||||
---@field workspace string?
|
---@field workspace string?
|
||||||
---@field workspace_tag string?
|
---@field workspace_tag string?
|
||||||
|
|
||||||
|
---@param state FrecencyState
|
||||||
---@param filepath_formatter FrecencyFilepathFormatter
|
---@param filepath_formatter FrecencyFilepathFormatter
|
||||||
---@param initial_results table
|
---@param initial_results table
|
||||||
---@param opts FrecencyFinderOptions
|
---@param opts FrecencyFinderOptions
|
||||||
---@return table
|
---@return table
|
||||||
function Finder:start(filepath_formatter, initial_results, opts)
|
function Finder:start(state, filepath_formatter, initial_results, opts)
|
||||||
local entry_maker = self.entry_maker:create(filepath_formatter, opts.workspace, opts.workspace_tag)
|
local entry_maker = self.entry_maker:create(filepath_formatter, opts.workspace, opts.workspace_tag)
|
||||||
if not opts.need_scandir then
|
if not opts.need_scandir then
|
||||||
return finders.new_table {
|
return finders.new_table {
|
||||||
@ -40,7 +41,7 @@ function Finder:start(filepath_formatter, initial_results, opts)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
log.debug { finder = opts }
|
log.debug { finder = opts }
|
||||||
return AsyncFinder.new(self.fs, opts.workspace, entry_maker, initial_results)
|
return AsyncFinder.new(state, self.fs, opts.workspace, entry_maker, initial_results)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Finder
|
return Finder
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
local State = require "frecency.state"
|
||||||
local log = require "plenary.log"
|
local log = require "plenary.log"
|
||||||
local Path = require "plenary.path" --[[@as PlenaryPath]]
|
local Path = require "plenary.path" --[[@as PlenaryPath]]
|
||||||
local actions = require "telescope.actions"
|
local actions = require "telescope.actions"
|
||||||
@ -83,8 +84,10 @@ function Picker:start(opts)
|
|||||||
self.results = self:fetch_results(self.workspace)
|
self.results = self:fetch_results(self.workspace)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local state = State.new()
|
||||||
|
|
||||||
local filepath_formatter = self:filepath_formatter(opts)
|
local filepath_formatter = self:filepath_formatter(opts)
|
||||||
local finder = self.finder:start(filepath_formatter, self.results, {
|
local finder = self.finder:start(state, filepath_formatter, self.results, {
|
||||||
need_scandir = self.workspace and self.config.show_unindexed and true or false,
|
need_scandir = self.workspace and self.config.show_unindexed and true or false,
|
||||||
workspace = self.workspace,
|
workspace = self.workspace,
|
||||||
workspace_tag = self.config.initial_workspace_tag,
|
workspace_tag = self.config.initial_workspace_tag,
|
||||||
@ -95,11 +98,12 @@ function Picker:start(opts)
|
|||||||
finder = finder,
|
finder = finder,
|
||||||
previewer = config_values.file_previewer(opts),
|
previewer = config_values.file_previewer(opts),
|
||||||
sorter = sorters.get_substr_matcher(),
|
sorter = sorters.get_substr_matcher(),
|
||||||
on_input_filter_cb = self:on_input_filter_cb(opts),
|
on_input_filter_cb = self:on_input_filter_cb(state, opts),
|
||||||
attach_mappings = function(prompt_bufnr)
|
attach_mappings = function(prompt_bufnr)
|
||||||
return self:attach_mappings(prompt_bufnr)
|
return self:attach_mappings(prompt_bufnr)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
state:set(picker)
|
||||||
picker:find()
|
picker:find()
|
||||||
self:set_prompt_options(picker.prompt_bufnr)
|
self:set_prompt_options(picker.prompt_bufnr)
|
||||||
end
|
end
|
||||||
@ -227,9 +231,10 @@ function Picker:get_lsp_workspace()
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
|
---@param state FrecencyState
|
||||||
---@param picker_opts table
|
---@param picker_opts table
|
||||||
---@return fun(prompt: string): table
|
---@return fun(prompt: string): table
|
||||||
function Picker:on_input_filter_cb(picker_opts)
|
function Picker:on_input_filter_cb(state, picker_opts)
|
||||||
local filepath_formatter = self:filepath_formatter(picker_opts)
|
local filepath_formatter = self:filepath_formatter(picker_opts)
|
||||||
return function(prompt)
|
return function(prompt)
|
||||||
local workspace
|
local workspace
|
||||||
@ -243,7 +248,7 @@ function Picker:on_input_filter_cb(picker_opts)
|
|||||||
if self.workspace ~= workspace then
|
if self.workspace ~= workspace then
|
||||||
self.workspace = workspace
|
self.workspace = workspace
|
||||||
self.results = self:fetch_results(workspace)
|
self.results = self:fetch_results(workspace)
|
||||||
opts.updated_finder = self.finder:start(filepath_formatter, self.results, {
|
opts.updated_finder = self.finder:start(state, filepath_formatter, self.results, {
|
||||||
initial_results = self.results,
|
initial_results = self.results,
|
||||||
need_scandir = self.workspace and self.config.show_unindexed and true or false,
|
need_scandir = self.workspace and self.config.show_unindexed and true or false,
|
||||||
workspace = self.workspace,
|
workspace = self.workspace,
|
||||||
|
|||||||
21
lua/frecency/state.lua
Normal file
21
lua/frecency/state.lua
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---@class FrecencyState
|
||||||
|
---@field picker TelescopePicker?
|
||||||
|
local State = {}
|
||||||
|
|
||||||
|
---@return FrecencyState
|
||||||
|
State.new = function()
|
||||||
|
return setmetatable({}, { __index = State, __meta = "kv" })
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param picker TelescopePicker?
|
||||||
|
---@return nil
|
||||||
|
function State:set(picker)
|
||||||
|
self.picker = picker
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return TelescopePicker?
|
||||||
|
function State:get()
|
||||||
|
return self.picker
|
||||||
|
end
|
||||||
|
|
||||||
|
return State
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---@diagnostic disable: invisible
|
---@diagnostic disable: invisible
|
||||||
local AsyncFinder = require "frecency.async_finder"
|
local AsyncFinder = require "frecency.async_finder"
|
||||||
|
local State = require "frecency.state"
|
||||||
local FS = require "frecency.fs"
|
local FS = require "frecency.fs"
|
||||||
local EntryMaker = require "frecency.entry_maker"
|
local EntryMaker = require "frecency.entry_maker"
|
||||||
local WebDevicons = require "frecency.web_devicons"
|
local WebDevicons = require "frecency.web_devicons"
|
||||||
@ -22,7 +23,7 @@ local function with_files(files, initial_results, callback)
|
|||||||
local initials = vim.tbl_map(function(v)
|
local initials = vim.tbl_map(function(v)
|
||||||
return { path = (dir / v):absolute() }
|
return { path = (dir / v):absolute() }
|
||||||
end, initial_results)
|
end, initial_results)
|
||||||
local async_finder = AsyncFinder.new(fs, dir:absolute(), entry_maker, initials)
|
local async_finder = AsyncFinder.new(State.new(), fs, dir:absolute(), entry_maker, initials)
|
||||||
callback(async_finder, dir)
|
callback(async_finder, dir)
|
||||||
close()
|
close()
|
||||||
end
|
end
|
||||||
|
|||||||
@ -117,3 +117,20 @@ function PlenaryAsyncUtil.sleep(ms) end
|
|||||||
---@field path_tail fun(path: string): string
|
---@field path_tail fun(path: string): string
|
||||||
---@field transform_path fun(opts: table, path: string): string
|
---@field transform_path fun(opts: table, path: string): string
|
||||||
---@field buf_is_loaded fun(filename: string): boolean
|
---@field buf_is_loaded fun(filename: string): boolean
|
||||||
|
|
||||||
|
---@class TelescopePicker
|
||||||
|
---@field clear_extra_rows fun(self: TelescopePicker, results_bufnr: integer): nil
|
||||||
|
---@field get_row fun(self: TelescopePicker, index: integer): integer
|
||||||
|
---@field manager TelescopeEntryManager|false
|
||||||
|
---@field results_bufnr integer?
|
||||||
|
---@field results_win integer?
|
||||||
|
---@field sorting_strategy 'ascending'|'descending'
|
||||||
|
|
||||||
|
---@class TelescopeEntryManager
|
||||||
|
---@field num_results fun(): integer
|
||||||
|
|
||||||
|
-- NOTE: types for default functions
|
||||||
|
|
||||||
|
---@class WinInfo
|
||||||
|
---@field topline integer
|
||||||
|
---@field botline integer
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user