Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/lua/bugabinga/nugu/init.lua

Raw
local N = require 'bugabinga.nugu.palette'
local P = N.tui

local gui_palette = function ()
	return N[vim.o.background == 'light' and 'light' or 'dark']
end

local set_group_properties = function ( self, properties )
	vim.validate( 'properties',               properties,               'table' )
	vim.validate( 'properties.fg',            properties.fg,            'number',  true )
	vim.validate( 'properties.bg',            properties.bg,            'number',  true )
	vim.validate( 'properties.blend',         properties.blend,         'number',  true )
	vim.validate( 'properties.bold',          properties.bold,          'boolean', true )
	vim.validate( 'properties.standout',      properties.standout,      'boolean', true )
	vim.validate( 'properties.underline',     properties.underline,     'boolean', true )
	vim.validate( 'properties.undercurl',     properties.undercurl,     'boolean', true )
	vim.validate( 'properties.underdotted',   properties.underdotted,   'boolean', true )
	vim.validate( 'properties.underdashed',   properties.underdashed,   'boolean', true )
	vim.validate( 'properties.strikethrough', properties.strikethrough, 'boolean', true )
	vim.validate( 'properties.italic',        properties.italic,        'boolean', true )
	vim.validate( 'properties.reverse',       properties.reverse,       'boolean', true )
	vim.validate( 'properties.nocombine',     properties.nocombine,     'boolean', true )
	vim.validate( 'properties.default',       properties.default,       'boolean', true )
	vim.validate( 'properties.force',         properties.force,         'boolean', true )

	for key, value in pairs( properties ) do
		self[key] = value
	end
end

local new_group = function ()
	return setmetatable( {}, {
		__call = set_group_properties,
	} )
end

local add_group = function ( self, key )
	if not self.groups[key] then
		self.groups[key] = new_group()
	end
	return self.groups[key]
end

local link_group = function ( self, key, value )
	local group = add_group( self, key )
	for name, group_link in pairs( self.groups ) do
		if group_link == value then
			group.link = name
			return group
		end
	end
end

local _ = setmetatable( { groups = {} }, {
	__index = add_group,
	__newindex = link_group,
} )

-- editor
_.Normal { fg = P.content_normal, bg = P.content_backdrop }
_.NormalUi { fg = P.ui_normal, bg = P.ui_backdrop }
_.NormalFloat { bg = _.NormalUi.bg }
_.EndOfBuffer { bg = _.Normal.bg }
_.Cursor { fg = P.content_backdrop, bg = P.content_accent }
_.CursorColumn { bg = P.ui_unfocus }
_.CursorLine { bg = P.ui_unfocus }
_.CursorLineNr { fg = P.ui_focus, bg = P.ui_backdrop }
_.CursorLineSign = _.CursorLineNr
_.ColorColumn { fg = P.ui_important_global, bg = _.Normal.bg }
_.Conceal { fg = P.content_focus, bg = _.Normal.bg }
_.Directory { fg = _.Normal.fg }
_.MatchParen { bg = P.ui_unfocus, bold = true }
_.LineNr { fg = P.ui_focus, bg = P.content_backdrop }
_.LineNrAbove { fg = P.ui_minor, bg = P.content_backdrop }
_.LineNrBelow { fg = P.ui_minor, bg = P.content_backdrop }
_.FoldColumn = _.LineNrAbove
_.SignColumn = _.LineNrAbove
_.NonText { fg = P.content_unfocus }
_.Whitespace = _.NonText
_.SpecialKey { fg = P.error, bg = P.content_unfocus, bold = true }
_.Visual { bg = P.content_unfocus }
_.VisualNOS { bg = P.ui_unfocus }
_.Search { fg = P.content_backdrop, bg = P.content_focus }
_.IncSearch { fg = P.content_backdrop, bg = P.content_unfocus }
_.CurSearch { fg = P.content_backdrop, bg = P.content_important_local }
_.QuickFixLine = _.PmenuSel
_.Folded = _.Conceal

