mirror of
https://github.com/kristoferssolo/telescope-frecency.nvim.git
synced 2025-10-21 20:10:38 +00:00
feat: make query() faster and more lazier (#241)
* refactor: simplify logic to load web_devicons * refactor: make register() asynchronous * fix: load lazily modules outside this plugin * refactor: simplify logic to wait initialization * refactor: use uv.hrtime() instead of os.clock() * fix: avoid errors in calling plenary.log in async * test: store elapsed time to check in tests * test: fix module names This becomes a problem only in Ubuntu because macOS and Windows does not care cases in filenames. * test: fix types and unused modules * style: fix by stylua * refactor: make recency / entry_maker loaded lazily
This commit is contained in:
parent
673585ee99
commit
c140e6ff9c
@ -1,11 +1,13 @@
|
|||||||
local Table = require "frecency.database.table"
|
local Table = require "frecency.database.table"
|
||||||
local FileLock = require "frecency.file_lock"
|
local FileLock = require "frecency.file_lock"
|
||||||
|
local Timer = require "frecency.timer"
|
||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
local fs = require "frecency.fs"
|
local fs = require "frecency.fs"
|
||||||
local watcher = require "frecency.watcher"
|
local watcher = require "frecency.watcher"
|
||||||
local log = require "frecency.log"
|
local log = require "frecency.log"
|
||||||
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
local lazy_require = require "frecency.lazy_require"
|
||||||
local Path = require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
local async = lazy_require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
|
local Path = lazy_require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
||||||
|
|
||||||
---@class FrecencyDatabaseEntry
|
---@class FrecencyDatabaseEntry
|
||||||
---@field ages number[]
|
---@field ages number[]
|
||||||
@ -184,7 +186,7 @@ end
|
|||||||
---@async
|
---@async
|
||||||
---@return nil
|
---@return nil
|
||||||
function Database:load()
|
function Database:load()
|
||||||
local start = os.clock()
|
local timer = Timer.new "load()"
|
||||||
local err, data = self:file_lock():with(function(target)
|
local err, data = self:file_lock():with(function(target)
|
||||||
local err, stat = async.uv.fs_stat(target)
|
local err, stat = async.uv.fs_stat(target)
|
||||||
if err then
|
if err then
|
||||||
@ -203,13 +205,13 @@ function Database:load()
|
|||||||
assert(not err, err)
|
assert(not err, err)
|
||||||
local tbl = vim.F.npcall(loadstring(data or ""))
|
local tbl = vim.F.npcall(loadstring(data or ""))
|
||||||
self.tbl:set(tbl)
|
self.tbl:set(tbl)
|
||||||
log.debug(("load() takes %f seconds"):format(os.clock() - start))
|
timer:finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@async
|
---@async
|
||||||
---@return nil
|
---@return nil
|
||||||
function Database:save()
|
function Database:save()
|
||||||
local start = os.clock()
|
local timer = Timer.new "save()"
|
||||||
local err = self:file_lock():with(function(target)
|
local err = self:file_lock():with(function(target)
|
||||||
self:raw_save(self.tbl:raw(), target)
|
self:raw_save(self.tbl:raw(), target)
|
||||||
local err, stat = async.uv.fs_stat(target)
|
local err, stat = async.uv.fs_stat(target)
|
||||||
@ -218,7 +220,7 @@ function Database:save()
|
|||||||
return nil
|
return nil
|
||||||
end)
|
end)
|
||||||
assert(not err, err)
|
assert(not err, err)
|
||||||
log.debug(("save() takes %f seconds"):format(os.clock() - start))
|
timer:finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@async
|
---@async
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
local log = require "frecency.log"
|
local Timer = require "frecency.timer"
|
||||||
local async = require "plenary.async"
|
local lazy_require = require "frecency.lazy_require"
|
||||||
|
local async = lazy_require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
|
|
||||||
---@class FrecencyDatabaseRecordValue
|
---@class FrecencyDatabaseRecordValue
|
||||||
---@field count integer
|
---@field count integer
|
||||||
@ -47,13 +48,13 @@ end
|
|||||||
---@async
|
---@async
|
||||||
---@return nil
|
---@return nil
|
||||||
function Table:wait_ready()
|
function Table:wait_ready()
|
||||||
local start = os.clock()
|
local timer = Timer.new "wait_ready()"
|
||||||
local t = 0.2
|
local t = 0.2
|
||||||
while not rawget(self, "is_ready") do
|
while not rawget(self, "is_ready") do
|
||||||
async.util.sleep(t)
|
async.util.sleep(t)
|
||||||
t = t * 2
|
t = t * 2
|
||||||
end
|
end
|
||||||
log.debug(("wait_ready() takes %f seconds"):format(os.clock() - start))
|
timer:finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
return Table
|
return Table
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
local WebDevicons = require "frecency.web_devicons"
|
local web_devicons = require "frecency.web_devicons"
|
||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
local fs = require "frecency.fs"
|
local fs = require "frecency.fs"
|
||||||
local Path = require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
local Path = require "plenary.path"
|
||||||
local entry_display = require "telescope.pickers.entry_display" --[[@as FrecencyTelescopeEntryDisplay]]
|
local lazy_require = require "frecency.lazy_require"
|
||||||
local utils = require "telescope.utils" --[[@as FrecencyTelescopeUtils]]
|
local entry_display = lazy_require "telescope.pickers.entry_display" --[[@as FrecencyTelescopeEntryDisplay]]
|
||||||
|
local utils = lazy_require "telescope.utils" --[[@as FrecencyTelescopeUtils]]
|
||||||
|
|
||||||
---@class FrecencyEntryMaker
|
---@class FrecencyEntryMaker
|
||||||
---@field loaded table<string,boolean>
|
---@field loaded table<string,boolean>
|
||||||
---@field web_devicons WebDevicons
|
|
||||||
local EntryMaker = {}
|
local EntryMaker = {}
|
||||||
|
|
||||||
---@return FrecencyEntryMaker
|
---@return FrecencyEntryMaker
|
||||||
EntryMaker.new = function()
|
EntryMaker.new = function()
|
||||||
return setmetatable({ web_devicons = WebDevicons.new() }, { __index = EntryMaker })
|
return setmetatable({}, { __index = EntryMaker })
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class FrecencyEntry
|
---@class FrecencyEntry
|
||||||
@ -86,7 +86,7 @@ function EntryMaker:width_items(workspace, workspace_tag)
|
|||||||
table.insert(width_items, { width = 6 }) -- fuzzy score
|
table.insert(width_items, { width = 6 }) -- fuzzy score
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.web_devicons.is_enabled then
|
if not config.disable_devicons then
|
||||||
table.insert(width_items, { width = 2 })
|
table.insert(width_items, { width = 2 })
|
||||||
end
|
end
|
||||||
if config.show_filter_column and workspace and workspace_tag then
|
if config.show_filter_column and workspace and workspace_tag then
|
||||||
@ -116,12 +116,11 @@ function EntryMaker:items(entry, workspace, workspace_tag, formatter)
|
|||||||
table.insert(items, { score, "TelescopeFrecencyScores" })
|
table.insert(items, { score, "TelescopeFrecencyScores" })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.web_devicons.is_enabled then
|
if not config.disable_devicons then
|
||||||
local basename = utils.path_tail(entry.name)
|
local basename = utils.path_tail(entry.name)
|
||||||
local icon, icon_highlight =
|
local icon, icon_highlight = web_devicons.get_icon(basename, utils.file_extension(basename), { default = false })
|
||||||
self.web_devicons:get_icon(basename, utils.file_extension(basename), { default = false })
|
|
||||||
if not icon then
|
if not icon then
|
||||||
icon, icon_highlight = self.web_devicons:get_icon(basename, nil, { default = true })
|
icon, icon_highlight = web_devicons.get_icon(basename, nil, { default = true })
|
||||||
end
|
end
|
||||||
table.insert(items, { icon, icon_highlight })
|
table.insert(items, { icon, icon_highlight })
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
local log = require "frecency.log"
|
local log = require "frecency.log"
|
||||||
local Path = require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
local lazy_require = require "frecency.lazy_require"
|
||||||
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
local Path = lazy_require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
||||||
|
local async = lazy_require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
|
|
||||||
---@class FrecencyFileLock
|
---@class FrecencyFileLock
|
||||||
---@field base string
|
---@field base string
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
|
local Timer = require "frecency.timer"
|
||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
local fs = require "frecency.fs"
|
local fs = require "frecency.fs"
|
||||||
local os_util = require "frecency.os_util"
|
local os_util = require "frecency.os_util"
|
||||||
|
local recency = require "frecency.recency"
|
||||||
local log = require "frecency.log"
|
local log = require "frecency.log"
|
||||||
local Job = require "plenary.job"
|
local lazy_require = require "frecency.lazy_require"
|
||||||
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
local Job = lazy_require "plenary.job" --[[@as FrecencyPlenaryJob]]
|
||||||
|
local async = lazy_require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
|
|
||||||
---@class FrecencyFinder
|
---@class FrecencyFinder
|
||||||
---@field config FrecencyFinderConfig
|
---@field config FrecencyFinderConfig
|
||||||
@ -21,7 +24,6 @@ local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
|||||||
---@field private need_scan_dir boolean
|
---@field private need_scan_dir boolean
|
||||||
---@field private seen table<string, boolean>
|
---@field private seen table<string, boolean>
|
||||||
---@field private process VimSystemObj?
|
---@field private process VimSystemObj?
|
||||||
---@field private recency FrecencyRecency
|
|
||||||
---@field private state FrecencyState
|
---@field private state FrecencyState
|
||||||
local Finder = {}
|
local Finder = {}
|
||||||
|
|
||||||
@ -34,11 +36,10 @@ local Finder = {}
|
|||||||
---@param entry_maker FrecencyEntryMakerInstance
|
---@param entry_maker FrecencyEntryMakerInstance
|
||||||
---@param need_scandir boolean
|
---@param need_scandir boolean
|
||||||
---@param path string?
|
---@param path string?
|
||||||
---@param recency FrecencyRecency
|
|
||||||
---@param state FrecencyState
|
---@param state FrecencyState
|
||||||
---@param finder_config? FrecencyFinderConfig
|
---@param finder_config? FrecencyFinderConfig
|
||||||
---@return FrecencyFinder
|
---@return FrecencyFinder
|
||||||
Finder.new = function(database, entry_maker, need_scandir, path, recency, state, finder_config)
|
Finder.new = function(database, entry_maker, need_scandir, path, state, finder_config)
|
||||||
local tx, rx = async.control.channel.mpsc()
|
local tx, rx = async.control.channel.mpsc()
|
||||||
local scan_tx, scan_rx = async.control.channel.mpsc()
|
local scan_tx, scan_rx = async.control.channel.mpsc()
|
||||||
local self = setmetatable({
|
local self = setmetatable({
|
||||||
@ -47,7 +48,6 @@ Finder.new = function(database, entry_maker, need_scandir, path, recency, state,
|
|||||||
database = database,
|
database = database,
|
||||||
entry_maker = entry_maker,
|
entry_maker = entry_maker,
|
||||||
path = path,
|
path = path,
|
||||||
recency = recency,
|
|
||||||
state = state,
|
state = state,
|
||||||
|
|
||||||
seen = {},
|
seen = {},
|
||||||
@ -257,25 +257,21 @@ end
|
|||||||
---@return FrecencyFile[]
|
---@return FrecencyFile[]
|
||||||
function Finder:get_results(workspace, epoch)
|
function Finder:get_results(workspace, epoch)
|
||||||
log.debug { workspace = workspace or "NONE" }
|
log.debug { workspace = workspace or "NONE" }
|
||||||
local start_fetch = os.clock()
|
local timer_fetch = Timer.new "fetching entries"
|
||||||
local files = self.database:get_entries(workspace, epoch)
|
local files = self.database:get_entries(workspace, epoch)
|
||||||
log.debug(("it takes %f seconds in fetching entries"):format(os.clock() - start_fetch))
|
timer_fetch:finish()
|
||||||
local start_results = os.clock()
|
local timer_results = Timer.new "making results"
|
||||||
local elapsed_recency = 0
|
|
||||||
for _, file in ipairs(files) do
|
for _, file in ipairs(files) do
|
||||||
local start_recency = os.clock()
|
file.score = file.ages and recency.calculate(file.count, file.ages) or 0
|
||||||
file.score = file.ages and self.recency:calculate(file.count, file.ages) or 0
|
|
||||||
file.ages = nil
|
file.ages = nil
|
||||||
elapsed_recency = elapsed_recency + (os.clock() - start_recency)
|
|
||||||
end
|
end
|
||||||
log.debug(("it takes %f seconds in calculating recency"):format(elapsed_recency))
|
timer_results:finish()
|
||||||
log.debug(("it takes %f seconds in making results"):format(os.clock() - start_results))
|
|
||||||
|
|
||||||
local start_sort = os.clock()
|
local timer_sort = Timer.new "sorting"
|
||||||
table.sort(files, function(a, b)
|
table.sort(files, function(a, b)
|
||||||
return a.score > b.score or (a.score == b.score and a.path > b.path)
|
return a.score > b.score or (a.score == b.score and a.path > b.path)
|
||||||
end)
|
end)
|
||||||
log.debug(("it takes %f seconds in sorting"):format(os.clock() - start_sort))
|
timer_sort:finish()
|
||||||
return files
|
return files
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
local os_util = require "frecency.os_util"
|
local os_util = require "frecency.os_util"
|
||||||
local log = require "frecency.log"
|
local log = require "frecency.log"
|
||||||
local Path = require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
local lazy_require = require "frecency.lazy_require"
|
||||||
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
local Path = lazy_require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
||||||
local scandir = require "plenary.scandir"
|
local async = lazy_require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
|
local scandir = lazy_require "plenary.scandir"
|
||||||
local uv = vim.uv or vim.loop
|
local uv = vim.uv or vim.loop
|
||||||
|
|
||||||
|
---@class FrecencyFS
|
||||||
local M = {
|
local M = {
|
||||||
os_homedir = assert(uv.os_homedir()),
|
os_homedir = assert(uv.os_homedir()),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
local sorters = require "telescope.sorters"
|
local lazy_require = require "frecency.lazy_require"
|
||||||
|
local sorters = lazy_require "telescope.sorters"
|
||||||
|
|
||||||
---@param opts any options for get_fzy_sorter()
|
---@param opts any options for get_fzy_sorter()
|
||||||
return function(opts)
|
return function(opts)
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
---@field complete fun(findstart: 1|0, base: string): integer|''|string[]
|
---@field complete fun(findstart: 1|0, base: string): integer|''|string[]
|
||||||
---@field delete async fun(path: string): nil
|
---@field delete async fun(path: string): nil
|
||||||
---@field query fun(opts?: FrecencyQueryOpts): FrecencyQueryEntry[]|string[]
|
---@field query fun(opts?: FrecencyQueryOpts): FrecencyQueryEntry[]|string[]
|
||||||
---@field register fun(bufnr: integer, datetime: string?): nil
|
---@field register async fun(bufnr: integer, datetime: string?): nil
|
||||||
---@field start fun(opts: FrecencyPickerOptions?): nil
|
---@field start fun(opts: FrecencyPickerOptions?): nil
|
||||||
---@field validate_database async fun(force: boolean?): nil
|
---@field validate_database async fun(force: boolean?): nil
|
||||||
local frecency = setmetatable({}, {
|
local frecency = setmetatable({}, {
|
||||||
@ -43,7 +43,9 @@ local function setup(ext_config)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
require("frecency.config").setup(ext_config)
|
local config = require "frecency.config"
|
||||||
|
|
||||||
|
config.setup(ext_config)
|
||||||
|
|
||||||
vim.api.nvim_set_hl(0, "TelescopeBufferLoaded", { link = "String", default = true })
|
vim.api.nvim_set_hl(0, "TelescopeBufferLoaded", { link = "String", default = true })
|
||||||
vim.api.nvim_set_hl(0, "TelescopePathSeparator", { link = "Directory", default = true })
|
vim.api.nvim_set_hl(0, "TelescopePathSeparator", { link = "Directory", default = true })
|
||||||
@ -76,9 +78,10 @@ local function setup(ext_config)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
local is_floatwin = vim.api.nvim_win_get_config(0).relative ~= ""
|
local is_floatwin = vim.api.nvim_win_get_config(0).relative ~= ""
|
||||||
if not is_floatwin then
|
if is_floatwin or (config.ignore_register and config.ignore_register(args.buf)) then
|
||||||
frecency.register(args.buf)
|
return
|
||||||
end
|
end
|
||||||
|
async_call(frecency.register, args.buf, vim.api.nvim_buf_get_name(args.buf))
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,54 +1,46 @@
|
|||||||
local Database = require "frecency.database"
|
local Database = require "frecency.database"
|
||||||
local EntryMaker = require "frecency.entry_maker"
|
|
||||||
local Picker = require "frecency.picker"
|
local Picker = require "frecency.picker"
|
||||||
local Recency = require "frecency.recency"
|
local Timer = require "frecency.timer"
|
||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
local fs = require "frecency.fs"
|
local fs = require "frecency.fs"
|
||||||
local log = require "frecency.log"
|
local log = require "frecency.log"
|
||||||
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
local recency = require "frecency.recency"
|
||||||
|
local wait = require "frecency.wait"
|
||||||
|
local lazy_require = require "frecency.lazy_require"
|
||||||
|
local async = lazy_require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
|
|
||||||
---@class Frecency
|
---@class Frecency
|
||||||
---@field private buf_registered table<integer, boolean> flag to indicate the buffer is registered to the database.
|
---@field private buf_registered table<integer, boolean> flag to indicate the buffer is registered to the database.
|
||||||
---@field private database FrecencyDatabase
|
---@field private database FrecencyDatabase
|
||||||
---@field private entry_maker FrecencyEntryMaker
|
|
||||||
---@field private picker FrecencyPicker
|
---@field private picker FrecencyPicker
|
||||||
---@field private recency FrecencyRecency
|
|
||||||
local Frecency = {}
|
local Frecency = {}
|
||||||
|
|
||||||
---@return Frecency
|
---@return Frecency
|
||||||
Frecency.new = function()
|
Frecency.new = function()
|
||||||
local self = setmetatable({ buf_registered = {} }, { __index = Frecency }) --[[@as Frecency]]
|
local self = setmetatable({ buf_registered = {} }, { __index = Frecency }) --[[@as Frecency]]
|
||||||
self.database = Database.new()
|
self.database = Database.new()
|
||||||
self.entry_maker = EntryMaker.new()
|
|
||||||
self.recency = Recency.new()
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
---This is called when `:Telescope frecency` is called at the first time.
|
---This is called when `:Telescope frecency` is called at the first time.
|
||||||
---@return nil
|
---@return nil
|
||||||
function Frecency:setup()
|
function Frecency:setup()
|
||||||
local done = false
|
|
||||||
---@async
|
---@async
|
||||||
local function init()
|
local function init()
|
||||||
|
local timer = Timer.new "init()"
|
||||||
self.database:start()
|
self.database:start()
|
||||||
self:assert_db_entries()
|
self:assert_db_entries()
|
||||||
if config.auto_validate then
|
if config.auto_validate then
|
||||||
self:validate_database()
|
self:validate_database()
|
||||||
end
|
end
|
||||||
done = true
|
timer:finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
local is_async = not not coroutine.running()
|
local is_async = not not coroutine.running()
|
||||||
if is_async then
|
if is_async then
|
||||||
init()
|
init()
|
||||||
else
|
else
|
||||||
async.void(init)()
|
wait(init)
|
||||||
local ok, status = vim.wait(10000, function()
|
|
||||||
return done
|
|
||||||
end)
|
|
||||||
if not ok then
|
|
||||||
error("failed to setup:" .. (status == -1 and "timed out" or "interrupted"))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -56,7 +48,7 @@ end
|
|||||||
---@param opts? FrecencyPickerOptions
|
---@param opts? FrecencyPickerOptions
|
||||||
---@return nil
|
---@return nil
|
||||||
function Frecency:start(opts)
|
function Frecency:start(opts)
|
||||||
local start = os.clock()
|
local timer = Timer.new "start()"
|
||||||
log.debug "Frecency:start"
|
log.debug "Frecency:start"
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
if opts.cwd then
|
if opts.cwd then
|
||||||
@ -66,13 +58,13 @@ function Frecency:start(opts)
|
|||||||
if opts.hide_current_buffer or config.hide_current_buffer then
|
if opts.hide_current_buffer or config.hide_current_buffer then
|
||||||
ignore_filenames = { vim.api.nvim_buf_get_name(0) }
|
ignore_filenames = { vim.api.nvim_buf_get_name(0) }
|
||||||
end
|
end
|
||||||
self.picker = Picker.new(self.database, self.entry_maker, self.recency, {
|
self.picker = Picker.new(self.database, {
|
||||||
editing_bufnr = vim.api.nvim_get_current_buf(),
|
editing_bufnr = vim.api.nvim_get_current_buf(),
|
||||||
ignore_filenames = ignore_filenames,
|
ignore_filenames = ignore_filenames,
|
||||||
initial_workspace_tag = opts.workspace,
|
initial_workspace_tag = opts.workspace,
|
||||||
})
|
})
|
||||||
self.picker:start(vim.tbl_extend("force", config.get(), opts))
|
self.picker:start(vim.tbl_extend("force", config.get(), opts))
|
||||||
log.debug(("Frecency:start picker:start takes %f seconds"):format(os.clock() - start))
|
timer:finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
---This can be calledBy `require("telescope").extensions.frecency.complete`.
|
---This can be calledBy `require("telescope").extensions.frecency.complete`.
|
||||||
@ -128,15 +120,12 @@ function Frecency:assert_db_entries()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@async
|
||||||
---@param bufnr integer
|
---@param bufnr integer
|
||||||
|
---@param path string
|
||||||
---@param epoch? integer
|
---@param epoch? integer
|
||||||
function Frecency:register(bufnr, epoch)
|
function Frecency:register(bufnr, path, epoch)
|
||||||
if (config.ignore_register and config.ignore_register(bufnr)) or self.buf_registered[bufnr] then
|
if self.buf_registered[bufnr] or not fs.is_valid_path(path) then
|
||||||
return
|
|
||||||
end
|
|
||||||
local path = vim.api.nvim_buf_get_name(bufnr)
|
|
||||||
async.void(function()
|
|
||||||
if not fs.is_valid_path(path) then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local err, realpath = async.uv.fs_realpath(path)
|
local err, realpath = async.uv.fs_realpath(path)
|
||||||
@ -146,7 +135,6 @@ function Frecency:register(bufnr, epoch)
|
|||||||
self.database:update(realpath, epoch)
|
self.database:update(realpath, epoch)
|
||||||
self.buf_registered[bufnr] = true
|
self.buf_registered[bufnr] = true
|
||||||
log.debug("registered:", bufnr, path)
|
log.debug("registered:", bufnr, path)
|
||||||
end)()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@async
|
---@async
|
||||||
@ -191,7 +179,7 @@ function Frecency:query(opts, epoch)
|
|||||||
return {
|
return {
|
||||||
count = entry.count,
|
count = entry.count,
|
||||||
path = entry.path,
|
path = entry.path,
|
||||||
score = entry.ages and self.recency:calculate(entry.count, entry.ages) or 0,
|
score = entry.ages and recency.calculate(entry.count, entry.ages) or 0,
|
||||||
timestamps = entry.timestamps,
|
timestamps = entry.timestamps,
|
||||||
}
|
}
|
||||||
end, self.database:get_entries(opts.workspace, epoch))
|
end, self.database:get_entries(opts.workspace, epoch))
|
||||||
|
|||||||
11
lua/frecency/lazy_require.lua
Normal file
11
lua/frecency/lazy_require.lua
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---@param module string
|
||||||
|
return function(module)
|
||||||
|
return setmetatable({}, {
|
||||||
|
__index = function(_, key)
|
||||||
|
return require(module)[key]
|
||||||
|
end,
|
||||||
|
__call = function(_, ...)
|
||||||
|
return require(module)(...)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
@ -1,8 +1,11 @@
|
|||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
local log = require "plenary.log"
|
local lazy_require = require "frecency.lazy_require"
|
||||||
|
local log = lazy_require "plenary.log"
|
||||||
|
|
||||||
return setmetatable({}, {
|
return setmetatable({}, {
|
||||||
__index = function(_, key)
|
__index = function(_, key)
|
||||||
return config.debug and log[key] or function() end
|
return config.debug and vim.schedule_wrap(function(...)
|
||||||
|
log[key](...)
|
||||||
|
end) or function() end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
local Path = require "plenary.path"
|
local lazy_require = require "frecency.lazy_require"
|
||||||
|
local Path = lazy_require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
||||||
local uv = vim.uv or vim.loop
|
local uv = vim.uv or vim.loop
|
||||||
|
|
||||||
|
---@class FrecencyOSUtil
|
||||||
local M = {
|
local M = {
|
||||||
is_windows = uv.os_uname().sysname == "Windows_NT",
|
is_windows = uv.os_uname().sysname == "Windows_NT",
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
local EntryMaker = require "frecency.entry_maker"
|
||||||
local State = require "frecency.state"
|
local State = require "frecency.state"
|
||||||
local Finder = require "frecency.finder"
|
local Finder = require "frecency.finder"
|
||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
@ -5,11 +6,12 @@ local fs = require "frecency.fs"
|
|||||||
local fuzzy_sorter = require "frecency.fuzzy_sorter"
|
local fuzzy_sorter = require "frecency.fuzzy_sorter"
|
||||||
local substr_sorter = require "frecency.substr_sorter"
|
local substr_sorter = require "frecency.substr_sorter"
|
||||||
local log = require "frecency.log"
|
local log = require "frecency.log"
|
||||||
local Path = require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
local lazy_require = require "frecency.lazy_require"
|
||||||
local actions = require "telescope.actions"
|
local Path = lazy_require "plenary.path" --[[@as FrecencyPlenaryPath]]
|
||||||
local config_values = require("telescope.config").values
|
local actions = lazy_require "telescope.actions"
|
||||||
local pickers = require "telescope.pickers"
|
local telescope_config = lazy_require "telescope.config"
|
||||||
local utils = require "telescope.utils" --[[@as FrecencyTelescopeUtils]]
|
local pickers = lazy_require "telescope.pickers"
|
||||||
|
local utils = lazy_require "telescope.utils" --[[@as FrecencyTelescopeUtils]]
|
||||||
local uv = vim.loop or vim.uv
|
local uv = vim.loop or vim.uv
|
||||||
|
|
||||||
---@class FrecencyPicker
|
---@class FrecencyPicker
|
||||||
@ -18,7 +20,6 @@ local uv = vim.loop or vim.uv
|
|||||||
---@field private entry_maker FrecencyEntryMaker
|
---@field private entry_maker FrecencyEntryMaker
|
||||||
---@field private lsp_workspaces string[]
|
---@field private lsp_workspaces string[]
|
||||||
---@field private namespace integer
|
---@field private namespace integer
|
||||||
---@field private recency FrecencyRecency
|
|
||||||
---@field private state FrecencyState
|
---@field private state FrecencyState
|
||||||
---@field private workspace string?
|
---@field private workspace string?
|
||||||
---@field private workspace_tag_regex string
|
---@field private workspace_tag_regex string
|
||||||
@ -37,18 +38,15 @@ local Picker = {}
|
|||||||
---@field score number
|
---@field score number
|
||||||
|
|
||||||
---@param database FrecencyDatabase
|
---@param database FrecencyDatabase
|
||||||
---@param entry_maker FrecencyEntryMaker
|
|
||||||
---@param recency FrecencyRecency
|
|
||||||
---@param picker_config FrecencyPickerConfig
|
---@param picker_config FrecencyPickerConfig
|
||||||
---@return FrecencyPicker
|
---@return FrecencyPicker
|
||||||
Picker.new = function(database, entry_maker, recency, picker_config)
|
Picker.new = function(database, picker_config)
|
||||||
local self = setmetatable({
|
local self = setmetatable({
|
||||||
config = picker_config,
|
config = picker_config,
|
||||||
database = database,
|
database = database,
|
||||||
entry_maker = entry_maker,
|
entry_maker = EntryMaker.new(),
|
||||||
lsp_workspaces = {},
|
lsp_workspaces = {},
|
||||||
namespace = vim.api.nvim_create_namespace "frecency",
|
namespace = vim.api.nvim_create_namespace "frecency",
|
||||||
recency = recency,
|
|
||||||
}, { __index = Picker })
|
}, { __index = Picker })
|
||||||
local d = config.filter_delimiter
|
local d = config.filter_delimiter
|
||||||
self.workspace_tag_regex = "^%s*" .. d .. "(%S+)" .. d
|
self.workspace_tag_regex = "^%s*" .. d .. "(%S+)" .. d
|
||||||
@ -80,7 +78,6 @@ function Picker:finder(opts, workspace, workspace_tag)
|
|||||||
entry_maker,
|
entry_maker,
|
||||||
need_scandir,
|
need_scandir,
|
||||||
workspace,
|
workspace,
|
||||||
self.recency,
|
|
||||||
self.state,
|
self.state,
|
||||||
{ ignore_filenames = self.config.ignore_filenames }
|
{ ignore_filenames = self.config.ignore_filenames }
|
||||||
)
|
)
|
||||||
@ -93,7 +90,7 @@ function Picker:start(opts)
|
|||||||
path_display = function(picker_opts, path)
|
path_display = function(picker_opts, path)
|
||||||
return self:default_path_display(picker_opts, path)
|
return self:default_path_display(picker_opts, path)
|
||||||
end,
|
end,
|
||||||
}, config_values, opts or {}) --[[@as FrecencyPickerOptions]]
|
}, telescope_config.values, opts or {}) --[[@as FrecencyPickerOptions]]
|
||||||
self.workspace = self:get_workspace(opts.cwd, self.config.initial_workspace_tag or config.default_workspace)
|
self.workspace = self:get_workspace(opts.cwd, self.config.initial_workspace_tag or config.default_workspace)
|
||||||
log.debug { workspace = self.workspace }
|
log.debug { workspace = self.workspace }
|
||||||
|
|
||||||
@ -102,7 +99,7 @@ function Picker:start(opts)
|
|||||||
local picker = pickers.new(opts, {
|
local picker = pickers.new(opts, {
|
||||||
prompt_title = "Frecency",
|
prompt_title = "Frecency",
|
||||||
finder = finder,
|
finder = finder,
|
||||||
previewer = config_values.file_previewer(opts),
|
previewer = telescope_config.values.file_previewer(opts),
|
||||||
sorter = config.matcher == "default" and substr_sorter() or fuzzy_sorter(opts),
|
sorter = config.matcher == "default" and substr_sorter() or fuzzy_sorter(opts),
|
||||||
on_input_filter_cb = self:on_input_filter_cb(opts),
|
on_input_filter_cb = self:on_input_filter_cb(opts),
|
||||||
attach_mappings = function(prompt_bufnr)
|
attach_mappings = function(prompt_bufnr)
|
||||||
|
|||||||
@ -1,23 +1,15 @@
|
|||||||
local config = require "frecency.config"
|
local config = require "frecency.config"
|
||||||
|
|
||||||
---@class FrecencyRecency
|
---@class FrecencyRecency
|
||||||
---@field private modifier table<integer, { age: integer, value: integer }>
|
local M = {}
|
||||||
local Recency = {}
|
|
||||||
|
|
||||||
---@return FrecencyRecency
|
|
||||||
Recency.new = function()
|
|
||||||
return setmetatable({
|
|
||||||
modifier = config.recency_values,
|
|
||||||
}, { __index = Recency })
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param count integer
|
---@param count integer
|
||||||
---@param ages number[]
|
---@param ages number[]
|
||||||
---@return number
|
---@return number
|
||||||
function Recency:calculate(count, ages)
|
function M.calculate(count, ages)
|
||||||
local score = 0
|
local score = 0
|
||||||
for _, age in ipairs(ages) do
|
for _, age in ipairs(ages) do
|
||||||
for _, rank in ipairs(self.modifier) do
|
for _, rank in ipairs(config.recency_values) do
|
||||||
if age <= rank.age then
|
if age <= rank.age then
|
||||||
score = score + rank.value
|
score = score + rank.value
|
||||||
goto continue
|
goto continue
|
||||||
@ -28,4 +20,4 @@ function Recency:calculate(count, ages)
|
|||||||
return count * score / config.max_timestamps
|
return count * score / config.max_timestamps
|
||||||
end
|
end
|
||||||
|
|
||||||
return Recency
|
return M
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
-- TODO: use this module until telescope's release include this below.
|
-- TODO: use this module until telescope's release include this below.
|
||||||
-- https://github.com/nvim-telescope/telescope.nvim/pull/2950
|
-- https://github.com/nvim-telescope/telescope.nvim/pull/2950
|
||||||
|
|
||||||
local sorters = require "telescope.sorters"
|
local lazy_require = require "frecency.lazy_require"
|
||||||
local util = require "telescope.utils"
|
local sorters = lazy_require "telescope.sorters"
|
||||||
|
local util = lazy_require "telescope.utils"
|
||||||
|
|
||||||
local substr_highlighter = function(make_display)
|
local substr_highlighter = function(make_display)
|
||||||
return function(_, prompt, display)
|
return function(_, prompt, display)
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
-- https://github.com/nvim-lua/plenary.nvim/blob/663246936325062427597964d81d30eaa42ab1e4/lua/plenary/test_harness.lua#L86-L86
|
-- https://github.com/nvim-lua/plenary.nvim/blob/663246936325062427597964d81d30eaa42ab1e4/lua/plenary/test_harness.lua#L86-L86
|
||||||
vim.opt.runtimepath:append(vim.env.TELESCOPE_PATH)
|
vim.opt.runtimepath:append(vim.env.TELESCOPE_PATH)
|
||||||
|
|
||||||
|
local Timer = require "frecency.timer"
|
||||||
local util = require "frecency.tests.util"
|
local util = require "frecency.tests.util"
|
||||||
local log = require "plenary.log"
|
local log = require "plenary.log"
|
||||||
|
|
||||||
@ -183,7 +184,7 @@ describe("frecency", function()
|
|||||||
register(file, make_epoch "2023-07-29T00:00:00+09:00")
|
register(file, make_epoch "2023-07-29T00:00:00+09:00")
|
||||||
log.new({}, true)
|
log.new({}, true)
|
||||||
end
|
end
|
||||||
local start = os.clock()
|
local timer = Timer.new "all results"
|
||||||
local results = vim.tbl_map(function(result)
|
local results = vim.tbl_map(function(result)
|
||||||
result.timestamps = nil
|
result.timestamps = nil
|
||||||
return result
|
return result
|
||||||
@ -191,11 +192,10 @@ describe("frecency", function()
|
|||||||
table.sort(results, function(a, b)
|
table.sort(results, function(a, b)
|
||||||
return a.path < b.path
|
return a.path < b.path
|
||||||
end)
|
end)
|
||||||
local elapsed = os.clock() - start
|
timer:finish()
|
||||||
log.info(("it takes %f seconds in fetching all results"):format(elapsed))
|
|
||||||
|
|
||||||
it("returns appropriate latency (<1.0 second)", function()
|
it("returns appropriate latency (<1.0 second)", function()
|
||||||
assert.are.is_true(elapsed < 1.0)
|
assert.are.is_true(timer.elapsed < 1.0)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("returns valid response", function()
|
it("returns valid response", function()
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
local Recency = require "frecency.recency"
|
local recency = require "frecency.recency"
|
||||||
local recency = Recency.new()
|
|
||||||
|
|
||||||
describe("frecency.recency", function()
|
describe("frecency.recency", function()
|
||||||
for _, c in ipairs {
|
for _, c in ipairs {
|
||||||
@ -13,7 +12,7 @@ describe("frecency.recency", function()
|
|||||||
} do
|
} do
|
||||||
local dumped = vim.inspect(c.ages, { indent = "", newline = "" })
|
local dumped = vim.inspect(c.ages, { indent = "", newline = "" })
|
||||||
it(("%d, %s => %d"):format(c.count, dumped, c.score), function()
|
it(("%d, %s => %d"):format(c.count, dumped, c.score), function()
|
||||||
assert.are.same(c.score, recency:calculate(c.count, c.ages))
|
assert.are.same(c.score, recency.calculate(c.count, c.ages))
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ local log = require "plenary.log"
|
|||||||
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
local Path = require "plenary.path"
|
local Path = require "plenary.path"
|
||||||
local Job = require "plenary.job"
|
local Job = require "plenary.job"
|
||||||
local wait = require "frecency.tests.wait"
|
local wait = require "frecency.wait"
|
||||||
|
|
||||||
---@return FrecencyPlenaryPath
|
---@return FrecencyPlenaryPath
|
||||||
---@return fun(): nil close swwp all entries
|
---@return fun(): nil close swwp all entries
|
||||||
@ -101,7 +101,7 @@ local function with_files(files, cb_or_config, callback)
|
|||||||
frecency.database:start()
|
frecency.database:start()
|
||||||
frecency.database.tbl:wait_ready()
|
frecency.database.tbl:wait_ready()
|
||||||
end)
|
end)
|
||||||
frecency.picker = Picker.new(frecency.database, frecency.entry_maker, frecency.recency, { editing_bufnr = 0 })
|
frecency.picker = Picker.new(frecency.database, { editing_bufnr = 0 })
|
||||||
local finder = frecency.picker:finder {}
|
local finder = frecency.picker:finder {}
|
||||||
callback(frecency, finder, dir)
|
callback(frecency, finder, dir)
|
||||||
close()
|
close()
|
||||||
@ -116,16 +116,28 @@ end
|
|||||||
---@return fun(file: string, epoch: integer, reset: boolean?, wipeout?: boolean): nil reset: boolean?): nil
|
---@return fun(file: string, epoch: integer, reset: boolean?, wipeout?: boolean): nil reset: boolean?): nil
|
||||||
local function make_register(frecency, dir)
|
local function make_register(frecency, dir)
|
||||||
return function(file, epoch, reset, wipeout)
|
return function(file, epoch, reset, wipeout)
|
||||||
|
-- NOTE: this function does the same thing as BufWinEnter autocmd.
|
||||||
|
---@param bufnr integer
|
||||||
|
local function register(bufnr)
|
||||||
|
if vim.api.nvim_buf_get_name(bufnr) == "" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local is_floatwin = vim.api.nvim_win_get_config(0).relative ~= ""
|
||||||
|
if is_floatwin or (config.ignore_register and config.ignore_register(bufnr)) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
async.util.block_on(function()
|
||||||
|
frecency:register(bufnr, vim.api.nvim_buf_get_name(bufnr), epoch)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
local path = filepath(dir, file)
|
local path = filepath(dir, file)
|
||||||
vim.cmd.edit(path)
|
vim.cmd.edit(path)
|
||||||
local bufnr = assert(vim.fn.bufnr(path))
|
local bufnr = assert(vim.fn.bufnr(path))
|
||||||
if reset then
|
if reset then
|
||||||
frecency.buf_registered[bufnr] = nil
|
frecency.buf_registered[bufnr] = nil
|
||||||
end
|
end
|
||||||
frecency:register(bufnr, epoch)
|
register(bufnr)
|
||||||
vim.wait(1000, function()
|
|
||||||
return not not frecency.buf_registered[bufnr]
|
|
||||||
end)
|
|
||||||
-- HACK: This is needed because almost the same filenames use the same
|
-- HACK: This is needed because almost the same filenames use the same
|
||||||
-- buffer.
|
-- buffer.
|
||||||
if wipeout then
|
if wipeout then
|
||||||
@ -154,7 +166,7 @@ local function with_fake_register(frecency, dir, callback)
|
|||||||
bufnr = bufnr + 1
|
bufnr = bufnr + 1
|
||||||
buffers[bufnr] = path
|
buffers[bufnr] = path
|
||||||
async.util.block_on(function()
|
async.util.block_on(function()
|
||||||
frecency:register(bufnr, epoch)
|
frecency:register(bufnr, path, epoch)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
callback(register)
|
callback(register)
|
||||||
|
|||||||
26
lua/frecency/timer.lua
Normal file
26
lua/frecency/timer.lua
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
local config = require "frecency.config"
|
||||||
|
local log = require "frecency.log"
|
||||||
|
local uv = vim.uv or vim.loop
|
||||||
|
|
||||||
|
---@class FrecencyTimer
|
||||||
|
---@field elapsed number
|
||||||
|
---@field start integer
|
||||||
|
---@field title string
|
||||||
|
local Timer = {}
|
||||||
|
|
||||||
|
---@param title string
|
||||||
|
---@return FrecencyTimer
|
||||||
|
Timer.new = function(title)
|
||||||
|
return setmetatable({ start = uv.hrtime(), title = title }, { __index = Timer })
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return nil
|
||||||
|
function Timer:finish()
|
||||||
|
if not config.debug then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.elapsed = (uv.hrtime() - self.start) / 1000000000
|
||||||
|
log.debug(("[%s] takes %.3f seconds"):format(self.title, self.elapsed))
|
||||||
|
end
|
||||||
|
|
||||||
|
return Timer
|
||||||
@ -2,6 +2,20 @@
|
|||||||
|
|
||||||
-- NOTE: types are borrowed from plenary.nvim
|
-- NOTE: types are borrowed from plenary.nvim
|
||||||
|
|
||||||
|
---@class FrecencyPlenaryJob
|
||||||
|
---@field new fun(self: FrecencyPlenaryJob, opts: FrecencyPlenaryJobOpts): FrecencyPlenaryJob
|
||||||
|
---@field start fun(self: FrecencyPlenaryJob): nil
|
||||||
|
---@field handle VimSystemObj uv_process_t
|
||||||
|
|
||||||
|
---@class FrecencyPlenaryJobOpts
|
||||||
|
---@field cwd? string
|
||||||
|
---@field command? string
|
||||||
|
---@field args? string[]
|
||||||
|
---@field on_stdout? FrecencyPlenaryJobCallback
|
||||||
|
---@field on_stderr? FrecencyPlenaryJobCallback
|
||||||
|
|
||||||
|
---@alias FrecencyPlenaryJobCallback fun(error: string, data: string, self?: FrecencyPlenaryJob)
|
||||||
|
|
||||||
---@class FrecencyPlenaryPath
|
---@class FrecencyPlenaryPath
|
||||||
---@field new fun(self: FrecencyPlenaryPath|string, path?: string): FrecencyPlenaryPath
|
---@field new fun(self: FrecencyPlenaryPath|string, path?: string): FrecencyPlenaryPath
|
||||||
---@field absolute fun(): string
|
---@field absolute fun(): string
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
local log = require "frecency.log"
|
local log = require "frecency.log"
|
||||||
local async = require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
local lazy_require = require "frecency.lazy_require"
|
||||||
|
local async = lazy_require "plenary.async" --[[@as FrecencyPlenaryAsync]]
|
||||||
local uv = vim.loop or vim.uv
|
local uv = vim.loop or vim.uv
|
||||||
|
|
||||||
---@class FrecencyNativeWatcherMtime
|
---@class FrecencyWatcherMtime
|
||||||
---@field sec integer
|
---@field sec integer
|
||||||
---@field nsec integer
|
---@field nsec integer
|
||||||
local Mtime = {}
|
local Mtime = {}
|
||||||
|
|
||||||
---@param mtime FsStatMtime
|
---@param mtime FsStatMtime
|
||||||
---@return FrecencyNativeWatcherMtime
|
---@return FrecencyWatcherMtime
|
||||||
Mtime.new = function(mtime)
|
Mtime.new = function(mtime)
|
||||||
return setmetatable({ sec = mtime.sec, nsec = mtime.nsec }, Mtime)
|
return setmetatable({ sec = mtime.sec, nsec = mtime.nsec }, Mtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param other FrecencyNativeWatcherMtime
|
---@param other FrecencyWatcherMtime
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function Mtime:__eq(other)
|
function Mtime:__eq(other)
|
||||||
return self.sec == other.sec and self.nsec == other.nsec
|
return self.sec == other.sec and self.nsec == other.nsec
|
||||||
@ -24,13 +25,13 @@ function Mtime:__tostring()
|
|||||||
return string.format("%d.%d", self.sec, self.nsec)
|
return string.format("%d.%d", self.sec, self.nsec)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class FrecencyNativeWatcher
|
---@class FrecencyWatcher
|
||||||
---@field handler UvFsEventHandle
|
---@field handler UvFsEventHandle
|
||||||
---@field path string
|
---@field path string
|
||||||
---@field mtime FrecencyNativeWatcherMtime
|
---@field mtime FrecencyWatcherMtime
|
||||||
local Watcher = {}
|
local Watcher = {}
|
||||||
|
|
||||||
---@return FrecencyNativeWatcher
|
---@return FrecencyWatcher
|
||||||
Watcher.new = function()
|
Watcher.new = function()
|
||||||
return setmetatable({ path = "", mtime = Mtime.new { sec = 0, nsec = 0 } }, { __index = Watcher })
|
return setmetatable({ path = "", mtime = Mtime.new { sec = 0, nsec = 0 } }, { __index = Watcher })
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,32 +1,14 @@
|
|||||||
local config = require "frecency.config"
|
---@class FrecencyWebDevicons
|
||||||
|
local M = {
|
||||||
---@class WebDeviconsModule
|
|
||||||
---@field get_icon fun(name?: string, ext?: string, opts?: table): string, string
|
|
||||||
|
|
||||||
---@class WebDevicons
|
|
||||||
---@field is_enabled boolean
|
|
||||||
---@field private web_devicons WebDeviconsModule
|
|
||||||
local WebDevicons = {}
|
|
||||||
|
|
||||||
---@return WebDevicons
|
|
||||||
WebDevicons.new = function()
|
|
||||||
local ok, web_devicons = pcall(require, "nvim-web-devicons")
|
|
||||||
return setmetatable(
|
|
||||||
{ is_enabled = not config.disable_devicons and ok, web_devicons = web_devicons },
|
|
||||||
{ __index = WebDevicons }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param name string?
|
---@param name string?
|
||||||
---@param ext string?
|
---@param ext string?
|
||||||
---@param opts table?
|
---@param opts table?
|
||||||
---@return string
|
---@return string
|
||||||
---@return string
|
---@return string
|
||||||
function WebDevicons:get_icon(name, ext, opts)
|
get_icon = function(name, ext, opts)
|
||||||
if self.is_enabled then
|
local ok, web_devicons = pcall(require, "nvim-web-devicons")
|
||||||
return self.web_devicons.get_icon(name, ext, opts)
|
return ok and web_devicons.get_icon(name, ext, opts) or "", ""
|
||||||
end
|
end,
|
||||||
return "", ""
|
}
|
||||||
end
|
|
||||||
|
|
||||||
return WebDevicons
|
return M
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user