feat: expand nvim highlights and add audit script

This commit is contained in:
s0wlz (Matthias Puchstein)
2026-01-12 23:11:24 +01:00
parent 6b3bb01c2c
commit 2ac05f469c
5 changed files with 304 additions and 0 deletions

View File

@@ -82,6 +82,12 @@ function M.load()
WildMenu = { fg = p.void, bg = p.tech },
Pmenu = { fg = p.text, bg = p.panel },
PmenuSel = { fg = p.ink, bg = p.razor, bold = true }, -- Red Menu Selection
PmenuKind = { fg = p.dim, bg = p.panel },
PmenuKindSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuExtra = { fg = p.dim, bg = p.panel },
PmenuExtraSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuMatch = { fg = p.tech, bg = p.panel, bold = true },
PmenuMatchSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuSbar = { bg = p.panel },
PmenuThumb = { bg = p.stealth },
ErrorMsg = { fg = p.alert },
@@ -149,6 +155,10 @@ function M.load()
LspReferenceWrite = { bg = p.panel, bold = true },
LspSignatureActiveParameter = { fg = p.void, bg = p.tech, bold = true },
LspInlayHint = { fg = p.dim, bg = p.panel },
LspCodeLens = { fg = p.dim },
LspCodeLensSeparator = { fg = p.stealth },
LspInfoBorder = { fg = p.border, bg = p.panel },
LspInfoTitle = { fg = p.dim, bg = p.panel },
-- DIAGNOSTICS -----------------------------------------------------------
DiagnosticError = { fg = p.alert },
@@ -282,10 +292,29 @@ function M.load()
["@text"] = "Normal",
["@text.title"] = "Title",
["@markup.heading"] = "Title",
["@markup.heading.1"] = "Title",
["@markup.heading.2"] = "Title",
["@markup.heading.3"] = "Title",
["@markup.heading.4"] = "Title",
["@markup.heading.5"] = "Title",
["@markup.heading.6"] = "Title",
["@markup.link"] = "ApexMarkupLink",
["@markup.link.label"] = "ApexMarkupLink",
["@markup.link.url"] = "ApexMarkupLink",
["@markup.strong"] = "ApexMarkupStrong",
["@markup.italic"] = "ApexMarkupItalic",
["@markup.strikethrough"] = "DiagnosticDeprecated",
["@markup.underline"] = "Underlined",
["@markup.raw"] = "String",
["@markup.raw.block"] = "String",
["@markup.raw.delimiter"] = "Delimiter",
["@markup.quote"] = "Comment",
["@markup.list"] = "Delimiter",
["@markup.list.checked"] = "String",
["@markup.list.unchecked"] = "Comment",
["@markup.math"] = "Constant",
["@markup.environment"] = "Type",
["@markup.environment.name"] = "Type",
["@type"] = "Type",
["@type.builtin"] = "Type",
["@type.definition"] = "Type",
@@ -320,6 +349,12 @@ function M.load()
["@lsp.type.variable"] = "Identifier",
["@lsp.mod.deprecated"] = "DiagnosticDeprecated",
["@lsp.mod.abstract"] = "Type",
["@lsp.mod.declaration"] = "Keyword",
["@lsp.mod.defaultLibrary"] = "Constant",
["@lsp.mod.definition"] = "Keyword",
["@lsp.mod.documentation"] = "Comment",
["@lsp.mod.modification"] = "Operator",
["@lsp.mod.readonly"] = "Constant",
["@lsp.mod.static"] = "Constant",
["@lsp.mod.async"] = "Keyword",

View File

