diff --git a/lua/telescope/_extensions/frecency.lua b/lua/telescope/_extensions/frecency.lua index 68c2da2..13a5fb8 100644 --- a/lua/telescope/_extensions/frecency.lua +++ b/lua/telescope/_extensions/frecency.lua @@ -6,9 +6,10 @@ if not has_telescope then end -- start the database client -print("start") +-- print("start") local db_client = require("telescope._extensions.frecency.db_client") -vim.defer_fn(db_client.init, 100) -- TODO: this is a crappy attempt to lessen loadtime impact, use VimEnter? +-- vim.defer_fn(db_client.init, 100) -- TODO: this is a crappy attempt to lessen loadtime impact, use VimEnter? +db_client.init() -- TODO: this is a crappy attempt to lessen loadtime impact, use VimEnter? -- finder code @@ -77,9 +78,15 @@ local frecency = function(opts) }):find() end +local validate = function() + print("validate db") + db_client.validate() +end + return telescope.register_extension { exports = { frecency = frecency, + validate = validate, }, } diff --git a/lua/telescope/_extensions/frecency/db_client.lua b/lua/telescope/_extensions/frecency/db_client.lua index 30fa0f0..00fe0e9 100644 --- a/lua/telescope/_extensions/frecency/db_client.lua +++ b/lua/telescope/_extensions/frecency/db_client.lua @@ -1,4 +1,5 @@ -local sqlwrap = require("telescope._extensions.frecency.sql_wrapper") +local sqlwrap = require("telescope._extensions.frecency.sql_wrapper") +local util = require("telescope._extensions.frecency.util") local MAX_TIMESTAMPS = 10 @@ -23,15 +24,10 @@ local function init() -- setup autocommands vim.api.nvim_command("augroup TelescopeFrecency") vim.api.nvim_command("autocmd!") - vim.api.nvim_command("autocmd BufEnter * lua require'telescope._extensions.frecency.db_client'.autocmd_handler(vim.fn.expand(''))") + vim.api.nvim_command("autocmd BufWinEnter,BufWritePost * lua require'telescope._extensions.frecency.db_client'.autocmd_handler(vim.fn.expand(''))") vim.api.nvim_command("augroup END") end --- TODO: move these to util.lua -local function string_isempty(s) - return s == nil or s == '' -end - local function calculate_file_score(frequency, timestamps) local recency_score = 0 for _, ts in pairs(timestamps) do @@ -83,17 +79,38 @@ local function get_file_scores() end local function autocmd_handler(filepath) - if not sql_wrapper or string_isempty(filepath) then return end + if not sql_wrapper or util.string_isempty(filepath) then return end -- check if file is registered as loaded if not vim.b.frecency_registered then + -- allow noname files to go unregistered until BufWritePost + if not util.fs_stat(filepath).exists then return end + + -- TODO: only register buffer if update did something? + -- TODO: apply filetype_ignore here? vim.b.frecency_registered = 1 + -- print("registered buffer") sql_wrapper:update(filepath) end end +local function validate() + if not sql_wrapper then return {} end + + local files = sql_wrapper:do_transaction('get_all_filepaths') + for _, entry in pairs(files) do + if not util.fs_stat(entry.path).exists then + -- remove entries from file and timestamp tables + print("removing entry: " .. entry.path .. "[" .. entry.id .."]") + sql_wrapper:do_transaction('file_delete_entry', { id = entry.id }) + sql_wrapper:do_transaction('timestamp_delete_with_file_id', { file_id = entry.id }) + end + end +end + return { init = init, get_file_scores = get_file_scores, autocmd_handler = autocmd_handler, + validate = validate, } diff --git a/lua/telescope/_extensions/frecency/sorter.lua b/lua/telescope/_extensions/frecency/sorter.lua index a4e798d..706221e 100644 --- a/lua/telescope/_extensions/frecency/sorter.lua +++ b/lua/telescope/_extensions/frecency/sorter.lua @@ -1,20 +1,21 @@ local sorters = require "telescope.sorters" +local util = require("telescope._extensions.frecency.util") local my_sorters = {} -local function split(s, delimiter) - local result = {} - for match in (s .. delimiter):gmatch("(.-)" .. delimiter) do - table.insert(result, match) - end - return result -end +-- local function split(s, delimiter) +-- local result = {} +-- for match in (s .. delimiter):gmatch("(.-)" .. delimiter) do +-- table.insert(result, match) +-- end +-- return result +-- end local substr_highlighter = function(_, prompt, display) local highlights = {} display = display:lower() - local search_terms = split(prompt, " ") + local search_terms = util.split(prompt, " ") local hl_start, hl_end for _, word in pairs(search_terms) do @@ -35,7 +36,7 @@ my_sorters.get_substr_matcher = function(opts) substr.scoring_function = function(_, prompt, _, entry) local display = entry.name:lower() - local search_terms = split(prompt, " ") + local search_terms = util.split(prompt, " ") local matched for _, word in pairs(search_terms) do matched = display:find(word, 1, true) and 1 or -1 diff --git a/lua/telescope/_extensions/frecency/sql_wrapper.lua b/lua/telescope/_extensions/frecency/sql_wrapper.lua index d008654..ed7e464 100644 --- a/lua/telescope/_extensions/frecency/sql_wrapper.lua +++ b/lua/telescope/_extensions/frecency/sql_wrapper.lua @@ -1,5 +1,5 @@ +local util = require("telescope._extensions.frecency.util") local vim = vim -local uv = vim.loop local has_sql, sql = pcall(require, "sql") if not has_sql then @@ -28,28 +28,22 @@ local schemas = {[[ ]]} local queries = { - ["file_add_entry"] = "INSERT INTO files (path, count) values(:path, 1);", - ["file_update_counter"] = "UPDATE files SET count = count + 1 WHERE path = :path;", - ["timestamp_add_entry"] = "INSERT INTO timestamps (file_id, timestamp) values(:file_id, julianday('now'));", - ["timestamp_delete_before_id"] = "DELETE FROM timestamps WHERE id < :id and file_id == :file_id;", - ["get_all_filepaths"] = "SELECT * FROM files;", - ["get_all_timestamp_ages"] = "SELECT id, file_id, CAST((julianday('now') - julianday(timestamp)) * 24 * 60 AS INTEGER) AS age FROM timestamps;", - ["get_row"] = "SELECT * FROM files WHERE path == :path;", - ["get_timestamp_ids_for_file"] = "SELECT id FROM timestamps WHERE file_id == :file_id;", + ["file_add_entry"] = "INSERT INTO files (path, count) values(:path, 1);", + ["file_delete_entry"] = "DELETE FROM files WHERE id == :id;", + ["file_update_counter"] = "UPDATE files SET count = count + 1 WHERE path == :path;", + ["timestamp_add_entry"] = "INSERT INTO timestamps (file_id, timestamp) values(:file_id, julianday('now'));", + ["timestamp_delete_before_id"] = "DELETE FROM timestamps WHERE id < :id and file_id == :file_id;", + ["timestamp_delete_with_file_id"] = "DELETE FROM timestamps WHERE file_id == :file_id;", + ["get_all_filepaths"] = "SELECT * FROM files;", + ["get_all_timestamp_ages"] = "SELECT id, file_id, CAST((julianday('now') - julianday(timestamp)) * 24 * 60 AS INTEGER) AS age FROM timestamps;", + ["get_row"] = "SELECT * FROM files WHERE path == :path;", + ["get_timestamp_ids_for_file"] = "SELECT id FROM timestamps WHERE file_id == :file_id;", } -- local ignore_patterns = { -- } -- -local function fs_stat(path) -- TODO: move this to new file with M - local stat = uv.fs_stat(path) - local res = {} - res.exists = stat and true or false -- TODO: this is silly - res.isdirectory = (stat and stat.type == "directory") and true or false - - return res -end local M = {} M.queries = queries @@ -108,7 +102,7 @@ function M:get_row_id(filepath) end function M:update(filepath) - local filestat = fs_stat(filepath) + local filestat = util.fs_stat(filepath) if (vim.tbl_isempty(filestat) or filestat.exists == false or filestat.isdirectory == true) then diff --git a/lua/telescope/_extensions/frecency/util.lua b/lua/telescope/_extensions/frecency/util.lua new file mode 100644 index 0000000..4dffef7 --- /dev/null +++ b/lua/telescope/_extensions/frecency/util.lua @@ -0,0 +1,26 @@ +local uv = vim.loop + +local util = {} + +util.string_isempty = function(s) + return s == nil or s == '' +end + +util.split = function(s, delimiter) + local result = {} + for match in (s .. delimiter):gmatch("(.-)" .. delimiter) do + table.insert(result, match) + end + return result +end + +util.fs_stat = function(path) -- TODO: move this to new file with M + local stat = uv.fs_stat(path) + local res = {} + res.exists = stat and true or false -- TODO: this is silly + res.isdirectory = (stat and stat.type == "directory") and true or false + + return res +end + +return util