minimal extui fuzzy finder for neovim
1---@module 'artio.config'
2
3---@class artio.config
4---@field opts artio.config.opts
5---@field win artio.config.win
6---@field mappings table<string, 'up'|'down'|'accept'|'cancel'|'togglepreview'|string>
7
8---@class artio.config.opts
9---@field preselect boolean
10---@field bottom boolean
11---@field shrink boolean
12---@field promptprefix string
13---@field prompt_title boolean
14---@field pointer string
15---@field marker string
16---@field infolist ('index'|'list')[]
17---@field use_icons boolean
18
19---@class artio.config.win
20---@field height? integer|number
21---@field hidestatusline? boolean
22---@field preview_opts? fun(view: artio.View): vim.api.keyset.win_config
23
24local M = {}
25
26---@type artio.config
27---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section)
28---@text # Default ~
29M.default = {
30 opts = {
31 preselect = true,
32 bottom = true,
33 shrink = true,
34 promptprefix = "",
35 prompt_title = true,
36 pointer = "",
37 marker = "│",
38 infolist = { "list" }, -- index: [1] list: (4/5)
39 use_icons = _G["MiniIcons"] and true or false,
40 },
41 win = {
42 height = 0.4,
43 hidestatusline = false, -- works best with laststatus=3
44 ---@diagnostic disable-next-line: assign-type-mismatch
45 preview_opts = vim.NIL,
46 },
47 mappings = {
48 ["<down>"] = "down",
49 ["<up>"] = "up",
50 ["<cr>"] = "accept",
51 ["<esc>"] = "cancel",
52 ["<tab>"] = "mark",
53 ["<c-g>"] = "togglelive",
54 ["<c-l>"] = "togglepreview",
55 ["<c-q>"] = "setqflist",
56 ["<m-q>"] = "setqflistmark",
57 ["<c-s>"] = "split",
58 ["<c-v>"] = "vsplit",
59 ["<c-t>"] = "tabnew",
60 },
61}
62
63---@type artio.config
64---@diagnostic disable-next-line: missing-fields
65M.config = {}
66
67---@private
68---@generic T: table|any[]
69---@param tdefault T
70---@param toverride T
71---@return T
72local function tmerge(tdefault, toverride)
73 if toverride == nil then
74 return tdefault
75 end
76
77 if vim.islist(tdefault) then
78 return toverride
79 end
80 if vim.tbl_isempty(tdefault) then
81 return toverride
82 end
83
84 return vim.iter(pairs(tdefault)):fold({}, function(tnew, k, v)
85 if v == vim.NIL and toverride[k] ~= nil then
86 tnew[k] = toverride[k]
87 return tnew
88 end
89
90 if toverride[k] == nil or type(v) ~= type(toverride[k]) then
91 tnew[k] = v
92 return tnew
93 end
94 if type(v) == "table" then
95 tnew[k] = tmerge(v, toverride[k])
96 return tnew
97 end
98
99 tnew[k] = toverride[k]
100 return tnew
101 end)
102end
103
104---@param tdefault artio.config
105---@param toverride artio.config
106---@return artio.config
107function M.merge(tdefault, toverride)
108 local defaults = vim.deepcopy(tdefault, true)
109 local mappings = tdefault.mappings
110 defaults.mappings = vim.NIL
111 local t = tmerge(defaults, toverride)
112 t.mappings = toverride.mappings or mappings
113
114 return t
115end
116
117---@return artio.config
118function M.get()
119 return M.merge(M.default, M.config)
120end
121
122---@param cfg artio.config
123---@return artio.config
124function M.override(cfg)
125 return M.merge(M.default, cfg)
126end
127
128---@param cfg artio.config
129function M.set(cfg)
130 M.config = cfg
131end
132
133return M