Skip to content

Commit

Permalink
hoge
Browse files Browse the repository at this point in the history
  • Loading branch information
delphinus committed Sep 2, 2023
1 parent 76e8238 commit 487d0e2
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 27 deletions.
161 changes: 143 additions & 18 deletions lua/frecency/fndr.lua
Original file line number Diff line number Diff line change
@@ -1,39 +1,164 @@
local async = require "plenary.async" --[[@as PlenaryAsync]]
local log = require "plenary.log"

---@class FrecencyFndr
---@field private config FrecencyFndrConfig
---@field config FrecencyFndrConfig
---@field closed boolean
---@field entries FrecencyEntry[]
---@field private database FrecencyDatabase
---@field private entry_maker FrecencyEntryMaker
---@field private fs FrecencyFS
---@field private recency FrecencyRecency
---@field private rx PlenaryAsyncControlChannelRx
---@field private state FrecencyState
local Finder = {}

---@class FrecencyFndrConfig
---@field chunk_size integer default: 1000
---@field sleep_interval integer default: 50

---@param database FrecencyDatabase
---@param entry_maker FrecencyEntryMaker
---@param entry_maker fun(file: FrecencyFile): FrecencyEntry
---@param fs FrecencyFS
---@param path string
---@param recency FrecencyRecency
---@param state FrecencyState
---@param workspace string?
---@param datetime string?
---@param config FrecencyFndrConfig?
---@return FrecencyFndr
Finder.new = function(database, entry_maker, fs, recency, config)
return setmetatable({
config = vim.tbl_extend("force", { chunk_size = 1000 }, config or {}),
Finder.new = function(database, entry_maker, fs, path, recency, state, workspace, datetime, config)
local self = setmetatable({
config = vim.tbl_extend("force", { chunk_size = 1000, sleep_interval = 50 }, config or {}),
closed = false,
database = database,
entry_maker = entry_maker,
fs = fs,
entries = {},
recency = recency,
}, { __index = Finder })
state = state,
}, {
__index = Finder,
---@param self FrecencyFndr
__call = function(self, ...)
return self:find(...)
end,
})
local tx, rx = async.control.channel.mpsc()
self.rx = rx
async.run(function()
-- NOTE: return to the main loop
async.util.sleep(0)
local seen = {}
for i, file in ipairs(self:get_results(workspace, datetime)) do
local entry = entry_maker(file)
seen[entry.filename] = true
entry.index = i
table.insert(self.entries, entry)
tx.send(entry)
end
local count = 0
local index = #self.entries
for name in fs:scan_dir(path) do
if self.closed then
break
end
local fullpath = fs.joinpath(path, name)
if not seen[fullpath] then
seen[fullpath] = true
count = count + 1
local entry = entry_maker { id = 0, count = 0, path = fullpath, score = 0 }
if entry then
index = index + 1
entry.index = index
table.insert(self.entries, entry)
tx.send(entry)
if count % self.config.chunk_size == 0 then
self:reflow_results()
async.util.sleep(self.config.sleep_interval)
end
end
end
end
self:close()
tx.send(nil)
end)
return self
end

---@class FrecencyFndrOptions
---@field workspace string?
---@field workspace_tag string?
---@param _ string
---@param process_result fun(entry: FrecencyEntry): nil
---@param process_complete fun(): nil
function Finder:find(_, process_result, process_complete)
for _, entry in ipairs(self.entries) do
if process_result(entry) then
return
end
end
while not self.closed do
local entry = self.rx.recv()
if not entry then
break
elseif entry.index > #self.entries and process_result(entry) then
return
end
end
process_complete()
end

---@param state FrecencyState
---@param filepath_formatter FrecencyFilepathFormatter
---@param opts FrecencyFndrOptions
function Finder:start(state, filepath_formatter, opts)
local entry_maker = self.entry_maker:create(filepath_formatter, opts.workspace, opts.workspace_tag)
---@async
---@param workspace string?
---@param datetime string?
---@return FrecencyFile[]
function Finder:get_results(workspace, datetime)
log.debug { workspace = workspace or "NONE" }
local start_fetch = os.clock()
local files = self.database:get_entries(workspace, datetime)
log.debug(("it takes %f seconds in fetching entries"):format(os.clock() - start_fetch))
local start_results = os.clock()
local elapsed_recency = 0
for _, file in ipairs(files) do
local start_recency = os.clock()
file.score = file.ages and self.recency:calculate(file.count, file.ages) or 0
file.ages = nil
elapsed_recency = elapsed_recency + (os.clock() - start_recency)
end
log.debug(("it takes %f seconds in calculating recency"):format(elapsed_recency))
log.debug(("it takes %f seconds in making results"):format(os.clock() - start_results))