@@ -82,6 +82,12 @@ function M.load()
WildMenu = { fg = p.void, bg = p.tech },
Pmenu = { fg = p.text, bg = p.panel },
PmenuSel = { fg = p.ink, bg = p.razor, bold = true }, -- Red Menu Selection
PmenuKind = { fg = p.dim, bg = p.panel },
PmenuKindSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuExtra = { fg = p.dim, bg = p.panel },
PmenuExtraSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuMatch = { fg = p.tech, bg = p.panel, bold = true },
PmenuMatchSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuSbar = { bg = p.panel },
PmenuThumb = { bg = p.stealth },
ErrorMsg = { fg = p.alert },
@@ -149,6 +155,10 @@ function M.load()
LspReferenceWrite = { bg = p.panel, bold = true },
LspSignatureActiveParameter = { fg = p.void, bg = p.tech, bold = true },
LspInlayHint = { fg = p.dim, bg = p.panel },
LspCodeLens = { fg = p.dim },
LspCodeLensSeparator = { fg = p.stealth },
LspInfoBorder = { fg = p.border, bg = p.panel },
LspInfoTitle = { fg = p.dim, bg = p.panel },
-- DIAGNOSTICS -----------------------------------------------------------
DiagnosticError = { fg = p.alert },
@@ -282,10 +292,29 @@ function M.load()
["@text"] = "Normal",
["@text.title"] = "Title",
["@markup.heading"] = "Title",
["@markup.heading.1"] = "Title",
["@markup.heading.2"] = "Title",
["@markup.heading.3"] = "Title",
["@markup.heading.4"] = "Title",
["@markup.heading.5"] = "Title",
["@markup.heading.6"] = "Title",
["@markup.link"] = "ApexMarkupLink",
["@markup.link.label"] = "ApexMarkupLink",
["@markup.link.url"] = "ApexMarkupLink",
["@markup.strong"] = "ApexMarkupStrong",
["@markup.italic"] = "ApexMarkupItalic",
["@markup.strikethrough"] = "DiagnosticDeprecated",
["@markup.underline"] = "Underlined",
["@markup.raw"] = "String",
["@markup.raw.block"] = "String",
["@markup.raw.delimiter"] = "Delimiter",
["@markup.quote"] = "Comment",
["@markup.list"] = "Delimiter",
["@markup.list.checked"] = "String",
["@markup.list.unchecked"] = "Comment",
["@markup.math"] = "Constant",
["@markup.environment"] = "Type",
["@markup.environment.name"] = "Type",
["@type"] = "Type",
["@type.builtin"] = "Type",
["@type.definition"] = "Type",
@@ -320,6 +349,12 @@ function M.load()
["@lsp.type.variable"] = "Identifier",
["@lsp.mod.deprecated"] = "DiagnosticDeprecated",
["@lsp.mod.abstract"] = "Type",
["@lsp.mod.declaration"] = "Keyword",
["@lsp.mod.defaultLibrary"] = "Constant",
["@lsp.mod.definition"] = "Keyword",
["@lsp.mod.documentation"] = "Comment",
["@lsp.mod.modification"] = "Operator",
["@lsp.mod.readonly"] = "Constant",
["@lsp.mod.static"] = "Constant",
["@lsp.mod.async"] = "Keyword",

18
scripts/nvim-audit.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
if ! command -v nvim >/dev/null 2>&1; then
echo "error: nvim not found on PATH" >&2
exit 1
fi
if [[ ! -f "${root}/dist/nvim/colors/apex-neon.lua" ]]; then
echo "error: missing dist/nvim/colors/apex-neon.lua; run 'uv run build.py'" >&2
exit 1
fi
cd "$root"
nvim --headless -u NONE -U NONE -c "lua dofile('${root}/scripts/nvim_audit.lua')"

181
scripts/nvim_audit.lua Normal file
View File

