1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
local M = {}
local config = require("denote-fzf-lua.config")
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 format_field(field, delim)
if field == "." then return "" end
return delim .. delim .. field:gsub("%s", delim)
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.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
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
function M.reconstruct_filename(row)
if not row or row == "" then return "" end
row = row:gsub("%s+$", "")
local parts = {}
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()
function M.reconstruct_previewer:new(o, opts, fzf_win)
M.reconstruct_previewer.super.new(self, o, opts, fzf_win)
setmetatable(self, M.reconstruct_previewer)
return self
end
function M.reconstruct_previewer:parse_entry(entry_str)
return {
path = M.reconstruct_filename(entry_str),
line = 1,
col = 1,
}
end
function M.search_files(options)
local script = M.get_script(options.force_slow_mode)
if not script then return end
local opts = {}
opts.previewer = M.reconstruct_previewer
opts.fzf_opts = vim.deepcopy(options.fzf_lua_opts.fzf_opts)
opts.fzf_opts["--with-nth"] = M.format_fzf_with_nth(options)
opts.fzf_opts["--header-lines"] = 1
opts.fzf_opts["--delimiter"] = "\\s{2,}"
opts.actions = {
default = function(selected)
local filename = M.reconstruct_filename(selected[1])
vim.api.nvim_command("edit " .. vim.fn.fnameescape(filename))
end,
}
local dir = vim.fn.expand(options.dir)
fzflua.fzf_exec(script .. " " .. dir, opts)
end
function M.search_contents(options)
if vim.fn.executable("rg") ~= 1 then
vim.notify("denote-fzf-lua: ripgrep is required for content search", vim.log.levels.WARN)
return
end
local opts = {}
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
fzflua.fzf_live(function(query)
local q = type(query) == "table" and table.concat(query, " ") or query or ""
return "rg --column --color=always -i -- " .. vim.fn.shellescape(q)
end, opts)
end
function M.load_cmd(options)
vim.api.nvim_create_user_command("DenoteSearch", function(opts)
if opts.fargs[1] == "files" then
M.search_files(options)
elseif opts.fargs[1] == "contents" then
M.search_contents(options)
else
error("Unsupported operation " .. opts.fargs[1])
end
end, {
nargs = 1,
complete = function()
return { "files", "contents" }
end,
})
end
function M.setup(options)
options = vim.tbl_deep_extend("force", config.defaults, options or {})
fzflua.setup(options.fzf_lua_opts)
M.load_cmd(options)
end
return M
|