Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/manual/analyze_color_usage.lua

Raw
-- Analyze which nugu palette colors are used in highlight groups
-- and map them to wezterm ANSI/indexed slots.
-- Usage: :luafile tests/manual/analyze_color_usage.lua

local palette = require 'bugabinga.nugu.palette'

-- Build reverse map: hex -> semantic name
local hex_to_name = {}
for k, v in pairs(palette) do
  hex_to_name[v] = k
end

-- Current wezterm mapping (from wezterm/nugu/init.lua)
local ansi_map = {
  [0]  = 'content_backdrop',
  [1]  = 'error',
  [2]  = 'content_focus',
  [3]  = 'warning',
  [4]  = 'content_important_local',
  [5]  = 'content_accent',
  [6]  = 'content_unfocus',
  [7]  = 'content_normal',
  [8]  = 'content_minor',
  [9]  = 'error',              -- duplicate
  [10] = 'ui_unfocus',
  [11] = 'ui_backdrop',
  [12] = 'content_important_global',
  [13] = 'ui_accent',
  [14] = 'ui_important_local',
  [15] = 'ui_important_global',
}

-- Build name -> slot
local name_to_slot = {}
for slot, name in pairs(ansi_map) do
  name_to_slot[name] = slot
end

-- Collect all unique fg/bg/sp colors used
local all_hl = vim.api.nvim_get_hl(0, {})
local color_usage = {} -- hex -> { groups={}, as={fg=0, bg=0, sp=0} }

for name, hl in pairs(all_hl) do
  for _, prop in ipairs { 'fg', 'bg', 'sp' } do
    if hl[prop] then
      local hex = string.format('#%06x', hl[prop])
      if not color_usage[hex] then
        color_usage[hex] = { groups = {}, as = { fg = 0, bg = 0, sp = 0 } }
      end
      color_usage[hex].as[prop] = color_usage[hex].as[prop] + 1
      color_usage[hex].groups[#color_usage[hex].groups + 1] = name .. '.' .. prop
    end
  end
end

print('=== Color Usage Analysis ===')
print('')

-- Sort by total usage
local sorted = {}
for hex, info in pairs(color_usage) do
  local total = info.as.fg + info.as.bg + info.as.sp
  sorted[#sorted + 1] = { hex = hex, info = info, total = total }
end
table.sort(sorted, function(a, b) return a.total > b.total end)

local covered = 0
local uncovered = 0
local uncovered_colors = {}

for _, entry in ipairs(sorted) do
  local hex = entry.hex
  local name = hex_to_name[hex] or 'UNKNOWN'
  local slot = name_to_slot[name]
  local status = slot and ('slot ' .. slot) or 'UNMAPPED'
  print(string.format('%-30s  %-25s  fg=%-3d bg=%-3d sp=%-3d  total=%-3d  %s',
    hex, name, entry.info.as.fg, entry.info.as.bg, entry.info.as.sp, entry.total, status))
  if slot then
    covered = covered + entry.total
  else
    uncovered = uncovered + entry.total
    uncovered_colors[#uncovered_colors + 1] = { hex = hex, name = name, total = entry.total }
  end
end

print('')
print(string.format('Covered by ANSI:     %d references', covered))
print(string.format('Not in ANSI palette: %d references', uncovered))
print('')

print('=== Unmapped colors ===')
for _, c in ipairs(uncovered_colors) do
  print(string.format('  %-30s  (%s)  used %d times', c.hex, c.name, c.total))
end

print('')
print('=== Proposed indexed slot assignment ===')
local next_slot = 16
for _, c in ipairs(uncovered_colors) do
  print(string.format('  indexed[%d] = %s  (%s)', next_slot, c.hex, c.name))
  next_slot = next_slot + 1
end

-- Also check: can we reclaim slot 9?
print('')
print('=== Slot 9 reclaim ===')
print('Slot 9 currently duplicates error (slot 1).')
print('Can be reassigned to: ' .. uncovered_colors[1].name .. ' (' .. uncovered_colors[1].hex .. ')')