From 9adf5a2cb0f5f3715b1fba354d91d291cac8a0dc Mon Sep 17 00:00:00 2001 From: delphinus Date: Wed, 26 Jul 2023 18:40:28 +0900 Subject: [PATCH] feat: use dynamic finder not to block Neovim In searching workspace --- lua/frecency/finder.lua | 72 ++++++++++++++++++++++++++++++++++++++++ lua/frecency/pickers.lua | 22 ++++++++---- 2 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 lua/frecency/finder.lua diff --git a/lua/frecency/finder.lua b/lua/frecency/finder.lua new file mode 100644 index 00000000..7feb5425 --- /dev/null +++ b/lua/frecency/finder.lua @@ -0,0 +1,72 @@ +local finders = require "telescope.finders" +local log = require "frecency.log" + +---@class FrecencyFinder +---@field config FrecencyFinderConfig +local Finder = {} + +---@class FrecencyFinderConfig +---@field fs FrecencyFS +---@field entry_maker FrecencyEntryMaker +---@field initial_results table[] + +---@param config FrecencyFinderConfig +---@return FrecencyFinder +Finder.new = function(config) + return setmetatable({ config = config }, { __index = Finder }) +end + +---@class FrecencyFinderOptions +---@field need_scandir boolean +---@field workspace string? + +---@param opts FrecencyFinderOptions +---@return table +function Finder:start(opts) + local entry_maker = self.config.entry_maker:create(opts.workspace) + if not opts.need_scandir then + return finders.new_table { + results = self.config.initial_results, + entry_maker = entry_maker, + } + end + log:debug("%s", { finder = opts }) + return finders.new_dynamic { entry_maker = entry_maker, fn = self:create_fn { path = opts.workspace } } +end + +---@class FrecencyFinderCreateFnOptions +---@field path string + +---@param opts FrecencyFinderCreateFnOptions +---@return fun(prompt: string?): table[] +function Finder:create_fn(opts) + local it = self.config.fs:scan_dir(opts.path) + local is_dead = false + local results = vim.deepcopy(self.config.initial_results) + local called = 0 + ---@param prompt string? + ---@return table[] + return function(prompt) + if is_dead then + return results + end + called = called + 1 + log:debug("called: %d", called) + local count = 0 + while true do + local ok, name = pcall(it) + if not ok then + is_dead = true + break + end + table.insert(results, { path = vim.fs.joinpath(opts.path, name), score = 0 }) + count = count + 1 + if count >= 1000 then + break + end + end + return results + end +end + +return Finder diff --git a/lua/frecency/pickers.lua b/lua/frecency/pickers.lua index 1a014f1b..273bec67 100644 --- a/lua/frecency/pickers.lua +++ b/lua/frecency/pickers.lua @@ -1,4 +1,5 @@ local EntryMaker = require "frecency.picker.entry_maker" +local Finder = require "frecency.finder" local log = require "frecency.log" local actions = require "telescope.actions" local config_values = require("telescope.config").values @@ -91,12 +92,16 @@ function Picker:start(opts) self.results = self:fetch_results(self.workspace) end + local finder = Finder.new({ fs = self.config.fs, entry_maker = self.entry_maker, initial_results = self.results }) + :start { need_scandir = self.workspace and self.config.show_unindexed and true or false, workspace = self.workspace } + local picker = pickers.new(opts, { prompt_title = "Frecency", - finder = finders.new_table { + --[[ finder = finders.new_table { results = self.results, entry_maker = self.entry_maker:create(self.workspace), - }, + }, ]] + finder = finder, previewer = config_values.file_previewer(opts), sorter = sorters.get_substr_matcher(), on_input_filter_cb = function(prompt) @@ -203,11 +208,11 @@ function Picker:fetch_results(workspace) file.score = self.recency:calculate(file.count, ages) end - if workspace and self.config.show_unindexed then + --[[ if workspace and self.config.show_unindexed then for name in self.config.fs:scan_dir(workspace) do table.insert(files, { path = vim.fs.joinpath(workspace, name), score = 0 }) end - end + end ]] table.sort(files, function(a, b) return a.score > b.score @@ -235,10 +240,15 @@ function Picker:on_input_filter_cb(prompt, cwd) log:debug("%s", { workspace = workspace, ["self.workspace"] = self.workspace }) if self.workspace ~= workspace then self.workspace = workspace - opts.updated_finder = finders.new_table { + --[[ opts.updated_finder = finders.new_table { results = self:fetch_results(workspace), entry_maker = self.entry_maker:create(workspace), - } + } ]] + opts.updated_finder = + Finder.new({ fs = self.config.fs, entry_maker = self.entry_maker, initial_results = self.results }):start { + need_scandir = self.workspace and self.config.show_unindexed and true or false, + workspace = self.workspace, + } end return opts end