local start_sort = os.clock()
table.sort(files, function(a, b)
return a.score > b.score or (a.score == b.score and a.path > b.path)
end)
log.debug(("it takes %f seconds in sorting"):format(os.clock() - start_sort))
return files
end

function Finder:close()
self.closed = true
end

function Finder: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 Finder
8 changes: 3 additions & 5 deletions lua/frecency/frecency.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ local Sqlite = require "frecency.database.sqlite"
local Native = require "frecency.database.native"
local EntryMaker = require "frecency.entry_maker"
local FS = require "frecency.fs"
local Finder = require "frecency.finder"
local Migrator = require "frecency.migrator"
local Picker = require "frecency.picker"
local Recency = require "frecency.recency"
Expand All @@ -14,7 +13,7 @@ local log = require "plenary.log"
---@field config FrecencyConfig
---@field private buf_registered table<integer, boolean> flag to indicate the buffer is registered to the database.
---@field private database FrecencyDatabase
---@field private finder FrecencyFinder
---@field private entry_maker FrecencyEntryMaker
---@field private fs FrecencyFS
---@field private migrator FrecencyMigrator
---@field private picker FrecencyPicker
Expand Down Expand Up @@ -69,11 +68,10 @@ Frecency.new = function(opts)
end
self.database = Database.new(self.fs, { root = config.db_root })
local web_devicons = WebDevicons.new(not config.disable_devicons)
local entry_maker = EntryMaker.new(self.fs, web_devicons, {
self.entry_maker = EntryMaker.new(self.fs, web_devicons, {
show_filter_column = config.show_filter_column,
show_scores = config.show_scores,
})
self.finder = Finder.new(entry_maker, self.fs)
self.recency = Recency.new()
self.migrator = Migrator.new(self.fs, self.recency, self.config.db_root)
return self
Expand Down Expand Up @@ -122,7 +120,7 @@ function Frecency:start(opts)
local start = os.clock()
log.debug "Frecency:start"
opts = opts or {}
self.picker = Picker.new(self.database, self.finder, self.fs, self.recency, {
self.picker = Picker.new(self.database, self.entry_maker, self.fs, self.recency, {
default_workspace_tag = self.config.default_workspace,
editing_bufnr = vim.api.nvim_get_current_buf(),
filter_delimiter = self.config.filter_delimiter,
Expand Down
21 changes: 17 additions & 4 deletions lua/frecency/picker.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local State = require "frecency.state"
local Finder = require "frecency.fndr"
local log = require "plenary.log"
local Path = require "plenary.path" --[[@as PlenaryPath]]
local actions = require "telescope.actions"
Expand All @@ -11,7 +12,7 @@ local uv = vim.loop or vim.uv
---@class FrecencyPicker
---@field private config FrecencyPickerConfig
---@field private database FrecencyDatabase
---@field private finder FrecencyFinder
---@field private entry_maker FrecencyEntryMaker
---@field private fs FrecencyFS
---@field private lsp_workspaces string[]
---@field private namespace integer
Expand All @@ -37,16 +38,16 @@ local Picker = {}
---@field score number

---@param database FrecencyDatabase
---@param finder FrecencyFinder
---@param entry_maker FrecencyEntryMaker
---@param fs FrecencyFS
---@param recency FrecencyRecency
---@param config FrecencyPickerConfig
---@return FrecencyPicker
Picker.new = function(database, finder, fs, recency, config)
Picker.new = function(database, entry_maker, fs, recency, config)
local self = setmetatable({
config = config,
database = database,
finder = finder,
entry_maker = entry_maker,
fs = fs,
lsp_workspaces = {},
namespace = vim.api.nvim_create_namespace "frecency",
Expand All @@ -70,6 +71,18 @@ end
---| fun(opts: FrecencyPickerOptions, path: string): string
---@field workspace string?

---@param state FrecencyState
---@param need_scandir boolean
---@param opts table
---@param path string
---@param workspace string?
---@param workspace_tag string?
function Picker:finder(state, need_scandir, opts, path, workspace, workspace_tag)
local filepath_formatter = self:filepath_formatter(opts)
local entry_maker = self.entry_maker:create(filepath_formatter, workspace, workspace_tag)
return Finder.new(self.database, entry_maker, self.fs, path, self.recency, state, workspace)
end

---@param opts FrecencyPickerOptions?
function Picker:start(opts)
opts = vim.tbl_extend("force", {
Expand Down

0 comments on commit 487d0e2

Please sign in to comment.