-- floats
_.FloatBorder { fg = P.ui_accent, bg = _.NormalFloat.bg }
_.FloatBorderCorner { fg = P.ui_accent, bg = _.Normal.bg }
_.FloatShadow { bg = P.content_unfocus, blend = 80 }
_.FloatShadowThrough { bg = P.content_unfocus, blend = 100 }
_.FloatTitle { fg = _.FloatBorder.fg, bg = _.FloatBorder.bg, bold = true }

-- ui chrome
_.StatusLine = _.NormalUi
_.StatusLineNC { fg = P.ui_minor, bg = _.StatusLine.bg }
_.WinBar { fg = P.ui_focus, bg = _.StatusLine.bg }
_.WinBarNC { fg = P.ui_minor, bg = _.StatusLine.bg }
_.TabLine = _.StatusLine
_.TabLineFill = _.StatusLine
_.TabLineSel { fg = P.ui_important_global, bg = _.TabLine.bg, bold = true, underline = true }
_.VertSplit { fg = P.ui_important_global }
_.Title { fg = P.content_important_global, bold = true, underline = true }
_.ModeMsg { bold = true }
_.MsgArea = _.NormalUi
_.MsgSeparator = _.NormalUi
_.MoreMsg = _.NormalUi
_.Question { fg = P.ui_important_local, bold = true }
_.WildMenu = _.PmenuSel
_.Debug { fg = P.ui_normal, bg = P.debug, bold = true }

-- menus
_.Pmenu = _.NormalFloat
_.PmenuSel { fg = P.ui_important_local, bg = _.Pmenu.bg, bold = true, underline = true }
_.PmenuSbar { fg = P.ui_minor, bg = _.NormalFloat.bg }
_.PmenuThumb { fg = P.ui_important_local, bg = _.NormalFloat.bg }
_.PmenuMatch { fg = P.content_focus, bold = true }
_.PmenuMatchSel { fg = P.content_focus, bold = true }
_.ComplMatchIns { fg = P.content_accent }
_.PmenuKind { fg = P.ui_minor }
_.PmenuKindSel { fg = P.ui_important_local }

-- cmdline
_.BugabingaCmdlineCursor { fg = P.ui_important_local, bg = P.ui_unfocus, bold = true }
_.CmdlineBorderSearch { fg = P.ui_important_global, bg = _.NormalFloat.bg }
_.CmdlineBorderShell { fg = P.content_focus, bg = _.NormalFloat.bg }
_.CmdlineBorderHelp { fg = P.info, bg = _.NormalFloat.bg }
_.CmdlineBorderLua { fg = P.content_focus, bg = _.NormalFloat.bg }
_.CmdlineBorderInput { fg = P.ui_important_local, bg = _.NormalFloat.bg }
_.CmdlineBorderCmdline { fg = P.ui_minor, bg = _.NormalFloat.bg }
_.CmdlineBorderCornerSearch { fg = _.CmdlineBorderSearch.fg, bg = _.FloatBorderCorner.bg }
_.CmdlineBorderCornerShell { fg = _.CmdlineBorderShell.fg, bg = _.FloatBorderCorner.bg }
_.CmdlineBorderCornerHelp { fg = _.CmdlineBorderHelp.fg, bg = _.FloatBorderCorner.bg }
_.CmdlineBorderCornerLua { fg = _.CmdlineBorderLua.fg, bg = _.FloatBorderCorner.bg }
_.CmdlineBorderCornerInput { fg = _.CmdlineBorderInput.fg, bg = _.FloatBorderCorner.bg }
_.CmdlineBorderCornerCmdline { fg = _.CmdlineBorderCmdline.fg, bg = _.FloatBorderCorner.bg }
_.CmdlineIconSearch { fg = _.CmdlineBorderSearch.fg }
_.CmdlineIconShell { fg = _.CmdlineBorderShell.fg }
_.CmdlineIconHelp { fg = _.CmdlineBorderHelp.fg }
_.CmdlineIconLua { fg = _.CmdlineBorderLua.fg }
_.CmdlineIconInput { fg = _.CmdlineBorderInput.fg }
_.CmdlineIconCmdline { fg = _.CmdlineBorderCmdline.fg }

