tangled
alpha
login
or
join now
robinwobin.dev
/
artio.nvim
3
fork
atom
minimal extui fuzzy finder for neovim
3
fork
atom
overview
issues
pulls
pipelines
feat: add icon support
robinwobin.dev
4 months ago
e4a741b3
2eade987
+50
-7
5 changed files
expand all
collapse all
unified
split
README.md
lua
artio
builtins.lua
config.lua
picker.lua
view.lua
+2
README.md
···
12
12
- Lightweight picker window built on Neovim's extui
13
13
- Prompt + list UI components - minimal and focused
14
14
- Fuzzy filtering using matchfuzzy (built-in)
15
15
+
- Icon support for common filetypes through [mini.icons](https://github.com/echasnovski/mini.nvim) _(optional)_
15
16
- No heavy dependencies - pure Lua
16
17
17
18
## installation
···
39
40
bottom = true,
40
41
promptprefix = "",
41
42
pointer = "",
43
43
+
use_icons = true, -- requires mini.icons
42
44
},
43
45
win = {
44
46
height = 12,
+9
-1
lua/artio/builtins.lua
···
7
7
end
8
8
9
9
local artio = lzrq("artio")
10
10
+
local config = lzrq("artio.config")
10
11
11
12
local builtins = {}
12
13
···
47
48
vim.cmd.edit(text)
48
49
end)
49
50
end,
51
51
+
get_icon = config.get().opts.use_icons and function(item)
52
52
+
return require("mini.icons").get("file", item.v)
53
53
+
end or nil,
50
54
})
51
55
end
52
56
···
92
96
vim.schedule(function()
93
97
vim.cmd.buffer(bufnr)
94
98
end)
95
95
-
end)
99
99
+
end, {
100
100
+
get_icon = config.get().opts.use_icons and function(item)
101
101
+
return require("mini.icons").get("file", vim.api.nvim_buf_get_name(item.v))
102
102
+
end or nil,
103
103
+
})
96
104
end
97
105
98
106
return builtins
+2
lua/artio/config.lua
···
9
9
---@field bottom boolean
10
10
---@field promptprefix string
11
11
---@field pointer string
12
12
+
---@field use_icons boolean
12
13
13
14
---@class artio.config.win
14
15
---@field height? integer|number
···
25
26
bottom = true,
26
27
promptprefix = "",
27
28
pointer = "",
29
29
+
use_icons = package.loaded['mini.icons'] and true or false,
28
30
},
29
31
win = {
30
32
height = 12,
+2
-1
lua/artio/picker.lua
···
1
1
local View = require("artio.view")
2
2
3
3
-
---@alias artio.Picker.item { id: integer, v: string, text: string }
3
3
+
---@alias artio.Picker.item { id: integer, v: string, text: string, icon?: string, icon_hl?: string }
4
4
---@alias artio.Picker.match [integer, integer[], integer] [item, pos[], score]
5
5
6
6
---@class artio.Picker.proto
···
8
8
---@field fn? fun(lst: artio.Picker.item[], input: string): artio.Picker.match[]
9
9
---@field on_close? fun(text: string, idx: integer)
10
10
---@field format_item? fun(item: string): string
11
11
+
---@field get_icon? fun(item: artio.Picker.item): string, string
11
12
---@field opts? artio.config.opts
12
13
---@field win? artio.config.win
13
14
---@field prompt? string
+35
-5
lua/artio/view.lua
···
361
361
offset = math.min(math.max(0, offset), math.max(0, #self.picker.matches - maxlistheight))
362
362
end
363
363
364
364
+
local icon_pad = 2
365
365
+
364
366
function View:showmatches()
365
367
local indent = vim.fn.strdisplaywidth(self.picker.opts.pointer) + 1
366
368
local prefix = (" "):rep(indent)
369
369
+
local icon_pad_str = (" "):rep(icon_pad)
367
370
368
371
self:updateoffset()
369
372
370
373
local lines = {} ---@type string[]
371
374
local hls = {}
375
375
+
local icons = {} ---@type ([string, string]|false)[]
372
376
for i = 1 + offset, math.min(#self.picker.matches, maxlistheight + offset) do
373
377
local match = self.picker.matches[i]
374
374
-
lines[#lines + 1] = ("%s%s"):format(prefix, self.picker.items[match[1]].text)
378
378
+
local item = self.picker.items[match[1]]
379
379
+
380
380
+
local icon, icon_hl = item.icon, item.icon_hl
381
381
+
if not (icon and icon_hl) and vim.is_callable(self.picker.get_icon) then
382
382
+
icon, icon_hl = self.picker.get_icon(item)
383
383
+
item.icon, item.icon_hl = icon, icon_hl
384
384
+
end
385
385
+
icons[#icons + 1] = icon and { icon, icon_hl } or false
386
386
+
icon = icon and ("%s%s"):format(item.icon, icon_pad_str) or ""
387
387
+
388
388
+
lines[#lines + 1] = ("%s%s%s"):format(prefix, icon, item.text)
375
389
hls[#hls + 1] = match[2]
376
390
end
377
391
cmdline.erow = cmdline.srow + #lines
378
392
vim.api.nvim_buf_set_lines(ext.bufs.cmd, cmdline.srow, cmdline.erow, false, lines)
379
393
380
380
-
for i = 1, #hls do
381
381
-
for j = 1, #hls[i] do
382
382
-
local col = indent + hls[i][j]
383
383
-
self:mark(cmdline.srow + i - 1, col, vim.tbl_extend("force", ext_match_opts, { end_col = col + 1 }))
394
394
+
for i = 1, #lines do
395
395
+
local has_icon = icons[i] and icons[i][1] and true
396
396
+
local icon_indent = has_icon and (#icons[i][1] + icon_pad) or 0
397
397
+
398
398
+
if has_icon and icons[i][2] then
399
399
+
self:mark(
400
400
+
cmdline.srow + i - 1,
401
401
+
indent,
402
402
+
vim.tbl_extend("force", ext_match_opts, {
403
403
+
end_col = indent + icon_indent,
404
404
+
hl_group = icons[i][2],
405
405
+
})
406
406
+
)
407
407
+
end
408
408
+
409
409
+
if hls[i] then
410
410
+
for j = 1, #hls[i] do
411
411
+
local col = indent + icon_indent + hls[i][j]
412
412
+
self:mark(cmdline.srow + i - 1, col, vim.tbl_extend("force", ext_match_opts, { end_col = col + 1 }))
413
413
+
end
384
414
end
385
415
end
386
416
end