@@ -0,0 +1,181 @@
local function out(msg)
vim.api.nvim_out_write(msg .. "\n")
end
local function err(msg)
vim.api.nvim_err_write(msg .. "\n")
end
if not vim.api.nvim_get_hl then
err("error: nvim_get_hl unavailable; require Neovim 0.9+")
vim.cmd("cquit")
end
local function load_theme()
local theme_path = vim.fn.getcwd() .. "/dist/nvim/colors/apex-neon.lua"
local ok, load_err = pcall(dofile, theme_path)
if not ok then
err("error: failed to load theme: " .. tostring(load_err))
err("hint: run 'uv run build.py' to regenerate dist/")
vim.cmd("cquit")
end
end
local function has_style(hl)
for key, value in pairs(hl) do
if key ~= "link" and key ~= "default" then
if type(value) ~= "boolean" or value then
return true
end
end
end
return false
end
local function get_hl(name)
local ok, hl = pcall(vim.api.nvim_get_hl, 0, { name = name, link = false })
if not ok then
return nil, "error"
end
return hl, nil
end
local function audit(groups)
local issues = {}
local default_links = {
Normal = true,
NONE = true,
}
for _, group in ipairs(groups) do
local hl, api_err = get_hl(group)
if api_err or not hl or next(hl) == nil then
table.insert(issues, "missing: " .. group)
elseif hl.link and default_links[hl.link] then
table.insert(issues, "default-link: " .. group .. " -> " .. hl.link)
elseif not hl.link and not has_style(hl) then
table.insert(issues, "empty: " .. group)
end
end
return issues
end
local groups = {
-- Pmenu
"Pmenu",
"PmenuSel",
"PmenuSbar",
"PmenuThumb",
"WildMenu",
-- LSP UI
"LspReferenceText",
"LspReferenceRead",
"LspReferenceWrite",
"LspSignatureActiveParameter",
"LspInlayHint",
-- Diagnostics (core + variants)
"DiagnosticError",
"DiagnosticWarn",
"DiagnosticInfo",
"DiagnosticHint",
"DiagnosticOk",
"DiagnosticDeprecated",
"DiagnosticUnnecessary",
"DiagnosticUnderlineError",
"DiagnosticUnderlineWarn",
"DiagnosticUnderlineInfo",
"DiagnosticUnderlineHint",
"DiagnosticUnderlineOk",
"DiagnosticVirtualTextError",
"DiagnosticVirtualTextWarn",
"DiagnosticVirtualTextInfo",
"DiagnosticVirtualTextHint",
"DiagnosticVirtualTextOk",
"DiagnosticVirtualLinesError",
"DiagnosticVirtualLinesWarn",
"DiagnosticVirtualLinesInfo",
"DiagnosticVirtualLinesHint",
"DiagnosticVirtualLinesOk",
"DiagnosticSignError",
"DiagnosticSignWarn",
"DiagnosticSignInfo",
"DiagnosticSignHint",
"DiagnosticSignOk",
"DiagnosticFloatingError",
"DiagnosticFloatingWarn",
"DiagnosticFloatingInfo",
"DiagnosticFloatingHint",
"DiagnosticFloatingOk",
-- Markup (Tree-sitter)
"@markup.heading",
"@markup.link",
"@markup.link.url",
"@markup.strong",
"@markup.italic",
"ApexMarkupStrong",
"ApexMarkupItalic",
"ApexMarkupLink",
-- LSP semantic tokens (types)
"@lsp.type.boolean",
"@lsp.type.builtinType",
"@lsp.type.class",
"@lsp.type.comment",
"@lsp.type.decorator",
"@lsp.type.enum",
"@lsp.type.enumMember",
"@lsp.type.event",
"@lsp.type.function",
"@lsp.type.interface",
"@lsp.type.keyword",
"@lsp.type.macro",
"@lsp.type.method",
"@lsp.type.modifier",
"@lsp.type.namespace",
"@lsp.type.number",
"@lsp.type.operator",
"@lsp.type.parameter",
"@lsp.type.property",
"@lsp.type.regexp",
"@lsp.type.string",
"@lsp.type.struct",
"@lsp.type.type",
"@lsp.type.typeParameter",
"@lsp.type.variable",
-- LSP semantic tokens (modifiers)
"@lsp.mod.deprecated",
"@lsp.mod.readonly",
"@lsp.mod.static",
"@lsp.mod.async",
-- LSP semantic tokens (typemods)
"@lsp.typemod.function.async",
"@lsp.typemod.method.async",
"@lsp.typemod.function.deprecated",
"@lsp.typemod.method.deprecated",
"@lsp.typemod.variable.deprecated",
"@lsp.typemod.variable.readonly",
"@lsp.typemod.parameter.readonly",
"@lsp.typemod.property.readonly",
"@lsp.typemod.variable.static",
"@lsp.typemod.property.static",
}
load_theme()
local issues = audit(groups)
if #issues == 0 then
out("nvim audit: ok (" .. tostring(#groups) .. " groups)")
vim.cmd("qa")
end
err("nvim audit: " .. tostring(#issues) .. " issue(s)")
for _, issue in ipairs(issues) do
err(issue)
end
vim.cmd("cquit")

View File

@@ -82,6 +82,12 @@ function M.load()
WildMenu = { fg = p.void, bg = p.tech },
Pmenu = { fg = p.text, bg = p.panel },
PmenuSel = { fg = p.ink, bg = p.razor, bold = true }, -- Red Menu Selection
PmenuKind = { fg = p.dim, bg = p.panel },
PmenuKindSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuExtra = { fg = p.dim, bg = p.panel },
PmenuExtraSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuMatch = { fg = p.tech, bg = p.panel, bold = true },
PmenuMatchSel = { fg = p.ink, bg = p.razor, bold = true },
PmenuSbar = { bg = p.panel },
PmenuThumb = { bg = p.stealth },
ErrorMsg = { fg = p.alert },
@@ -149,6 +155,10 @@ function M.load()
LspReferenceWrite = { bg = p.panel, bold = true },
LspSignatureActiveParameter = { fg = p.void, bg = p.tech, bold = true },
LspInlayHint = { fg = p.dim, bg = p.panel },
LspCodeLens = { fg = p.dim },
LspCodeLensSeparator = { fg = p.stealth },
LspInfoBorder = { fg = p.border, bg = p.panel },
LspInfoTitle = { fg = p.dim, bg = p.panel },
-- DIAGNOSTICS -----------------------------------------------------------
DiagnosticError = { fg = p.alert },
@@ -282,10 +292,29 @@ function M.load()
["@text"] = "Normal",
["@text.title"] = "Title",
["@markup.heading"] = "Title",
["@markup.heading.1"] = "Title",
["@markup.heading.2"] = "Title",
["@markup.heading.3"] = "Title",
["@markup.heading.4"] = "Title",
["@markup.heading.5"] = "Title",
["@markup.heading.6"] = "Title",
["@markup.link"] = "ApexMarkupLink",
["@markup.link.label"] = "ApexMarkupLink",
["@markup.link.url"] = "ApexMarkupLink",
["@markup.strong"] = "ApexMarkupStrong",
["@markup.italic"] = "ApexMarkupItalic",
["@markup.strikethrough"] = "DiagnosticDeprecated",
["@markup.underline"] = "Underlined",
["@markup.raw"] = "String",
["@markup.raw.block"] = "String",
["@markup.raw.delimiter"] = "Delimiter",
["@markup.quote"] = "Comment",
["@markup.list"] = "Delimiter",
["@markup.list.checked"] = "String",
["@markup.list.unchecked"] = "Comment",
["@markup.math"] = "Constant",
["@markup.environment"] = "Type",
["@markup.environment.name"] = "Type",
["@type"] = "Type",
["@type.builtin"] = "Type",
["@type.definition"] = "Type",
@@ -320,6 +349,12 @@ function M.load()
["@lsp.type.variable"] = "Identifier",
["@lsp.mod.deprecated"] = "DiagnosticDeprecated",
["@lsp.mod.abstract"] = "Type",
["@lsp.mod.declaration"] = "Keyword",
["@lsp.mod.defaultLibrary"] = "Constant",
["@lsp.mod.definition"] = "Keyword",
["@lsp.mod.documentation"] = "Comment",
["@lsp.mod.modification"] = "Operator",
["@lsp.mod.readonly"] = "Constant",
["@lsp.mod.static"] = "Constant",
["@lsp.mod.async"] = "Keyword",