-- diagnostics
_.DiagnosticError { fg = P.error }
_.DiagnosticWarn { fg = P.warning }
_.DiagnosticInfo { fg = P.info }
_.DiagnosticHint { fg = P.ui_important_local }
_.DiagnosticOk { fg = P.ui_minor }
_.DiagnosticUnnecessary { fg = P.ui_focus }
_.DiagnosticDeprecated { fg = P.ui_important_global, strikethrough = true }
_.DiagnosticVirtualTextError = _.DiagnosticError
_.DiagnosticVirtualTextWarn = _.DiagnosticWarn
_.DiagnosticVirtualTextInfo = _.DiagnosticInfo
_.DiagnosticVirtualTextHint = _.DiagnosticHint
_.DiagnosticVirtualTextOk = _.DiagnosticOk
_.DiagnosticUnderlineError { fg = _.DiagnosticError.fg, underdouble = true }
_.DiagnosticUnderlineWarn { fg = _.DiagnosticWarn.fg, underline = true }
_.DiagnosticUnderlineInfo { fg = _.DiagnosticInfo.fg, underdashed = true }
_.DiagnosticUnderlineHint { fg = _.DiagnosticHint.fg, underdotted = true }
_.DiagnosticUnderlineOk { fg = _.DiagnosticOk.fg }
_.DiagnosticSignError = _.DiagnosticError
_.DiagnosticSignWarn = _.DiagnosticWarn
_.DiagnosticSignInfo = _.DiagnosticInfo
_.DiagnosticSignHint = _.DiagnosticHint
_.DiagnosticSignOk = _.DiagnosticOk

-- messages
_.ErrorMsg { fg = P.error }
_.WarningMsg { fg = P.warning, bold = true }
_.Added { fg = P.content_focus }
_.OkMsg = _.Added
_.Removed { fg = P.error }
_.Changed { fg = P.content_important_local }
_.NvimInternalError { fg = P.error, bg = P.content_backdrop }

-- diff
_.DiffAdd { fg = P.info }
_.DiffDelete { fg = P.error, strikethrough = true }
_.DiffChange { fg = P.warning }
_.DiffText { fg = P.content_backdrop, bg = P.warning, bold = true }

-- spelling
_.SpellBad { fg = P.error, undercurl = true }
_.SpellCap = _.SpellBad
_.SpellLocal = _.SpellBad
_.SpellRare = _.SpellBad

-- misc
_.Comment { fg = P.content_important_global, bold = true, italic = true }
_.NotifyBackground = _.NormalUi
_.CycleBufferFileName { fg = P.ui_accent, bold = true }
_.CycleBufferIcon { fg = P.ui_minor }
_.TextYankPost { fg = P.content_backdrop, bg = P.ui_important_local }
_.SnippetTabstop { bg = P.content_unfocus, underline = true }
_.RedrawDebugClear { fg = P.content_backdrop, bg = P.ui_backdrop }
_.RedrawDebugComposed { fg = P.content_backdrop, bg = P.ui_unfocus }
_.RedrawDebugRecompose { fg = P.content_backdrop, bg = P.error }

-- bugabinga code actions
_.BugabingaCodeActionFixAll = _.DiagnosticWarn
_.BugabingaCodeActionQuickFix = _.DiagnosticHint
_.BugabingaCodeActionRefactor = _.DiagnosticInfo
_.BugabingaCodeActionRefactorExtract = _.DiagnosticInfo
_.BugabingaCodeActionRefactorMove = _.DiagnosticInfo
_.BugabingaCodeActionSource = _.DiagnosticHint
_.BugabingaCodeActionSourceImports = _.DiagnosticHint
_.BugabingaCodeActionDefault = _.DiagnosticHint

