aboutsummaryrefslogtreecommitdiff
path: root/lua/denote-fzf-lua.lua
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-15 21:45:42 -0400
committerhistoria <[not public]>2026-06-15 21:45:42 -0400
commitf7e92893e0bddcbff82e11784fd620886fa1297d (patch)
treef7b59e5a7b98de383b976adfb007cb4ee8ee03d2 /lua/denote-fzf-lua.lua
parent920942239d2506cd48fde575da65b16742f6f575 (diff)
downloaddenote-fzf-lua-f7e92893e0bddcbff82e11784fd620886fa1297d.tar.gz
revert to shell scripts, too many bugs with lua implementation
Diffstat (limited to 'lua/denote-fzf-lua.lua')
-rw-r--r--lua/denote-fzf-lua.lua182
1 files changed, 44 insertions, 138 deletions
diff --git a/lua/denote-fzf-lua.lua b/lua/denote-fzf-lua.lua
index c2999bb..167ecb3 100644
--- a/lua/denote-fzf-lua.lua
+++ b/lua/denote-fzf-lua.lua
@@ -5,120 +5,57 @@ local fzflua = require("fzf-lua")
local builtin = require("fzf-lua.previewer.builtin")
local FIELDS = { "path", "date", "time", "sig", "title", "keywords", "ext" }
+local lua_dir = debug.getinfo(1, "S").source:match("@?(.*/)")
+local script_dir = lua_dir .. "denote-fzf-lua/scripts/"
-local function list_denote_files(dir)
- local results = {}
- local stack = { vim.fn.expand(dir) }
-
- while #stack > 0 do
- local current = table.remove(stack)
- local ok, handle = pcall(vim.loop.fs_scandir, current)
- if ok and handle then
- while true do
- local name, typ = vim.loop.fs_scandir_next(handle)
- if not name then break end
- local full = current .. "/" .. name
- if typ == "directory" then
- table.insert(stack, full)
- elseif (typ == "file" or typ == "link") and name:match("^%d%d%d%d%d%d%d%dT%d%d%d%d%d%d") then
- table.insert(results, full)
- end
- end
- end
- end
-
- return results
+local function format_field(field, delim)
+ if field == "." then return "" end
+ return delim .. delim .. field:gsub("%s", delim)
end
-local function parse_denote(basename)
- local dt = basename:sub(1, 15)
- if not dt:match("^%d%d%d%d%d%d%d%dT%d%d%d%d%d%d$") then return nil end
-
- local date = dt:sub(1, 4) .. "-" .. dt:sub(5, 6) .. "-" .. dt:sub(7, 8)
- local time = dt:sub(10, 11) .. ":" .. dt:sub(12, 13) .. ":" .. dt:sub(14, 15)
-
- local dot_idx = basename:find("%.", 16, true)
- if not dot_idx then return nil end
- local ext = basename:sub(dot_idx)
- local body = basename:sub(16, dot_idx - 1)
-
- local sig, title, keywords = "", "", ""
- local pos = 1
-
- if body:sub(pos, pos + 1) == "==" then
- local sig_end = body:find("%-%-", pos + 2)
- if sig_end then
- sig = body:sub(pos + 2, sig_end - 1)
- pos = sig_end
- end
- end
-
- if body:sub(pos, pos + 1) == "--" then
- local title_end = body:find("__", pos + 2)
- if title_end then
- title = body:sub(pos + 2, title_end - 1)
- pos = title_end
- else
- title = body:sub(pos + 2)
- pos = #body + 1
+function M.format_fzf_with_nth(options)
+ local indices = {}
+ for i, field in ipairs(FIELDS) do
+ if options.search_fields[field] then
+ table.insert(indices, i)
end
- else
- return nil
- end
-
- if pos <= #body and body:sub(pos) == "__" then
- keywords = body:sub(pos + 2)
end
-
- return {
- path = "",
- date = date,
- time = time,
- sig = sig ~= "" and sig:gsub("=", " ") or ".",
- title = title ~= "" and title:gsub("%-", " ") or ".",
- keywords = keywords ~= "" and keywords:gsub("_", " ") or ".",
- ext = ext,
- }
+ return table.concat(indices, ",")
end
-local function format_denote_table(files)
- local parsed = {}
- for _, filepath in ipairs(files) do
- local basename = vim.fn.fnamemodify(filepath, ":t")
- local dirpath = vim.fn.fnamemodify(filepath, ":h") .. "/"
- local info = parse_denote(basename)
- if info then
- info.path = dirpath
- table.insert(parsed, info)
- end
+function M.has_prereqs(force_slow)
+ if vim.fn.executable("fzf") ~= 1 then return "no" end
+ if force_slow then return "partial" end
+ for _, cmd in ipairs({ "fd", "sd", "qsv" }) do
+ if vim.fn.executable(cmd) ~= 1 then return "partial" end
end
+ return "yes"
+end
- local widths = {}
- for i, field in ipairs(FIELDS) do
- widths[i] = #field
- end
- for _, info in ipairs(parsed) do
- for i, field in ipairs(FIELDS) do
- widths[i] = math.max(widths[i], #info[field])
- end
+function M.get_script(force_slow)
+ local prereqs = M.has_prereqs(force_slow)
+ if prereqs == "no" then
+ error("Missing dependency: fzf")
+ return
+ elseif prereqs == "yes" then
+ return script_dir .. "search_files.sh"
+ else
+ return script_dir .. "fallback_search_files.sh"
end
+end
- local lines = {}
+function M.reconstruct_filename(row)
+ if not row or row == "" then return "" end
+ row = row:gsub("%s+$", "")
local parts = {}
- for i, field in ipairs(FIELDS) do
- parts[i] = string.format("%-" .. widths[i] .. "s", field)
- end
- table.insert(lines, table.concat(parts, " "))
-
- for _, info in ipairs(parsed) do
- parts = {}
- for i, field in ipairs(FIELDS) do
- parts[i] = string.format("%-" .. widths[i] .. "s", info[field])
- end
- table.insert(lines, table.concat(parts, " "))
- end
-
- return lines
+ row = row:gsub("%s%s+", "|")
+ parts.path, parts.year, parts.month, parts.day, parts.hour, parts.min, parts.sec, parts.sig, parts.title, parts.keywords, parts.ext =
+ row:match("^(.*/)|(%d%d%d%d)%-(%d%d)%-(%d%d)|(%d%d):(%d%d):(%d%d)|([^|]+)|([^|]+)|([^|]+)|(%..+)")
+ if not parts.path then return "" end
+ local sig = format_field(parts.sig, "=")
+ local title = format_field(parts.title, "-")
+ local keywords = format_field(parts.keywords, "_")
+ return parts.path .. parts.year .. parts.month .. parts.day .. "T" .. parts.hour .. parts.min .. parts.sec .. sig .. title .. keywords .. parts.ext
end
M.reconstruct_previewer = builtin.buffer_or_file:extend()
@@ -137,41 +74,9 @@ function M.reconstruct_previewer:parse_entry(entry_str)
}
end
-local function format_field(field, delim)
- if field == "." then return "" end
- return delim .. delim .. field:gsub("%s", delim)
-end
-
-function M.reconstruct_filename(row)
- if not row or row == "" then return "" end
- local t = {}
- row = row:gsub("%s%s+", "|")
- t.path, t.year, t.month, t.day, t.hour, t.min, t.sec, t.sig, t.title, t.keywords, t.ext =
- row:match("^(.*/)|(%d%d%d%d)%-(%d%d)%-(%d%d)|(%d%d):(%d%d):(%d%d)|([^|]+)|([^|]+)|([^|]+)|(%..+)")
- if not t.path then return "" end
- t.sig = format_field(t.sig, "=")
- t.title = format_field(t.title, "-")
- t.keywords = format_field(t.keywords, "_")
- return t.path .. t.year .. t.month .. t.day .. "T" .. t.hour .. t.min .. t.sec .. t.sig .. t.title .. t.keywords .. t.ext
-end
-
-function M.format_fzf_with_nth(options)
- local indices = {}
- for i, field in ipairs(FIELDS) do
- if options.search_fields[field] then
- table.insert(indices, i)
- end
- end
- return table.concat(indices, ",")
-end
-
function M.search_files(options)
- local files = list_denote_files(options.dir)
- if #files == 0 then
- vim.notify("denote-fzf-lua: no Denote files found in " .. options.dir, vim.log.levels.WARN)
- return
- end
- local lines = format_denote_table(files)
+ local script = M.get_script(options.force_slow_mode)
+ if not script then return end
local opts = {}
opts.previewer = M.reconstruct_previewer
@@ -185,7 +90,8 @@ function M.search_files(options)
vim.api.nvim_command("edit " .. vim.fn.fnameescape(filename))
end,
}
- fzflua.fzf_exec(lines, opts)
+ local dir = vim.fn.expand(options.dir)
+ fzflua.fzf_exec(script .. " " .. dir, opts)
end
function M.search_contents(options)
@@ -194,7 +100,7 @@ function M.search_contents(options)
return
end
local opts = {}
- opts.cwd = options.dir
+ opts.cwd = vim.fn.expand(options.dir)
opts.previewer = "builtin"
opts.fzf_opts = options.fzf_lua_opts.fzf_opts
opts.actions = fzflua.defaults.actions.files