Something went wrong. Try again.
🐻 minimal ui2 fuzzy finder for Neovim codeberg.org/comfysage/artio.nvim
Something went wrong. Try again.
5.3 kB · 222 lines
Lua
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223local uv = vim.uv
local utils = {}
---@param path string---@param ctx? vim.context.modsfunction utils.edit(path, ctx) local f = function() vim.api.nvim_cmd({ cmd = "edit", args = { path }, magic = { file = false, bar = false }, }, {}) end
if ctx then return vim._with(ctx, f) end
return f()end
local function parsechunks(chunks) local lines = {}
for _, chunk in ipairs(chunks) do for _, line in ipairs(vim.split(chunk, "\n", { trimempty = true })) do table.insert(lines, line) end end
return linesend
---@param prg? string---@param opts? table---@return fun(arg?: string): string[]function utils.make_cmd(prg, opts) ---@async ---@param arg? string ---@return string[] return function(arg) if not prg then return {} end local cmd, n = prg, nil if arg and #arg > 0 then arg = string.format("'%s'", arg) cmd, n = prg:gsub("%$%*", arg) if n == 0 then cmd = ("%s %s"):format(prg, arg) end end
local chunks = {} local err_chunks = {}
local stdout = uv.new_pipe() local stderr = uv.new_pipe()
local co = coroutine.running() assert(co, "utils.make_cmd needs to be run inside a coroutine")
uv.spawn( vim.o.shell, vim.tbl_extend("keep", { stdio = { nil, stdout, stderr }, args = { vim.o.shellcmdflag, cmd }, }, opts or {}), function(code, signal) if code == 0 then local lines = parsechunks(chunks) coroutine.resume(co, lines) return end local err = ("error while running shell cmd %s (%d)"):format(signal, code) table.insert(err_chunks, 1, err) local lines = parsechunks(err_chunks) coroutine.resume(co, lines, true) end )
---@diagnostic disable-next-line: param-type-mismatch uv.read_start(stdout, function(err, data) assert(not err, err) if data then table.insert(chunks, data) end end)
---@diagnostic disable-next-line: param-type-mismatch uv.read_start(stderr, function(err, data) assert(not err, err) if data then table.insert(err_chunks, data) end end)
return coroutine.yield() endend
---@param fn fun(item: artio.Picker.item): vim.quickfix.entry---@return artio.Picker.actionfunction utils.make_setqflist(fn) return require("artio").wrap(function(self) vim.fn.setqflist(vim .iter(ipairs(self.matches)) :map(function(_, match) local item = self.items[match[1]] local qfitem = fn(item) return qfitem end) :totable()) self:cancel() end, function(_) vim.cmd.copen() end)end
---@param fn fun(item: artio.Picker.item): vim.quickfix.entry---@return artio.Picker.actionfunction utils.make_setqflistmark(fn) return require("artio").wrap(function(self) vim.fn.setqflist(vim .iter(ipairs(self:getmarked())) :map(function(_, id) local item = self.items[id] local qfitem = fn(item) return qfitem end) :totable()) self:cancel() end, function(_) vim.cmd.copen() end)end
---@param fn fun(item: artio.Picker.item): vim.quickfix.entry---@return table<string, artio.Picker.action>function utils.make_setqflistactions(fn) return { setqflist = utils.make_setqflist(fn), setqflistmark = utils.make_setqflistmark(fn), }end
---@param fn fun(item: artio.Picker.item): integer---@return table<string, artio.Picker.action>function utils.make_fileactions(fn) return { split = require("artio").wrap(function(self) self:cancel() end, function(self) local item = self:getcurrent() if not item then return end local buf = fn(item) vim.api.nvim_open_win(buf, true, { win = -1, vertical = false }) end), vsplit = require("artio").wrap(function(self) self:cancel() end, function(self) local item = self:getcurrent() if not item then return end local buf = fn(item) vim.api.nvim_open_win(buf, true, { win = -1, vertical = true }) end), tabnew = require("artio").wrap(function(self) self:cancel() end, function(self) local item = self:getcurrent() if not item then return end local buf = fn(item) vim.api.nvim_cmd({ cmd = "split", args = { ("+%dbuf"):format(buf) }, ---@diagnostic disable-next-line: missing-fields mods = { tab = 1, silent = true, }, }, { output = false, }) end), }end
function utils.hl_qfitem(item) local name_end = string.find(item.text, ":") if not name_end then return end name_end = name_end - 1 local lnum_end = string.find(item.text, ":", name_end + 2) if not lnum_end then return end lnum_end = lnum_end - 1 local col_end = string.find(item.text, ":", lnum_end + 2) if not col_end then return end col_end = col_end - 1
return { { { 0, name_end }, "Title" }, { { name_end, name_end + 1 }, "NonText" }, { { name_end + 1, lnum_end }, "Number" }, { { lnum_end, lnum_end + 1 }, "NonText" }, { { lnum_end + 1, col_end }, "Number" }, { { col_end, col_end + 1 }, "NonText" }, }end
return utils