-- Takemi — matched to ~/.config/quickshell/config/Theme.qml and -- ~/.config/alacritty/takemi.toml. -- -- Same rules as the shell: near-black ground, white text, crimson as the only -- saturated colour. Crimson always means one of two things and never anything -- else — this construct is load-bearing (keyword, type, active), or it is -- wrong (error, diff-delete). Everything else is white, grey, or a hue pulled -- so far down it reads as grey with a temperature. -- -- Syntax needs more separation than a shell bar does, so the muted ANSI hues -- from takemi.toml do survive here. They are deliberately dull. If a token -- catches your eye and it isn't red, the palette has drifted. local M = {} local p = { ink = "#000000", base = "#0a0a0c", mantle = "#0d0d10", surface = "#141418", surface_alt = "#1c1c22", overlay = "#26262e", outline = "#3a3a44", text = "#ffffff", subtext = "#c8c8ce", muted = "#6b6b70", faint = "#4a4a52", -- THE KNOB. Keep in step with `accent` in Theme.qml and `$accent` in -- hypr/modules/takemi.conf. accent = "#ff2d40", accent_soft = "#ff6b78", accent_dim = "#8f1826", accent_bg = "#2a1016", -- crimson washed into the ground, for line/diff fills green = "#7f9b6a", green_br = "#9bb886", green_bg = "#161c14", yellow = "#d6a24a", yellow_br = "#f0c070", yellow_bg = "#221a10", blue = "#6f7d99", blue_br = "#8d9bb8", blue_bg = "#14181f", magenta = "#c0566d", magenta_br = "#e07a8e", cyan = "#7f9aa0", cyan_br = "#9db8bd", } M.palette = p local function hl(groups) for name, spec in pairs(groups) do vim.api.nvim_set_hl(0, name, spec) end end function M.load(opts) opts = opts or {} local transparent = opts.transparent or false local bg = transparent and "NONE" or p.base vim.cmd("hi clear") if vim.fn.exists("syntax_on") == 1 then vim.cmd("syntax reset") end vim.o.background = "dark" vim.g.colors_name = "takemi" -- :terminal and anything that reads terminal_color_*. Mirrors takemi.toml -- slot for slot so a shell inside nvim looks like a shell outside it. local ansi = { p.surface, p.accent, p.green, p.yellow, p.blue, p.magenta, p.cyan, p.subtext, p.outline, p.accent_soft, p.green_br, p.yellow_br, p.blue_br, p.magenta_br, p.cyan_br, p.text, } for i, c in ipairs(ansi) do vim.g["terminal_color_" .. (i - 1)] = c end hl({ -- ---------------------------------------------------------------- editor Normal = { fg = p.text, bg = bg }, NormalNC = { fg = p.subtext, bg = bg }, NormalFloat = { fg = p.text, bg = p.surface }, -- Floats get a hard crimson keyline, not a soft border. Same move as the -- shell's panels. FloatBorder = { fg = p.accent, bg = p.surface }, FloatTitle = { fg = p.ink, bg = p.accent, bold = true }, FloatFooter = { fg = p.muted, bg = p.surface }, Cursor = { fg = p.ink, bg = p.accent }, lCursor = { fg = p.ink, bg = p.accent }, CursorIM = { fg = p.ink, bg = p.accent }, TermCursor = { fg = p.ink, bg = p.accent }, CursorLine = { bg = p.surface }, CursorColumn = { bg = p.surface }, ColorColumn = { bg = p.mantle }, -- The current line number is crimson: it is the one "you are here" signal -- in the buffer, which is exactly what the accent is for. CursorLineNr = { fg = p.accent, bold = true }, LineNr = { fg = p.faint }, LineNrAbove = { fg = p.faint }, LineNrBelow = { fg = p.faint }, SignColumn = { fg = p.muted, bg = bg }, FoldColumn = { fg = p.faint, bg = bg }, Folded = { fg = p.muted, bg = p.surface }, -- Selection is a solid crimson block with the text punched out, matching -- [colors.selection] in takemi.toml. Visual = { fg = p.ink, bg = p.accent }, VisualNOS = { fg = p.ink, bg = p.accent_dim }, Search = { fg = p.ink, bg = p.subtext }, IncSearch = { fg = p.ink, bg = p.accent }, CurSearch = { fg = p.ink, bg = p.accent }, Substitute = { fg = p.ink, bg = p.accent_soft }, MatchParen = { fg = p.accent, bold = true, underline = true }, -- Splits are a black keyline, never a grey gutter. WinSeparator = { fg = p.ink, bg = bg }, VertSplit = { fg = p.ink, bg = bg }, Pmenu = { fg = p.subtext, bg = p.surface }, PmenuSel = { fg = p.ink, bg = p.accent, bold = true }, PmenuKind = { fg = p.blue, bg = p.surface }, PmenuKindSel = { fg = p.ink, bg = p.accent }, PmenuExtra = { fg = p.muted, bg = p.surface }, PmenuExtraSel = { fg = p.ink, bg = p.accent }, PmenuSbar = { bg = p.surface_alt }, PmenuThumb = { bg = p.accent }, PmenuMatch = { fg = p.accent, bold = true }, PmenuMatchSel = { fg = p.ink, bg = p.accent, bold = true }, WildMenu = { fg = p.ink, bg = p.accent }, StatusLine = { fg = p.subtext, bg = p.surface }, StatusLineNC = { fg = p.muted, bg = p.mantle }, TabLine = { fg = p.muted, bg = p.mantle }, TabLineFill = { bg = p.mantle }, TabLineSel = { fg = p.ink, bg = p.accent, bold = true }, WinBar = { fg = p.subtext, bg = bg, bold = true }, WinBarNC = { fg = p.muted, bg = bg }, MsgArea = { fg = p.subtext }, MsgSeparator = { fg = p.ink, bg = p.surface }, ModeMsg = { fg = p.accent, bold = true }, MoreMsg = { fg = p.text, bold = true }, Question = { fg = p.text }, ErrorMsg = { fg = p.accent, bold = true }, WarningMsg = { fg = p.yellow }, Title = { fg = p.text, bold = true }, Directory = { fg = p.text, bold = true }, Conceal = { fg = p.muted }, NonText = { fg = p.outline }, EndOfBuffer = { fg = bg == "NONE" and p.outline or bg }, SpecialKey = { fg = p.outline }, Whitespace = { fg = p.surface_alt }, QuickFixLine = { bg = p.surface_alt, bold = true }, SpellBad = { sp = p.accent, undercurl = true }, SpellCap = { sp = p.yellow, undercurl = true }, SpellLocal = { sp = p.cyan, undercurl = true }, SpellRare = { sp = p.magenta, undercurl = true }, -- ---------------------------------------------------------------- syntax -- Crimson is spent only on the words that structure the program. Comment = { fg = p.muted, italic = true }, Constant = { fg = p.subtext }, String = { fg = p.green }, Character = { fg = p.green }, Number = { fg = p.yellow }, Boolean = { fg = p.accent_soft }, Float = { fg = p.yellow }, Identifier = { fg = p.text }, Function = { fg = p.text, bold = true }, Statement = { fg = p.accent }, Conditional = { fg = p.accent }, Repeat = { fg = p.accent }, Label = { fg = p.accent }, Operator = { fg = p.subtext }, Keyword = { fg = p.accent }, Exception = { fg = p.accent }, PreProc = { fg = p.magenta }, Include = { fg = p.accent }, Define = { fg = p.magenta }, Macro = { fg = p.magenta }, PreCondit = { fg = p.magenta }, Type = { fg = p.accent_soft }, StorageClass = { fg = p.accent }, Structure = { fg = p.accent_soft }, Typedef = { fg = p.accent_soft }, Special = { fg = p.cyan }, SpecialChar = { fg = p.cyan_br }, Tag = { fg = p.accent }, Delimiter = { fg = p.muted }, SpecialComment = { fg = p.subtext, italic = true }, Debug = { fg = p.accent }, Underlined = { underline = true }, Ignore = { fg = p.faint }, Error = { fg = p.accent, bold = true }, Todo = { fg = p.ink, bg = p.accent, bold = true }, Added = { fg = p.green }, Changed = { fg = p.yellow }, Removed = { fg = p.accent }, -- ------------------------------------------------------------ treesitter ["@variable"] = { fg = p.text }, ["@variable.builtin"] = { fg = p.accent_soft, italic = true }, ["@variable.parameter"] = { fg = p.subtext, italic = true }, ["@variable.member"] = { fg = p.blue_br }, ["@constant"] = { fg = p.subtext }, ["@constant.builtin"] = { fg = p.accent_soft }, ["@constant.macro"] = { fg = p.magenta }, ["@module"] = { fg = p.subtext }, ["@label"] = { fg = p.accent }, ["@string"] = { fg = p.green }, ["@string.escape"] = { fg = p.cyan_br, bold = true }, ["@string.special"] = { fg = p.cyan }, ["@string.special.url"] = { fg = p.cyan, underline = true }, ["@character"] = { fg = p.green }, ["@number"] = { fg = p.yellow }, ["@boolean"] = { fg = p.accent_soft }, ["@float"] = { fg = p.yellow }, ["@function"] = { fg = p.text, bold = true }, ["@function.builtin"] = { fg = p.text, bold = true, italic = true }, ["@function.macro"] = { fg = p.magenta, bold = true }, ["@function.method"] = { fg = p.text, bold = true }, ["@constructor"] = { fg = p.accent_soft }, ["@keyword"] = { fg = p.accent }, ["@keyword.function"] = { fg = p.accent }, ["@keyword.operator"] = { fg = p.accent }, ["@keyword.return"] = { fg = p.accent, bold = true }, ["@keyword.import"] = { fg = p.accent }, ["@keyword.exception"] = { fg = p.accent }, ["@keyword.conditional"] = { fg = p.accent }, ["@keyword.repeat"] = { fg = p.accent }, ["@operator"] = { fg = p.subtext }, ["@punctuation.delimiter"] = { fg = p.muted }, ["@punctuation.bracket"] = { fg = p.muted }, ["@punctuation.special"] = { fg = p.accent }, ["@type"] = { fg = p.accent_soft }, ["@type.builtin"] = { fg = p.accent_soft, italic = true }, ["@type.definition"] = { fg = p.accent_soft }, ["@attribute"] = { fg = p.magenta }, ["@property"] = { fg = p.blue_br }, ["@comment"] = { fg = p.muted, italic = true }, ["@comment.todo"] = { fg = p.ink, bg = p.accent, bold = true }, ["@comment.note"] = { fg = p.ink, bg = p.subtext, bold = true }, ["@comment.warning"] = { fg = p.ink, bg = p.yellow, bold = true }, ["@comment.error"] = { fg = p.ink, bg = p.accent, bold = true }, ["@tag"] = { fg = p.accent }, ["@tag.builtin"] = { fg = p.accent }, ["@tag.attribute"] = { fg = p.blue_br, italic = true }, ["@tag.delimiter"] = { fg = p.muted }, ["@diff.plus"] = { fg = p.green }, ["@diff.minus"] = { fg = p.accent }, ["@diff.delta"] = { fg = p.yellow }, -- markdown / prose ["@markup.heading"] = { fg = p.text, bold = true }, ["@markup.heading.1"] = { fg = p.accent, bold = true }, ["@markup.heading.2"] = { fg = p.text, bold = true }, ["@markup.heading.3"] = { fg = p.subtext, bold = true }, ["@markup.heading.4"] = { fg = p.subtext }, ["@markup.heading.5"] = { fg = p.muted }, ["@markup.heading.6"] = { fg = p.muted }, ["@markup.strong"] = { fg = p.text, bold = true }, ["@markup.italic"] = { italic = true }, ["@markup.strikethrough"] = { strikethrough = true }, ["@markup.underline"] = { underline = true }, ["@markup.link"] = { fg = p.accent }, ["@markup.link.url"] = { fg = p.cyan, underline = true }, ["@markup.link.label"] = { fg = p.accent }, ["@markup.raw"] = { fg = p.green }, ["@markup.raw.block"] = { fg = p.subtext, bg = p.surface }, ["@markup.quote"] = { fg = p.muted, italic = true }, ["@markup.list"] = { fg = p.accent }, ["@markup.list.checked"] = { fg = p.green }, ["@markup.list.unchecked"] = { fg = p.muted }, -- ------------------------------------------------------------------- lsp ["@lsp.type.class"] = { link = "@type" }, ["@lsp.type.enum"] = { link = "@type" }, ["@lsp.type.interface"] = { link = "@type" }, ["@lsp.type.struct"] = { link = "@type" }, ["@lsp.type.namespace"] = { link = "@module" }, ["@lsp.type.parameter"] = { link = "@variable.parameter" }, ["@lsp.type.property"] = { link = "@property" }, ["@lsp.type.variable"] = { link = "@variable" }, ["@lsp.type.enumMember"] = { link = "@constant" }, ["@lsp.type.decorator"] = { link = "@attribute" }, ["@lsp.type.macro"] = { link = "@function.macro" }, ["@lsp.mod.deprecated"] = { strikethrough = true }, ["@lsp.mod.readonly"] = { link = "@constant" }, LspReferenceText = { bg = p.surface_alt }, LspReferenceRead = { bg = p.surface_alt }, LspReferenceWrite = { bg = p.surface_alt, underline = true }, LspSignatureActiveParameter = { fg = p.ink, bg = p.accent, bold = true }, LspInlayHint = { fg = p.faint, bg = p.mantle, italic = true }, LspCodeLens = { fg = p.faint, italic = true }, LspInfoBorder = { fg = p.accent, bg = p.surface }, -- Diagnostics. Error is crimson because crimson also means "wrong"; warn -- and hint stay dull so an error is never one of four equal shouts. DiagnosticError = { fg = p.accent }, DiagnosticWarn = { fg = p.yellow }, DiagnosticInfo = { fg = p.blue_br }, DiagnosticHint = { fg = p.cyan }, DiagnosticOk = { fg = p.green }, DiagnosticVirtualTextError = { fg = p.accent, bg = p.accent_bg }, DiagnosticVirtualTextWarn = { fg = p.yellow, bg = p.yellow_bg }, DiagnosticVirtualTextInfo = { fg = p.blue_br, bg = p.blue_bg }, DiagnosticVirtualTextHint = { fg = p.cyan, bg = p.blue_bg }, DiagnosticVirtualTextOk = { fg = p.green, bg = p.green_bg }, DiagnosticUnderlineError = { sp = p.accent, undercurl = true }, DiagnosticUnderlineWarn = { sp = p.yellow, undercurl = true }, DiagnosticUnderlineInfo = { sp = p.blue_br, undercurl = true }, DiagnosticUnderlineHint = { sp = p.cyan, undercurl = true }, DiagnosticUnderlineOk = { sp = p.green, undercurl = true }, DiagnosticDeprecated = { sp = p.muted, strikethrough = true }, DiagnosticUnnecessary = { fg = p.faint }, -- ------------------------------------------------------------------ diff DiffAdd = { fg = p.green_br, bg = p.green_bg }, DiffChange = { bg = p.yellow_bg }, DiffDelete = { fg = p.accent, bg = p.accent_bg }, DiffText = { fg = p.yellow_br, bg = p.surface_alt }, -- --------------------------------------------------------------- gitsigns GitSignsAdd = { fg = p.green }, GitSignsChange = { fg = p.yellow }, GitSignsDelete = { fg = p.accent }, GitSignsAddNr = { fg = p.green }, GitSignsChangeNr = { fg = p.yellow }, GitSignsDeleteNr = { fg = p.accent }, GitSignsAddLn = { bg = p.green_bg }, GitSignsChangeLn = { bg = p.yellow_bg }, GitSignsDeleteLn = { bg = p.accent_bg }, GitSignsCurrentLineBlame = { fg = p.faint, italic = true }, -- --------------------------------------------------------------- blink.cmp BlinkCmpMenu = { fg = p.subtext, bg = p.surface }, BlinkCmpMenuBorder = { fg = p.accent, bg = p.surface }, BlinkCmpMenuSelection = { fg = p.ink, bg = p.accent, bold = true }, BlinkCmpScrollBarThumb = { bg = p.accent }, BlinkCmpScrollBarGutter = { bg = p.surface_alt }, BlinkCmpLabel = { fg = p.subtext }, BlinkCmpLabelDeprecated = { fg = p.muted, strikethrough = true }, BlinkCmpLabelMatch = { fg = p.accent, bold = true }, BlinkCmpLabelDetail = { fg = p.muted }, BlinkCmpLabelDescription = { fg = p.muted }, BlinkCmpKind = { fg = p.blue_br }, BlinkCmpSource = { fg = p.faint }, BlinkCmpDoc = { fg = p.subtext, bg = p.surface }, BlinkCmpDocBorder = { fg = p.accent, bg = p.surface }, BlinkCmpDocSeparator = { fg = p.outline, bg = p.surface }, BlinkCmpSignatureHelp = { fg = p.subtext, bg = p.surface }, BlinkCmpSignatureHelpBorder = { fg = p.accent, bg = p.surface }, BlinkCmpSignatureHelpActiveParameter = { fg = p.ink, bg = p.accent, bold = true }, BlinkCmpGhostText = { fg = p.faint, italic = true }, -- --------------------------------------------------------------- which-key WhichKey = { fg = p.accent, bold = true }, WhichKeyGroup = { fg = p.text, bold = true }, WhichKeyDesc = { fg = p.subtext }, WhichKeySeparator = { fg = p.faint }, WhichKeyFloat = { bg = p.surface }, WhichKeyBorder = { fg = p.accent, bg = p.surface }, WhichKeyTitle = { fg = p.ink, bg = p.accent, bold = true }, WhichKeyValue = { fg = p.muted }, -- ------------------------------------------------------------------- mini MiniIconsRed = { fg = p.accent }, MiniIconsOrange = { fg = p.accent_soft }, MiniIconsYellow = { fg = p.yellow }, MiniIconsGreen = { fg = p.green }, MiniIconsCyan = { fg = p.cyan }, MiniIconsBlue = { fg = p.blue_br }, MiniIconsPurple = { fg = p.magenta }, MiniIconsGrey = { fg = p.subtext }, MiniStatuslineModeNormal = { fg = p.ink, bg = p.text, bold = true }, MiniStatuslineModeInsert = { fg = p.ink, bg = p.accent, bold = true }, MiniStatuslineModeVisual = { fg = p.ink, bg = p.accent_soft, bold = true }, MiniStatuslineModeReplace = { fg = p.ink, bg = p.yellow, bold = true }, MiniStatuslineModeCommand = { fg = p.ink, bg = p.subtext, bold = true }, MiniStatuslineModeOther = { fg = p.ink, bg = p.cyan, bold = true }, MiniStatuslineDevinfo = { fg = p.subtext, bg = p.surface_alt }, MiniStatuslineFilename = { fg = p.subtext, bg = p.surface }, MiniStatuslineInactive = { fg = p.muted, bg = p.mantle }, MiniPickBorder = { fg = p.accent, bg = p.surface }, MiniPickMatchCurrent = { fg = p.ink, bg = p.accent }, MiniPickMatchRanges = { fg = p.accent, bold = true }, MiniPickPrompt = { fg = p.accent, bg = p.surface, bold = true }, -- ------------------------------------------------------- render-markdown -- Only H1 gets the crimson bar. Deeper headings step down through greys so -- a document has one focal point, the same way a panel does. RenderMarkdownH1Bg = { fg = p.ink, bg = p.accent, bold = true }, RenderMarkdownH2Bg = { fg = p.ink, bg = p.text, bold = true }, RenderMarkdownH3Bg = { fg = p.text, bg = p.overlay, bold = true }, RenderMarkdownH4Bg = { fg = p.subtext, bg = p.surface_alt }, RenderMarkdownH5Bg = { fg = p.subtext, bg = p.surface }, RenderMarkdownH6Bg = { fg = p.muted, bg = p.surface }, RenderMarkdownCode = { bg = p.mantle }, RenderMarkdownCodeInline = { fg = p.green, bg = p.surface }, RenderMarkdownBullet = { fg = p.accent }, RenderMarkdownQuote = { fg = p.outline }, RenderMarkdownDash = { fg = p.outline }, RenderMarkdownLink = { fg = p.cyan }, RenderMarkdownTableHead = { fg = p.accent }, RenderMarkdownTableRow = { fg = p.muted }, RenderMarkdownSuccess = { fg = p.green }, RenderMarkdownInfo = { fg = p.blue_br }, RenderMarkdownHint = { fg = p.cyan }, RenderMarkdownWarn = { fg = p.yellow }, RenderMarkdownError = { fg = p.accent }, -- --------------------------------------------------------------- misc plugins ToggleTerm1FloatBorder = { fg = p.accent, bg = p.surface }, MasonHeader = { fg = p.ink, bg = p.accent, bold = true }, MasonHighlight = { fg = p.accent }, MasonHighlightBlock = { fg = p.ink, bg = p.accent }, MasonHighlightBlockBold = { fg = p.ink, bg = p.accent, bold = true }, MasonMuted = { fg = p.muted }, MasonMutedBlock = { fg = p.subtext, bg = p.surface_alt }, MasonError = { fg = p.accent }, NvimTreeNormal = { fg = p.subtext, bg = p.mantle }, NvimTreeRootFolder = { fg = p.accent, bold = true }, NvimTreeFolderIcon = { fg = p.subtext }, NvimTreeOpenedFile = { fg = p.text, bold = true }, NvimTreeGitDirty = { fg = p.yellow }, NvimTreeGitNew = { fg = p.green }, NvimTreeGitDeleted = { fg = p.accent }, NvimTreeIndentMarker = { fg = p.surface_alt }, NvimTreeWinSeparator = { fg = p.ink, bg = p.mantle }, }) end -- Lualine theme. Mode is the only place the bar carries hue, and it is the -- accent in the modes where you can actually change the buffer. function M.lualine() local outer = function(c) return { fg = p.ink, bg = c, gui = "bold" } end local mid = { fg = p.subtext, bg = p.surface_alt } local inner = { fg = p.muted, bg = p.surface } return { normal = { a = outer(p.text), b = mid, c = inner }, insert = { a = outer(p.accent), b = mid, c = inner }, visual = { a = outer(p.accent_soft), b = mid, c = inner }, replace = { a = outer(p.yellow), b = mid, c = inner }, command = { a = outer(p.subtext), b = mid, c = inner }, terminal = { a = outer(p.cyan), b = mid, c = inner }, inactive = { a = { fg = p.muted, bg = p.mantle }, b = { fg = p.muted, bg = p.mantle }, c = { fg = p.faint, bg = p.mantle }, }, } end return M