-- pivi conversation
-- A user message is the one thing worth finding while scrolling, so it alone
-- carries a background and a solid bar. Everything else stays quiet, and tool
-- work is the quietest.
_.PiviUser { bg = P.ui_backdrop }
_.PiviUserBar { fg = P.content_accent, bold = true }
_.PiviUserLabel { fg = P.content_accent, bold = true }
_.PiviAssistantLabel { fg = P.content_focus }
-- The output recedes furthest; the outcome beside the name stays scannable.
_.PiviTool { fg = P.content_unfocus }
_.PiviToolIcon { fg = P.content_focus }
_.PiviToolOutcome { fg = P.content_minor }
_.PiviError { fg = P.error }
_.PiviErrorIcon { fg = P.error, bold = true }

-- bugabinga debug viewer
_.DbgViewerKind = _.Title
_.DbgViewerTime = _.Comment
_.DbgViewerMessage = _.Normal
_.DbgViewerLocation = _.Comment
_.DbgViewerFilter = _.Search
_.DbgViewerKindIcon = _.DiagnosticInfo

-- lsp
_.LspReferenceText { underline = true }
_.LspReferenceRead = _.LspReferenceText
_.LspReferenceWrite = _.LspReferenceText
_.LspInlayHint { fg = P.content_minor, bg = _.Normal.bg }
_.LspSignatureActiveParameter = _.PmenuSel

-- mini.hipatterns
_.MiniHipatternsFixme { fg = P.ui_backdrop, bg = _.DiagnosticError.fg, bold = true, underline = true }
_.MiniHipatternsHack { fg = P.ui_backdrop, bg = _.DiagnosticWarn.fg, bold = true, underline = true }
_.MiniHipatternsTodo { fg = P.ui_backdrop, bg = _.DiagnosticHint.fg, bold = true, underline = true }
_.MiniHipatternsNote { fg = P.ui_backdrop, bg = _.DiagnosticInfo.fg, bold = true, underline = true }

-- syntax
_.String { fg = P.content_focus, italic = true }
_.Constant = _.String
_.Character = _.String
_.Number = _.String
_.Boolean = _.String
_.Float = _.String
_.Identifier { fg = _.Normal.fg }
_.Function { fg = _.Normal.fg }
_.FunctionDeclaration { fg = _.Function.fg, underline = true }
_.Parameter { fg = P.content_important_local, bold = true }
_.MutableVariable = { fg = _.Parameter.fg, underline = true }
_.Type { fg = _.Identifier.fg }
_.Delimiter { fg = P.content_minor }

_.Statement { fg = P.content_minor }
_.Conditional = _.Statement
_.Repeat = _.Statement
_.Label = _.Statement
_.Operator = _.Statement
_.Keyword = _.Statement
_.Exception = _.Statement
_.StorageClass = _.Statement
_.Structure = _.Statement
_.Typedef = _.Statement

_.PreProc { fg = P.content_important_global, bold = true }
_.Include = _.PreProc
_.Define = _.PreProc
_.Macro = _.PreProc
_.PreCondit = _.PreProc

_.Special { fg = P.content_important_global, bold = true }
_.SpecialChar = _.Special
_.Tag = _.Special
_.SpecialComment = _.Special

_.Underlined { underline = true }
_.Bold { bold = true }
_.Italic { italic = true }
_.Ignore { fg = _.Normal.bg }
_.Error { fg = P.error }
_.Todo { fg = P.content_important_global, bold = true, underdouble = true }

