minimal extui fuzzy finder for neovim
at main 144 lines 3.6 kB view raw
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 129function utils.hl_qfitem(item) 130 local name_end = string.find(item.text, ":") - 1 131 local lnum_end = string.find(item.text, ":", name_end + 2) - 1 132 local col_end = string.find(item.text, ":", lnum_end + 2) - 1 133 134 return { 135 { { 0, name_end }, "Title" }, 136 { { name_end, name_end + 1 }, "NonText" }, 137 { { name_end + 1, lnum_end }, "Number" }, 138 { { lnum_end, lnum_end + 1 }, "NonText" }, 139 { { lnum_end + 1, col_end }, "Number" }, 140 { { col_end, col_end + 1 }, "NonText" }, 141 } 142end 143 144return utils