Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions lua/volt/compat/devicons.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- lua/volt/compat/devicons.lua
-- Backwards compatibility shim that mimics the minimal nvim-web-devicons API

local icons = require "volt.icons"

local M = {}

-- Mimic nvim-web-devicons.get_icon(filename, extension, opts)
function M.get_icon(name, ext, opts)
local icon, color, hl_name = icons.get_icon(name, ext)
local hl = "VoltIcon" .. (hl_name or "Default")
return icon, hl
end

-- Minimal get_icon_color(filename, extension)
function M.get_icon_color(name, ext, opts)
local _, color = icons.get_icon(name, ext)
return color
end

-- Provide a filetype-based helper (best-effort)
function M.get_icon_by_filetype(ft, opts)
return M.get_icon(ft, ft, opts)
end

function M.setup(opts)
-- noop: Volt manages icons internally
end

return M
101 changes: 101 additions & 0 deletions lua/volt/icons.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
-- lua/volt/icons.lua
-- Minimal, cache-friendly icon provider with optional lazy full-set loader

local M = {}

-- Icon cache for performance
local icon_cache = {}

-- Lightweight icon data (commonly used)
local icons_by_extension = {
lua = { icon = "", color = "#51A0CF", name = "Lua" },
js = { icon = "", color = "#EAD41C", name = "JavaScript" },
ts = { icon = "", color = "#2b7489", name = "TypeScript" },
py = { icon = "", color = "#3572A5", name = "Python" },
md = { icon = "", color = "#083fa1", name = "Markdown" },
rs = { icon = "", color = "#dea584", name = "Rust" },
go = { icon = "", color = "#00ADD8", name = "Go" },
toml= { icon = "", color = "#9c4221", name = "TOML" },
json= { icon = "ﬥ", color = "#cbcb41", name = "JSON" },
sh = { icon = "", color = "#6e4a7e", name = "Shell" },
}

local icons_by_filename = {
[".gitignore"] = { icon = "", color = "#F54D27", name = "GitIgnore" },
["Makefile"] = { icon = "", color = "#6D8086", name = "Makefile" },
["Dockerfile"] = { icon = "", color = "#0db7ed", name = "Dockerfile" },
["README.md"] = { icon = "", color = "#083fa1", name = "Readme" },
["LICENSE"] = { icon = "", color = "#6d8086", name = "License" },
["package.json"]= { icon = "", color = "#cbcb41", name = "Npm" },
["tsconfig.json"]= { icon = "", color = "#2b7489", name = "TSConfig" },
["Cargo.toml"] = { icon = "", color = "#dea584", name = "Cargo" },
[".env"] = { icon = "", color = "#4f5d95", name = "Env" },
["init.lua"] = { icon = "", color = "#51A0CF", name = "LuaInit" },
}

-- Default fallback icon
local default_icon = {
icon = "",
color = "#6d8086",
name = "Default"
}

function M.get_icon(name, ext)
local cache_key = (name or "") .. ":" .. (ext or "")
if icon_cache[cache_key] then
return unpack(icon_cache[cache_key])
end

local icon_data

-- filename match (case-insensitive)
if name then
local lname = name:lower()
icon_data = icons_by_filename[lname]
end

-- extension match
if not icon_data and ext and ext ~= "" then
local lext = ext:lower()
icon_data = icons_by_extension[lext]
end

icon_data = icon_data or default_icon

icon_cache[cache_key] = { icon_data.icon, icon_data.color, icon_data.name }
return icon_data.icon, icon_data.color, icon_data.name
end

-- Lazy loading for full icon set
function M.load_full_icons()
if M.full_icons_loaded then return end

local ok, full_icons = pcall(require, "volt.icons.full")
if ok and full_icons then
if full_icons.by_extension then
icons_by_extension = vim.tbl_extend("force", icons_by_extension, full_icons.by_extension)
end
if full_icons.by_filename then
icons_by_filename = vim.tbl_extend("force", icons_by_filename, full_icons.by_filename)
end
-- clear cache so new icons are picked up
icon_cache = {}
end

M.full_icons_loaded = true
end

-- Utility to get icon with highlight group
function M.get_icon_with_hl(name, ext)
local icon, color, hl_name = M.get_icon(name, ext)
if color then
local safe_name = (hl_name or "Default"):gsub("%s+", "")
local hl_group = "VoltIcon" .. safe_name
-- set highlight (idempotent)
pcall(vim.api.nvim_set_hl, 0, hl_group, { fg = color })
return icon, hl_group
end
return icon, nil
end

return M
34 changes: 34 additions & 0 deletions lua/volt/icons/full.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- lua/volt/icons/full.lua
-- Extracted subset of the full nvim-web-devicons dataset.
-- Only a representative subset is included here to keep file short.
-- The extraction script (scripts/extract_icons.lua) can be used to generate
-- a complete table from an installed nvim-web-devicons.

