diff --git a/lua/frecency/picker/entry_maker.lua b/lua/frecency/entry_maker.lua similarity index 90% rename from lua/frecency/picker/entry_maker.lua rename to lua/frecency/entry_maker.lua index 3270b879..3ee9e013 100644 --- a/lua/frecency/picker/entry_maker.lua +++ b/lua/frecency/entry_maker.lua @@ -5,24 +5,25 @@ local utils = require "telescope.utils" --[[@as TelescopeUtils]] ---@class FrecencyEntryMaker ---@field config FrecencyEntryMakerConfig +---@field fs FrecencyFS ---@field loaded table local EntryMaker = {} ---@class FrecencyEntryMakerConfig ----@field show_scores boolean ---@field show_filter_column boolean|string[] ----@field os_home string +---@field show_scores boolean +---@param fs FrecencyFS ---@param config FrecencyEntryMakerConfig ---@return FrecencyEntryMaker -EntryMaker.new = function(config) - local self = setmetatable({ config = config }, { __index = EntryMaker }) +EntryMaker.new = function(fs, config) + local self = setmetatable({ config = config, fs = fs }, { __index = EntryMaker }) local loaded_bufnrs = vim.tbl_filter(function(v) return vim.api.nvim_buf_is_loaded(v) end, vim.api.nvim_list_bufs()) self.loaded = {} for _, bufnr in ipairs(loaded_bufnrs) do - self.loaded[vim.fn.bufname(bufnr)] = true + self.loaded[vim.api.nvim_buf_get_name(bufnr)] = true end return self end @@ -94,7 +95,7 @@ function EntryMaker:items(entry, workspace, formatter) end if self.config.show_filter_column and workspace then local filtered = self:should_show_tail(workspace) and utils.path_tail(workspace) .. Path.path.sep - or Path:new(workspace):make_relative(self.config.os_home) .. Path.path.sep + or self.fs:relative_from_home(workspace) .. Path.path.sep table.insert(items, { filtered, "Directory" }) end table.insert(items, { formatter(entry.name), self.loaded[entry.name] and "TelescopeBufferLoaded" or "" }) @@ -106,7 +107,7 @@ end ---@return integer function EntryMaker:calculate_filter_column_width(workspace) return self:should_show_tail(workspace) and #(utils.path_tail(workspace)) + 1 - or #(Path:new(workspace):make_relative(self.config.os_home)) + 1 + or #(self.fs:relative_from_home(workspace)) + 1 end ---@private @@ -127,7 +128,7 @@ function EntryMaker:filepath_formatter(opts, workspace) for k, v in pairs(opts) do path_opts[k] = v end - path_opts.cwd = workspace or self.config.os_home + path_opts.cwd = workspace or self.fs.os_homedir return function(filename) return utils.transform_path(path_opts, filename) diff --git a/lua/frecency/finder.lua b/lua/frecency/finder.lua index 38f8b8c5..63a810e4 100644 --- a/lua/frecency/finder.lua +++ b/lua/frecency/finder.lua @@ -2,47 +2,43 @@ local finders = require "telescope.finders" local log = require "frecency.log" ---@class FrecencyFinder ----@field config FrecencyFinderConfig +---@field private entry_maker FrecencyEntryMaker +---@field private fs FrecencyFS local Finder = {} ----@class FrecencyFinderConfig ----@field fs FrecencyFS ----@field entry_maker FrecencyEntryMaker ----@field initial_results table[] - ----@param config FrecencyFinderConfig +---@param entry_maker FrecencyEntryMaker +---@param fs FrecencyFS ---@return FrecencyFinder -Finder.new = function(config) - return setmetatable({ config = config }, { __index = Finder }) +Finder.new = function(entry_maker, fs) + return setmetatable({ entry_maker = entry_maker, fs = fs }, { __index = Finder }) end ---@class FrecencyFinderOptions ---@field need_scandir boolean ---@field workspace string? +---@param initial_results table ---@param opts FrecencyFinderOptions ---@return table -function Finder:start(opts) - local entry_maker = self.config.entry_maker:create(opts.workspace) +function Finder:start(initial_results, opts) + local entry_maker = self.entry_maker:create(opts.workspace) if not opts.need_scandir then return finders.new_table { - results = self.config.initial_results, + results = initial_results, entry_maker = entry_maker, } end log:debug { finder = opts } - return finders.new_dynamic { entry_maker = entry_maker, fn = self:create_fn { path = opts.workspace } } + return finders.new_dynamic { entry_maker = entry_maker, fn = self:create_fn(initial_results, opts.workspace) } end ----@class FrecencyFinderCreateFnOptions ----@field path string - ----@param opts FrecencyFinderCreateFnOptions +---@param initial_results table +---@param path string ---@return fun(prompt: string?): table[] -function Finder:create_fn(opts) - local it = self.config.fs:scan_dir(opts.path) +function Finder:create_fn(initial_results, path) + local it = self.fs:scan_dir(path) local is_dead = false - local results = vim.deepcopy(self.config.initial_results) + local results = vim.deepcopy(initial_results) local called = 0 ---@param prompt string? ---@return table[] @@ -59,7 +55,7 @@ function Finder:create_fn(opts) is_dead = true break end - table.insert(results, { path = vim.fs.joinpath(opts.path, name), score = 0 }) + table.insert(results, { path = vim.fs.joinpath(path, name), score = 0 }) count = count + 1 if count >= 1000 then break diff --git a/lua/frecency/frecency.lua b/lua/frecency/frecency.lua index 33158c9f..1196162f 100644 --- a/lua/frecency/frecency.lua +++ b/lua/frecency/frecency.lua @@ -1,5 +1,7 @@ local Database = require "frecency.database" +local EntryMaker = require "frecency.entry_maker" local FS = require "frecency.fs" +local Finder = require "frecency.finder" local Picker = require "frecency.picker" local Recency = require "frecency.recency" local log = require "frecency.log" @@ -7,10 +9,10 @@ local log = require "frecency.log" ---@class Frecency ---@field config FrecencyConfig ---@field picker FrecencyPicker +---@field private buf_registered table flag to indicate the buffer is registered to the database. ---@field private database FrecencyDatabase ---@field private fs FrecencyFS ---@field private recency FrecencyRecency ----@field private buf_registered table flag to indicate the buffer is registered to the database. local Frecency = {} ---@class FrecencyConfig @@ -29,37 +31,38 @@ local Frecency = {} ---@param opts FrecencyConfig? ---@return Frecency Frecency.new = function(opts) - local self = setmetatable({ - config = vim.tbl_extend("force", { - auto_validate = true, - db_root = vim.fn.stdpath "data", - db_safe_mode = true, - default_workspace = nil, - disable_devicons = false, - filter_delimiter = ":", - ignore_patterns = { "*.git/*", "*/tmp/*", "term://*" }, - show_filter_column = true, - show_scores = false, - show_unindexed = true, - workspaces = {}, - }, opts or {}), - buf_registered = {}, - }, { __index = Frecency })--[[@as Frecency]] + ---@type FrecencyConfig + local config = vim.tbl_extend("force", { + auto_validate = true, + db_root = vim.fn.stdpath "data", + db_safe_mode = true, + default_workspace = nil, + disable_devicons = false, + filter_delimiter = ":", + ignore_patterns = { "*.git/*", "*/tmp/*", "term://*" }, + show_filter_column = true, + show_scores = false, + show_unindexed = true, + workspaces = {}, + }, opts or {}) + local self = setmetatable({ buf_registered = {} }, { __index = Frecency })--[[@as Frecency]] self.database = Database.new { - auto_validate = self.config.auto_validate, - root = self.config.db_root, - safe_mode = self.config.db_safe_mode, + auto_validate = config.auto_validate, + root = config.db_root, + safe_mode = config.db_safe_mode, } - self.fs = FS.new { ignore_patterns = self.config.ignore_patterns } + self.fs = FS.new { ignore_patterns = config.ignore_patterns } + local entry_maker = EntryMaker.new(self.fs, { + show_filter_column = config.show_filter_column, + show_scores = config.show_scores, + }) + local finder = Finder.new(entry_maker, self.fs) self.recency = Recency.new() - self.picker = Picker.new(self.database, self.recency, { - default_workspace = self.config.default_workspace, - filter_delimiter = self.config.filter_delimiter, - fs = self.fs, - show_filter_column = self.config.show_filter_column, - show_scores = self.config.show_scores, - show_unindexed = self.config.show_unindexed, - workspaces = self.config.workspaces, + self.picker = Picker.new(self.database, finder, self.fs, self.recency, { + default_workspace = config.default_workspace, + filter_delimiter = config.filter_delimiter, + show_unindexed = config.show_unindexed, + workspaces = config.workspaces, }) return self end diff --git a/lua/frecency/fs.lua b/lua/frecency/fs.lua index 0cae85c5..5832be53 100644 --- a/lua/frecency/fs.lua +++ b/lua/frecency/fs.lua @@ -1,8 +1,10 @@ local Path = require "plenary.path" --[[@as PlenaryPath]] local scandir = require "plenary.scandir" local log = require "frecency.log" +local uv = vim.uv or vim.loop ---@class FrecencyFS +---@field os_homedir string ---@field private ignore_regexes string[] local FS = {} @@ -12,7 +14,7 @@ local FS = {} ---@param config FrecencyFSConfig ---@return FrecencyFS FS.new = function(config) - local self = setmetatable({ config = config }, { __index = FS }) + local self = setmetatable({ config = config, os_homedir = assert(uv.os_homedir()) }, { __index = FS }) ---@param pattern string self.ignore_regexes = vim.tbl_map(function(pattern) local escaped = pattern:gsub("[%-%.%+%[%]%(%)%$%^%%%?%*]", "%%%1") @@ -51,6 +53,12 @@ function FS:scan_dir(path) end) end +---@param path string +---@return string +function FS:relative_from_home(path) + return Path:new(path):make_relative(self.os_homedir) +end + ---@private ---@param path string ---@return boolean diff --git a/lua/frecency/picker.lua b/lua/frecency/picker.lua index cf82754c..69676a65 100644 --- a/lua/frecency/picker.lua +++ b/lua/frecency/picker.lua @@ -1,9 +1,6 @@ -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 -local finders = require "telescope.finders" local pickers = require "telescope.pickers" local sorters = require "telescope.sorters" local uv = vim.loop or vim.uv @@ -14,9 +11,6 @@ local Path = require "plenary.path" ---@class FrecencyPickerConfig ---@field default_workspace string ---@field filter_delimiter string ----@field fs FrecencyFS ----@field show_filter_column boolean|string[] ----@field show_scores boolean ---@field show_unindexed boolean ---@field workspaces table @@ -43,9 +37,9 @@ local Path = require "plenary.path" ---@field private config FrecencyPickerConfig ---@field private database FrecencyDatabase ---@field private editing_bufnr integer ----@field private entry_maker FrecencyEntryMaker +---@field private finder FrecencyFinder +---@field private fs FrecencyFS ---@field private lsp_workspaces string[] ----@field private os_home string ---@field private recency FrecencyRecency ---@field private results table[] ---@field private workspace string? @@ -53,24 +47,22 @@ local Path = require "plenary.path" local Picker = {} ---@param database FrecencyDatabase +---@param finder FrecencyFinder +---@param fs FrecencyFS ---@param recency FrecencyRecency ---@param config FrecencyPickerConfig ---@return FrecencyPicker -Picker.new = function(database, recency, config) +Picker.new = function(database, finder, fs, recency, config) local self = setmetatable({ config = config, database = database, editing_bufnr = 0, + finder = finder, + fs = fs, lsp_workspaces = {}, - os_home = uv.os_homedir(), recency = recency, results = {}, }, { __index = Picker }) - self.entry_maker = EntryMaker.new { - os_home = self.os_home, - show_filter_column = self.config.show_filter_column, - show_scores = self.config.show_scores, - } local d = self.config.filter_delimiter or ":" self.workspace_tag_regex = "^%s*(" .. d .. "(%S+)" .. d .. ")" return self @@ -92,15 +84,13 @@ 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 finder = self.finder:start(self.results, { + 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 { - results = self.results, - entry_maker = self.entry_maker:create(self.workspace), - }, ]] finder = finder, previewer = config_values.file_previewer(opts), sorter = sorters.get_substr_matcher(), @@ -161,8 +151,8 @@ end function Picker:default_path_display(opts, path) local filename = Path:new(path):make_relative(opts.cwd) if not self.workspace then - if vim.startswith(filename, self.os_home) then - filename = "~/" .. Path:new(filename):make_relative(self.os_home) + if vim.startswith(filename, self.fs.os_homedir) then + filename = "~/" .. self.fs:relative_from_home(filename) elseif filename ~= path then filename = "./" .. filename end @@ -234,11 +224,11 @@ function Picker:on_input_filter_cb(prompt, cwd) log:debug { workspace = workspace, ["self.workspace"] = self.workspace } if self.workspace ~= workspace then self.workspace = 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, - } + opts.updated_finder = self.finder:start(self.results, { + initial_results = self.results, + need_scandir = self.workspace and self.config.show_unindexed and true or false, + workspace = self.workspace, + }) end return opts end