minimal extui fuzzy finder for neovim
1local utils = {}
2
3local function cmd_callback(o)
4 local src = o.stderr
5 if o.code == 0 then
6 src = o.stdout
7 end
8 src = src
9 local lines = vim.split(src, "\n", { trimempty = true })
10 return lines
11end
12
13---@param prg? string
14---@param opts? table
15---@return fun(arg?: string): string[]
16function utils.make_cmd(prg, opts)
17 return function(arg)
18 if not prg then
19 return {}
20 end
21 arg = string.format("'%s'", arg or "")
22 local cmd, n = prg:gsub("%$%*", arg)
23 if n == 0 then
24 cmd = ("%s %s"):format(prg, arg)
25 end
26 return cmd_callback(vim
27 .system(
28 { vim.o.shell, "-c", cmd },
29 vim.tbl_extend("force", {
30 text = true,
31 }, opts or {})
32 )
33 :wait())
34 end
35end
36
37---@param fn fun(item: artio.Picker.item): vim.quickfix.entry
38---@return artio.Picker.action
39function utils.make_setqflist(fn)
40 return require("artio").wrap(function(self)
41 vim.fn.setqflist(vim
42 .iter(ipairs(self.matches))
43 :map(function(_, match)
44 local item = self.items[match[1]]
45 local qfitem = fn(item)
46 return qfitem
47 end)
48 :totable())
49 self:cancel()
50 end, function(_)
51 vim.cmd.copen()
52 end)
53end
54
55---@param fn fun(item: artio.Picker.item): vim.quickfix.entry
56---@return artio.Picker.action
57function utils.make_setqflistmark(fn)
58 return require("artio").wrap(function(self)
59 vim.fn.setqflist(vim
60 .iter(ipairs(self:getmarked()))
61 :map(function(_, id)
62 local item = self.items[id]
63 local qfitem = fn(item)
64 return qfitem
65 end)
66 :totable())
67 self:cancel()
68 end, function(_)
69 vim.cmd.copen()
70 end)
71end
72
73---@param fn fun(item: artio.Picker.item): vim.quickfix.entry
74---@return table<string, artio.Picker.action>
75function utils.make_setqflistactions(fn)
76 return {
77 setqflist = utils.make_setqflist(fn),
78 setqflistmark = utils.make_setqflistmark(fn),
79 }
80end
81
82---@param fn fun(item: artio.Picker.item): integer
83---@return table<string, artio.Picker.action>
84function utils.make_fileactions(fn)
85 return {
86 split = require("artio").wrap(function(self)
87 self:cancel()
88 end, function(self)
89 local item = self:getcurrent()
90 if not item then
91 return
92 end
93 local buf = fn(item)
94 vim.api.nvim_open_win(buf, true, { win = -1, vertical = false })
95 end),
96 vsplit = require("artio").wrap(function(self)
97 self:cancel()
98 end, function(self)
99 local item = self:getcurrent()
100 if not item then
101 return
102 end
103 local buf = fn(item)
104 vim.api.nvim_open_win(buf, true, { win = -1, vertical = true })
105 end),
106 tabnew = require("artio").wrap(function(self)
107 self:cancel()
108 end, function(self)
109 local item = self:getcurrent()
110 if not item then
111 return
112 end
113 local buf = fn(item)
114 vim.api.nvim_cmd({
115 cmd = "split",
116 args = { ("+%dbuf"):format(buf) },
117 ---@diagnostic disable-next-line: missing-fields
118 mods = {
119 tab = 1,
120 silent = true,
121 },
122 }, {
123 output = false,
124 })
125 end),
126 }
127end
128
129return utils