-- treesitter
_['@attribute'] = _.Keyword
_['@boolean'] = _.Boolean
_['@character'] = _.Character
_['@character.special'] = _.SpecialChar
_['@comment'] = _.Comment
_['@conditional'] = _.Conditional
_['@constant'] = _.Constant
_['@constant.builtin'] = _.String
_['@constant.macro'] = _.Define
_['@constructor'] = _.Special
_['@debug'] = _.Debug
_['@define'] = _.Define
_['@exception'] = _.Exception
_['@field'] = _.Identifier
_['@float'] = _.Float
_['@function'] = _.Function
_['@function.builtin'] = _.Special
_['@function.macro'] = _.Macro
_['@include'] = _.Include
_['@keyword'] = _.Keyword
_['@keyword.return'] { fg = _.Keyword.fg, bg = _.Keyword.bg, underline = true, bold = true }
_['@label'] = _.Label
_['@macro'] = _.Macro
_['@method'] = _.Function
_['@namespace'] = _.Function
_['@number'] = _.Number
_['@operator'] = _.Operator
_['@parameter'] = _.Parameter
_['@preproc'] = _.PreProc
_['@property'] = _.Identifier
_['@punctuation'] = _.Delimiter
_['@error'] = _.DiagnosticError
_['@repeat'] = _.Repeat
_['@storageclass'] = _.StorageClass
_['@string'] = _.String
_['@string.escape'] = _.SpecialChar
_['@string.special'] = _.SpecialChar
_['@structure'] = _.Structure
_['@tag'] = _.Tag
_['@text.literal'] = _.Comment
_['@text.reference'] = _.Identifier
_['@text.title'] = _.Title
_['@text.todo'] = _.Todo
_['@text.underline'] = _.Underlined
_['@type'] = _.Type
_['@type.builtin'] = _.Type
_['@type.definition'] = _.Typedef
_['@variable'] = _.Identifier
_['@variable.parameter'] = _.Parameter

_['@markup.raw.block'] { fg = P.content_normal }
_['@markup.raw.block.markdown'] { fg = P.ui_normal }
_['@markup.raw.block.vimdoc'] { fg = P.ui_normal }

-- lsp semantic tokens
_['@lsp.type.class'] = _['@type']
_['@lsp.type.decorator'] = _['@function']
_['@lsp.type.enum'] = _['@type']
_['@lsp.type.enumMember'] = _['@constant']
_['@lsp.type.function'] = _['@function']
_['@lsp.type.interface'] = _['@type']
_['@lsp.type.macro'] = _['@macro']
_['@lsp.type.method'] = _['@method']
_['@lsp.type.modifier'] = _['@keyword']
_['@lsp.type.namespace'] = _['@namespace']
_['@lsp.type.parameter'] = _['@parameter']
_['@lsp.type.property'] = _['@property']
_['@lsp.type.struct'] = _['@structure']
_['@lsp.type.type'] = _['@type']
_['@lsp.type.typeParameter'] = _['@type']
_['@lsp.type.variable'] = _['@variable']
_['@lsp.typemod.function.declaration'] = _.FunctionDeclaration
_['@lsp.typemod.method.declaration'] = _.FunctionDeclaration
_['@lsp.typemod.parameter.declaration'] = _.Parameter

-- cterm attributes that must be mirrored to the cterm table
local cterm_attrs = {
	bold = true,
	italic = true,
	reverse = true,
	standout = true,
	underline = true,
	undercurl = true,
	underdouble = true,
	underdotted = true,
	underdashed = true,
	strikethrough = true,
	nocombine = true,
}

return function ()
	for name, group in pairs( _.groups ) do
		if group.link then
			vim.api.nvim_set_hl( 0, name, { link = group.link, default = group.default } )
		else
			local opts = {}
			local gui = gui_palette()
			if group.fg then
				opts.ctermfg = group.fg
				opts.fg = gui[group.fg]
			end
			if group.bg then
				opts.ctermbg = group.bg
				opts.bg = gui[group.bg]
			end
			if group.fg and ( group.undercurl or group.underdashed or group.underdotted or group.underdouble ) then
				opts.sp = gui[group.fg]
			end
			local ct = {}
			for attr in pairs( cterm_attrs ) do
				if group[attr] then
					ct[attr] = true
					opts[attr] = true
				end
			end
			if next( ct ) then opts.cterm = ct end
			if group.blend then opts.blend = group.blend end
			if group.default then opts.default = group.default end
			if group.force then opts.force = group.force end
			vim.api.nvim_set_hl( 0, name, opts )
		end
	end
end