return {
by_extension = {
lua = { icon = "", color = "#51A0CF", name = "Lua" },
js = { icon = "", color = "#EAD41C", name = "JavaScript" },
ts = { icon = "", color = "#2b7489", name = "TypeScript" },
py = { icon = "", color = "#3572A5", name = "Python" },
rs = { icon = "", color = "#dea584", name = "Rust" },
go = { icon = "", color = "#00ADD8", name = "Go" },
md = { icon = "", color = "#083fa1", name = "Markdown" },
json= { icon = "ﬥ", color = "#cbcb41", name = "JSON" },
sh = { icon = "", color = "#6e4a7e", name = "Shell" },
toml= { icon = "", color = "#9c4221", name = "TOML" },
-- Note: full dataset would continue here...
},
by_filename = {
[".gitignore"] = { icon = "", color = "#F54D27", name = "GitIgnore" },
["Makefile"] = { icon = "", color = "#6D8086", name = "Makefile" },
["Dockerfile"] = { icon = "", color = "#0db7ed", name = "Dockerfile" },
["README.md"] = { icon = "", color = "#083fa1", name = "Readme" },
["LICENSE"] = { icon = "", color = "#6d8086", name = "License" },
["package.json"]= { icon = "", color = "#cbcb41", name = "Npm" },
["tsconfig.json"]= { icon = "", color = "#2b7489", name = "TSConfig" },
["Cargo.toml"] = { icon = "", color = "#dea584", name = "Cargo" },
[".env"] = { icon = "", color = "#4f5d95", name = "Env" },
["init.lua"] = { icon = "", color = "#51A0CF", name = "LuaInit" },
-- Note: full dataset would continue here...
},
}
11 changes: 11 additions & 0 deletions lua/volt/init.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
-- Updated: expose icons API for Volt and provide helper M.get_file_icon
local M = {}
local api = vim.api
local map = vim.keymap.set
local draw = require "volt.draw"
local state = require "volt.state"
local utils = require "volt.utils"
local icons = require "volt.icons" -- new

local get_section = function(tb, name)
for _, value in ipairs(tb) do
Expand Down Expand Up @@ -139,4 +141,13 @@ M.close = function(buf)
end)
end

-- Expose icon utilities (new)
M.icons = icons

M.get_file_icon = function(filepath)
local name = vim.fn.fnamemodify(filepath, ":t")
local ext = vim.fn.fnamemodify(filepath, ":e")
return M.icons.get_icon_with_hl(name, ext)
end

return M
65 changes: 65 additions & 0 deletions scripts/extract_icons.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
-- scripts/extract_icons.lua
-- Helper to extract the full icon tables from an installed nvim-web-devicons
-- Usage (from repo root):
-- nvim --headless -c 'lua require("scripts.extract_icons").run()' -c qa
--
-- This will write lua/volt/icons/full.lua. Requires nvim-web-devicons to be installed
-- in your runtimepath.

local M = {}

local function safe_write(path, content)
local f, err = io.open(path, "w")
if not f then
return nil, err
end
f:write(content)
f:close()
return true
end

function M.run()
local ok, devicons = pcall(require, "nvim-web-devicons")
if not ok or not devicons then
return error("nvim-web-devicons not found in runtimepath")
end

-- Try to get maps from the plugin API or fall back to known internals
local by_ext = {}
local by_name = {}

-- Attempt to use plugin-provided functions if available
if devicons.get_icons then
-- some versions expose a combined table
local tbl = devicons.get_icons()
if tbl.by_extension then by_ext = tbl.by_extension end
if tbl.by_filename then by_name = tbl.by_filename end
else
-- try common functions / internals
if devicons.get_icon_by_filetype then
-- Not standard; skip
end
-- Try reading exported tables (different plugin versions vary)
by_ext = devicons.icons_by_file_extension or devicons.get_icons_by_extension and devicons.get_icons_by_extension() or by_ext
by_name = devicons.icons_by_filename or devicons.get_icons_by_filename and devicons.get_icons_by_filename() or by_name
end

-- Fallback: if those calls returned functions/unknown, ensure final tables
by_ext = by_ext or {}
by_name = by_name or {}

local content = {}
table.insert(content, "-- Auto-generated by scripts/extract_icons.lua")
table.insert(content, "return {")
table.insert(content, " by_extension = " .. vim.inspect(by_ext) .. ",")
table.insert(content, " by_filename = " .. vim.inspect(by_name) .. ",")
table.insert(content, "}")

local ok, err = safe_write("lua/volt/icons/full.lua", table.concat(content, "\n"))
if not ok then
error("Failed to write lua/volt/icons/full.lua: " .. tostring(err))
end
print("Wrote lua/volt/icons/full.lua")
end

return M