Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/manual/compare_highlights.lua

Raw
--- Compare cterm highlight snapshot against the original hex baseline.
--- Verifies that every ctermfg/ctermbg index matches the expected nugu color.
--- Usage: nvim --headless /tmp/nugu_compare.txt -c "luafile tests/manual/compare_highlights.lua" -c "qa!"

-- The original hex baseline (captured before the cterm change)
local baseline_path = '/tmp/nugu_highlights_baseline.txt'

-- nugu color mapping: cterm index -> { dark_hex, semantic_name }
local slot_info = {
  [0]  = { '#121212', 'content_backdrop' },
  [1]  = { '#e46479', 'error' },
  [2]  = { '#7ba1aa', 'content_focus' },
  [3]  = { '#9e9a69', 'warning' },
  [4]  = { '#b59ae4', 'content_important_local' },
  [5]  = { '#d151d1', 'content_accent' },
  [6]  = { '#5d5d5d', 'content_unfocus' },
  [7]  = { '#ededed', 'content_normal' },
  [8]  = { '#8b8b8b', 'content_minor' },
  [9]  = { '#3ec5dd', 'info' },
  [10] = { '#6f6f6f', 'ui_unfocus' },
  [11] = { '#242424', 'ui_backdrop' },
  [12] = { '#dfd3f3', 'content_important_global' },
  [13] = { '#d86dd8', 'ui_accent' },
  [14] = { '#c9b6eb', 'ui_important_local' },
  [15] = { '#f3effb', 'ui_important_global' },
  [16] = { '#ed5eed', 'debug' },
  [17] = { '#dbdbdb', 'ui_normal' },
  [18] = { '#9d9d9d', 'ui_minor' },
  [19] = { '#9aabae', 'ui_focus' },
}

-- Build hex -> slot reverse map (lowercase for comparison)
local hex_to_slot = {}
for idx, info in pairs(slot_info) do
  hex_to_slot[info[1]:lower()] = idx
end

-- Parse baseline file: group_name -> { fg=hex, bg=hex, sp=hex, bold=bool, ... }
local function parse_file(path)
  local f = io.open(path, 'r')
  if not f then return {} end
  local groups = {}
  for line in f:lines() do
    if not line:match '^%-%-' and line ~= '' then
      local name, rest = line:match '^(%S+) (.+)$'
      if name then
        local props = {}
        for token in rest:gmatch '%S+' do
          local k, v = token:match '^(%a+)=(.+)$'
          if k then
            props[k] = v
          else
            props[token] = true
          end
        end
        groups[name] = props
      end
    end
  end
  f:close()
  return groups
end

local baseline = parse_file(baseline_path)
local cterm = parse_file('/tmp/nugu_highlights_cterm.txt')

local outpath = vim.fn.argv()[1] or '/tmp/nugu_compare.txt'
local lines = {
  '-- Highlight comparison: hex baseline vs cterm',
  '-- ' .. os.date '!%Y-%m-%dT%H:%M:%SZ',
  '',
}

local match_count = 0
local mismatch_count = 0
local missing_count = 0
local skipped_count = 0

-- Check all groups that exist in the baseline (nugu-defined groups)
for name, base_props in pairs(baseline) do
  local ct = cterm[name]
  if not ct then
    missing_count = missing_count + 1
    lines[#lines + 1] = 'MISSING: ' .. name
  else
    -- Compare fg
    if base_props.fg and ct.ctermfg then
      local base_hex = base_props.fg:lower()
      local slot = tonumber(ct.ctermfg)
      local expected_hex = slot_info[slot] and slot_info[slot][1]:lower()
      if base_hex == expected_hex then
        match_count = match_count + 1
      elseif hex_to_slot[base_hex] then
        mismatch_count = mismatch_count + 1
        lines[#lines + 1] = string.format(
          'MISMATCH FG: %s  baseline=%s (slot %d)  cterm=%s (slot %d, %s)',
          name, base_hex, hex_to_slot[base_hex],
          ct.ctermfg, slot, expected_hex or '?'
        )
      else
        -- baseline has a hex that isn't in our palette (built-in default)
        skipped_count = skipped_count + 1
      end
    end

    -- Compare bg
    if base_props.bg and ct.ctermbg then
      local base_hex = base_props.bg:lower()
      local slot = tonumber(ct.ctermbg)
      local expected_hex = slot_info[slot] and slot_info[slot][1]:lower()
      if base_hex == expected_hex then
        match_count = match_count + 1
      elseif hex_to_slot[base_hex] then
        mismatch_count = mismatch_count + 1
        lines[#lines + 1] = string.format(
          'MISMATCH BG: %s  baseline=%s (slot %d)  cterm=%s (slot %d, %s)',
          name, base_hex, hex_to_slot[base_hex],
          ct.ctermbg, slot, expected_hex or '?'
        )
      else
        skipped_count = skipped_count + 1
      end
    end

    -- Check for missing ctermfg when baseline has fg
    if base_props.fg and not ct.ctermfg and not ct.link then
      local base_hex = base_props.fg:lower()
      if hex_to_slot[base_hex] then
        missing_count = missing_count + 1
        lines[#lines + 1] = 'NO CTERMFG: ' .. name .. ' (baseline fg=' .. base_props.fg .. ')'
      end
    end
    if base_props.bg and not ct.ctermbg and not ct.link then
      local base_hex = base_props.bg:lower()
      if hex_to_slot[base_hex] then
        missing_count = missing_count + 1
        lines[#lines + 1] = 'NO CTERMBG: ' .. name .. ' (baseline bg=' .. base_props.bg .. ')'
      end
    end

    -- Compare boolean attributes
    for _, attr in ipairs({ 'bold', 'italic', 'underline', 'undercurl', 'underdouble',
                            'underdotted', 'underdashed', 'strikethrough', 'reverse' }) do
      local base_has = base_props[attr] and true or false
      local ct_has = ct[attr] and true or false
      if base_has ~= ct_has then
        lines[#lines + 1] = string.format('ATTR DIFF: %s  %s baseline=%s cterm=%s',
          name, attr, tostring(base_has), tostring(ct_has))
      end
    end
  end
end

-- Summary
lines[#lines + 1] = ''
lines[#lines + 1] = string.format('Matches:    %d', match_count)
lines[#lines + 1] = string.format('Mismatches: %d', mismatch_count)
lines[#lines + 1] = string.format('Missing:    %d', missing_count)
lines[#lines + 1] = string.format('Skipped:    %d (non-nugu colors)', skipped_count)

local f = assert(io.open(outpath, 'w'))
f:write(table.concat(lines, '\n') .. '\n')
f:close()
print(table.concat(lines, '\n'))