mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 10:49:08 +00:00
feat(picker): added new icons
picker for nerd fonts and emoji. Closes #703
This commit is contained in:
parent
570d2191d5
commit
97898e910d
6 changed files with 138 additions and 2 deletions
97
lua/snacks/picker/source/icons.lua
Normal file
97
lua/snacks/picker/source/icons.lua
Normal file
|
@ -0,0 +1,97 @@
|
|||
local M = {}
|
||||
|
||||
---@type table<string, {url: string, v?:number, build: fun(data:table):snacks.picker.Icon[]}>
|
||||
M.sources = {
|
||||
nerd_fonts = {
|
||||
url = "https://github.com/ryanoasis/nerd-fonts/raw/refs/heads/master/glyphnames.json",
|
||||
v = 3,
|
||||
build = function(data)
|
||||
---@cast data table<string, {char:string, code:string}>
|
||||
local ret = {} ---@type snacks.picker.Icon[]
|
||||
for name, info in pairs(data) do
|
||||
if name ~= "METADATA" then
|
||||
local font, icon = name:match("^([%w_]+)%-(.*)$")
|
||||
if not font then
|
||||
error("Invalid icon name: " .. name)
|
||||
end
|
||||
table.insert(ret, {
|
||||
name = icon,
|
||||
icon = info.char,
|
||||
source = "nerd font",
|
||||
category = font,
|
||||
})
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end,
|
||||
},
|
||||
emoji = {
|
||||
url = "https://raw.githubusercontent.com/muan/unicode-emoji-json/refs/heads/main/data-by-emoji.json",
|
||||
v = 4,
|
||||
build = function(data)
|
||||
---@cast data table<string, {name:string, slug:string, group:string}>
|
||||
local ret = {} ---@type snacks.picker.Icon[]
|
||||
for icon, info in pairs(data) do
|
||||
table.insert(ret, {
|
||||
name = info.name,
|
||||
icon = icon,
|
||||
source = "emoji",
|
||||
category = info.group,
|
||||
})
|
||||
end
|
||||
return ret
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
---@class snacks.picker.Icon: snacks.picker.finder.Item
|
||||
---@field icon string
|
||||
---@field name string
|
||||
---@field source string
|
||||
---@field category string
|
||||
---@field desc? string
|
||||
|
||||
---@param source_name string
|
||||
local function load(source_name)
|
||||
local source = M.sources[source_name]
|
||||
local file = vim.fn.stdpath("cache") .. "/snacks/picker/icons/" .. source_name .. "-v" .. (source.v or 1) .. ".json"
|
||||
vim.fn.mkdir(vim.fn.fnamemodify(file, ":h"), "p")
|
||||
if vim.fn.filereadable(file) == 1 then
|
||||
local fd = assert(io.open(file, "r"))
|
||||
local data = fd:read("*a")
|
||||
fd:close()
|
||||
return vim.json.decode(data) ---@type snacks.picker.Icon[]
|
||||
end
|
||||
|
||||
Snacks.notify("Fetching `" .. source_name .. "` icons …")
|
||||
if vim.fn.executable("curl") == 0 then
|
||||
Snacks.notify.error("`curl` is required to fetch icons")
|
||||
return {}
|
||||
end
|
||||
local out = vim.fn.system({ "curl", "-s", "-L", source.url })
|
||||
if vim.v.shell_error ~= 0 then
|
||||
Snacks.notify.error(out, { title = "Icons Picker" })
|
||||
return {}
|
||||
end
|
||||
local icons = source.build(vim.json.decode(out))
|
||||
local fd = assert(io.open(file, "w"))
|
||||
fd:write(vim.json.encode(icons))
|
||||
fd:close()
|
||||
return icons
|
||||
end
|
||||
|
||||
---@param opts snacks.picker.icons.Config
|
||||
---@type snacks.picker.finder
|
||||
function M.icons(opts)
|
||||
local ret = {} ---@type snacks.picker.Icon[]
|
||||
for _, source in ipairs(opts.icons or { "nerd_fonts", "emoji" }) do
|
||||
vim.list_extend(ret, load(source))
|
||||
end
|
||||
for _, icon in ipairs(ret) do
|
||||
icon.text = Snacks.picker.util.text(icon, { "source", "category", "name" })
|
||||
icon.data = icon.icon
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
return M
|
Loading…
Add table
Add a link
Reference in a new issue