-
Notifications
You must be signed in to change notification settings - Fork 77
/
search.lua
130 lines (115 loc) · 3.37 KB
/
search.lua
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
local Config = require("todo-comments.config")
local Highlight = require("todo-comments.highlight")
local Util = require("todo-comments.util")
local M = {}
local function keywords_filter(opts_keywords)
assert(not opts_keywords or type(opts_keywords) == "string", "'keywords' must be a comma separated string or nil")
local all_keywords = vim.tbl_keys(Config.keywords)
if not opts_keywords then
return all_keywords
end
local filters = vim.split(opts_keywords, ",")
return vim.tbl_filter(function(kw)
return vim.tbl_contains(filters, kw)
end, all_keywords)
end
function M.process(lines)
local results = {}
for _, line in pairs(lines) do
local file, row, col, text = line:match("^(.+):(%d+):(%d+):(.*)$")
if file then
local item = {
filename = file,
lnum = tonumber(row),
col = tonumber(col),
line = text,
}
local start, finish, kw = Highlight.match(text)
if start then
kw = Config.keywords[kw] or kw
item.tag = kw
item.text = vim.trim(text:sub(start))
item.message = vim.trim(text:sub(finish + 1))
table.insert(results, item)
end
end
end
return results
end
function M.search(cb, opts)
opts = opts or {}
opts.cwd = opts.cwd or "."
opts.cwd = vim.fn.fnamemodify(opts.cwd, ":p")
opts.disable_not_found_warnings = opts.disable_not_found_warnings or false
if not Config.loaded then
Util.error("todo-comments isn't loaded. Did you run setup()?")
return
end
local command = Config.options.search.command
if vim.fn.executable(command) ~= 1 then
Util.error(command .. " was not found on your path")
return
end
local ok, Job = pcall(require, "plenary.job")
if not ok then
Util.error("search requires https://github.com/nvim-lua/plenary.nvim")
return
end
local args =
vim.tbl_flatten({ Config.options.search.args, Config.search_regex(keywords_filter(opts.keywords)), opts.cwd })
Job
:new({
command = command,
args = args,
on_exit = vim.schedule_wrap(function(j, code)
if code == 2 then
local error = table.concat(j:stderr_result(), "\n")
Util.error(command .. " failed with code " .. code .. "\n" .. error)
end
if code == 1 and opts.disable_not_found_warnings ~= true then
Util.warn("no todos found")
end
local lines = j:result()
cb(M.process(lines))
end),
})
:start()
end
local function parse_opts(opts)
if not opts or type(opts) ~= "string" then
return opts
end
return {
keywords = opts:match("keywords=(%S*)"),
cwd = opts:match("cwd=(%S*)"),
}
end
function M.setqflist(opts)
M.setlist(opts)
end
function M.setloclist(opts)
M.setlist(opts, true)
end
function M.setlist(opts, use_loclist)
opts = parse_opts(opts) or {}
opts.open = (opts.open ~= nil and {opts.open} or {true})[1]
M.search(function(results)
if use_loclist then
vim.fn.setloclist(0, {}, " ", { title = "Todo", id = "$", items = results })
else
vim.fn.setqflist({}, " ", { title = "Todo", id = "$", items = results })
end
if opts.open then
if use_loclist then
vim.cmd([[lopen]])
else
vim.cmd([[copen]])
end
end
local win = vim.fn.getqflist({ winid = true })
if win.winid ~= 0 then
Highlight.highlight_win(win.winid, true)
end
end, opts)
end
return M