8000 mini.nvim/lua/mini/hues.lua at main · cosmicbuffalo/mini.nvim · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
1942 lines (1709 loc) · 85.2 KB

hues.lua

File metadata and controls

1942 lines (1709 loc) · 85.2 KB
--- *mini.hues* Generate configurable color scheme
--- *MiniHues*
---
--- MIT License Copyright (c) 2023 Evgeni Chasnovski
---
--- ==============================================================================
---
--- Features:
--- - Required to set two base colors: background and foreground.
--- Their shades and other non-base colors are computed to be as much
--- perceptually different as reasonably possible.
--- See |MiniHues.config| for setup inspiration.
---
--- - Configurable:
--- - Number of hues used for non-base colors (from 0 to 8).
--- - Saturation level ("low", "lowmedium", "medium", "mediumhigh", "high").
--- - Accent color used for some selected UI elements.
--- - Plugin integration (can be selectively enabled for faster startup).
---
--- - Random generator for base colors. See |MiniHues.gen_random_base_colors()|.
--- Powers |randomhue| color scheme.
---
--- - Lua function to compute palette used in color scheme.
--- See |MiniHues.make_palette()|.
---
--- Supported highlight groups:
--- - All built-in UI and syntax groups.
---
--- - Built-in Neovim LSP and diagnostic.
---
--- - Tree-sitter (|treesitter-highlight-groups|).
---
--- - LSP semantic tokens (|lsp-semantic-highlight|).
---
--- - Plugins (either with explicit definition or by verification that default
--- highlighting works appropriately):
--- - 'echasnovski/mini.nvim'
--- - 'akinsho/bufferline.nvim'
--- - 'anuvyklack/hydra.nvim'
--- - 'DanilaMihailov/beacon.nvim'
--- - 'folke/lazy.nvim'
--- - 'folke/noice.nvim'
--- - 'folke/todo-comments.nvim'
--- - 'folke/trouble.nvim'
--- - 'folke/which-key.nvim'
--- - 'ggandor/leap.nvim'
--- - 'glepnir/dashboard-nvim'
--- - 'glepnir/lspsaga.nvim'
--- - 'HiPhish/rainbow-delimiters.nvim'
--- - 'hrsh7th/nvim-cmp'
--- - 'ibhagwan/fzf-lua'
--- - 'justinmk/vim-sneak'
--- - 'kevinhwang91/nvim-bqf'
--- - 'kevinhwang91/nvim-ufo'
--- - 'lewis6991/gitsigns.nvim'
--- - 'lukas-reineke/indent-blankline.nvim'
--- - 'MeanderingProgrammer/render-markdown.nvim'
--- - 'neoclide/coc.nvim'
--- - 'NeogitOrg/neogit'
--- - 'nvim-lualine/lualine.nvim'
--- - 'nvim-neo-tree/neo-tree.nvim'
--- - 'nvim-telescope/telescope.nvim'
--- - 'nvim-tree/nvim-tree.lua'
--- - 'OXY2DEV/helpview.nvim'
--- - 'OXY2DEV/markview.nvim'
--- - 'phaazon/hop.nvim'
--- - 'rcarriga/nvim-dap-ui'
--- - 'rcarriga/nvim-notify'
--- - 'rlane/pounce.nvim'
--- - 'romgrk/barbar.nvim'
--- - 'stevearc/aerial.nvim'
--- - 'williamboman/mason.nvim'
---
--- # Setup ~
---
--- This module needs a setup with `require('mini.hues').setup({})` and
--- **mandatory `background` and `foreground` fields** (add more fields to fit
--- your taste). It will create global Lua table `MiniHues` which you can use
--- for scripting or manually (with `:lua MiniHues.*`).
---
--- See |MiniHues.config| for `config` structure and default values.
---
--- This module doesn't have runtime options, so using `vim.b.minihues_config`
--- will have no effect here.
---
--- Example:
--- >
--- require('mini.hues').setup({
--- background = '#11262d',
--- foreground = '#c0c8cc',
--- plugins = {
--- default = false,
--- ['echasnovski/mini.nvim'] = true,
--- },
--- })
--- <
--- # Notes ~
---
--- - Using `setup()` doesn't actually create a |colorscheme|. It basically
--- creates a coordinated set of |highlight|s. To create your own scheme:
--- - Put "myscheme.lua" file (name after your chosen theme name) inside
--- any "colors" directory reachable from 'runtimepath' ("colors" inside
--- your Neovim config directory is usually enough).
--- - Inside "myscheme.lua" call `require('mini.hues').setup()` with your
--- palette and only after that set |g:colors_name| to "myscheme".
---
--- - This module doesn't define |cterm-colors| for implementation simplicity.
--- Use |mini.colors| module, |MiniColors-colorscheme:add_cterm_attributes()|
--- in particular.
--- Random hue color scheme ~
---
--- This module comes with a pre-built color scheme but with a twist: every
--- `:colorscheme randomhue` call will result in a different (randomly yet
--- carefully selected) colors.
---
--- It is essentially a combination of calls to |MiniHues.setup()| and
--- |MiniHues.gen_random_base_colors()| with a slight adjustments for
--- 'background' value.
---
--- Activate it as regular |colorscheme|. Get currently active config with
--- `:lua print(vim.inspect(MiniHues.config))`.
---@tag randomhue
---@diagnostic disable:undefined-field
---@diagnostic disable:discard-returns
---@diagnostic disable:unused-local
-- Module definition ==========================================================
local MiniHues = {}
local H = {}
--- Module setup
---
--- Main side effect is to create palette and apply i 8BD0 t. Essentially, a combination
--- of |MiniHues.make_palette()| and |MiniHues.apply_palette()|.
---
---@usage >lua
--- require('mini.hues').setup({
--- -- Use config table as you like
--- -- Needs both `background` and `foreground` fields present
--- background = '#11262d',
--- foreground = '#c0c8cc',
--- })
--- <
MiniHues.setup = function(config)
-- TODO: Remove after Neovim=0.8 support is dropped
if vim.fn.has('nvim-0.9') == 0 then
vim.notify(
'(mini.hues) Neovim<0.9 is soft deprecated (module works but not supported).'
.. ' It will be deprecated after next "mini.nvim" release (module might not work).'
.. ' Please update your Neovim version.'
)
end
-- Export module
_G.MiniHues = MiniHues
-- Setup config
config = H.setup_config(config)
-- Apply config
H.apply_config(config)
end
--- Module config
---
--- See |MiniHues.make_palette()| for more information about how certain
--- settings affect output color scheme.
---
--- Default values:
---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section)
---@text # Options ~
---
--- ## Plugin integrations ~
---
--- `config.plugins` defines for which supported plugins highlight groups will
--- be created. Limiting number of integrations slightly decreases startup time.
--- It is a table with boolean (`true`/`false`) values which are applied as follows:
--- - If plugin name (as listed in |mini.hues|) has entry, it is used.
--- - Otherwise `config.plugins.default` is used.
---
--- Example which will load only "mini.nvim" integration:
--- >
--- require('mini.hues').setup({
--- background = '#11262d',
--- foreground = '#c0c8cc',
--- plugins = {
--- default = false,
--- ['echasnovski/mini.nvim'] = true,
--- },
--- })
---
--- # Examples ~
---
--- Here are some possible setup configurations (copy first line and then use
--- only one `setup` call): >
---
--- local setup = require('mini.hues').setup
---
--- -- Choose background and foreground
--- setup({ background = '#2f1c22', foreground = '#cdc4c6' }) -- red
--- setup({ background = '#2f1e16', foreground = '#cdc5c1' }) -- orange
--- setup({ background = '#282211', foreground = '#c9c6c0' }) -- yellow
--- setup({ background = '#1c2617', foreground = '#c4c8c2' }) -- green
--- setup({ background = '#112723', foreground = '#c0c9c7' }) -- cyan
--- setup({ background = '#11262d', foreground = '#c0c8cc' }) -- azure
--- setup({ background = '#1d2231', foreground = '#c4c6cd' }) -- blue
--- setup({ background = '#281e2c', foreground = '#c9c5cb' }) -- purple
---
--- -- Choose number of accent colors
--- setup({ background = '#11262d', foreground = '#c0c8cc', n_hues = 6 })
--- setup({ background = '#11262d', foreground = '#c0c8cc', n_hues = 4 })
--- setup({ background = '#11262d', foreground = '#c0c8cc', n_hues = 2 })
--- setup({ background = '#11262d', foreground = '#c0c8cc', n_hues = 0 })
---
--- -- Choose saturation of colored text
--- setup({ background = '#11262d', foreground = '#c0c8cc', saturation = 'low' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', saturation = 'lowmedium' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', saturation = 'medium' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', saturation = 'mediumhigh' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', saturation = 'high' })
---
--- -- Choose accent color
--- setup({ background = '#11262d', foreground = '#c0c8cc', accent = 'bg' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', accent = 'red' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', accent = 'yellow' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', accent = 'cyan' })
--- setup({ background = '#11262d', foreground = '#c0c8cc', accent = 'blue' })
MiniHues.config = {
-- **Required** base colors as '#rrggbb' hex strings
background = nil,
foreground = nil,
-- Number of hues used for non-base colors
n_hues = 8,
-- Saturation. One of 'low', 'lowmedium', 'medium', 'mediumhigh', 'high'.
saturation = 'medium',
-- Accent color. One of: 'bg', 'fg', 'red', 'orange', 'yellow', 'green',
-- 'cyan', 'azure', 'blue', 'purple'
accent = 'bg',
-- Plugin integrations. Use `default = false` to disable all integrations.
-- Also can be set per plugin (see |MiniHues.config|).
plugins = { default = true },
}
--minidoc_afterlines_end
--- Make palette
---
--- General idea of palette generation is that it is mostly based on color channel
--- information extracted from base colors (background and foreground).
---
--- All operations are done inside `Oklch` color space, meaning that each color
--- is defined by three numbers:
--- - Lightness (`l`) - number between 0 (black) and 100 (white) describing how
--- light is a color.
--- - Chroma (`c`) - positive number describing how colorful is a color (bigger
--- values - more colorful; 0 is gray).
--- - Hue (`h`) - periodic number in [0, 360) describing a value of "true color"
--- on color circle/wheel.
---
--- For more details about `Oklch` see |MiniColors-color-spaces| or
--- https://bottosson.github.io/posts/oklab/.
---
--- Algorithm overview ~
---
--- - Extract lightness, chroma, and hue of base colors.
---
--- - Generate reference lightness values:
--- - Background edge: 0 or 100, whichever is closest to background lightness.
--- - Foreground edge: 0 or 100, different from background edge.
--- - Middle: arithmetic mean of background and foreground lightness values.
---
--- - Compute background and foreground tints and shades by changing lightness
--- of background color: two colors closer to background lightness edge and
--- two closer to middle.
---
--- - Pick chroma value for non-base colors based on `config.saturation`.
---
--- - Generate hues for non-base colors:
--- - Fit an equidistant circular grid with `config.n_hues` points to be as
--- far from both background and foreground hues. This will ensure that
--- non-base colors are as different as possible from base ones (for
--- better visual perception).
--- Example: for background hue 0, foreground hue 180, and `config.n_hues` 2
--- the output grid will be `{ 90, 270 }`.
---
--- - For each hue of reference color (which itself is an equidistant grid
--- of 8 hues) compute the closest value from the grid. This allows
--- operating in same terms (like "red", "green") despite maybe actually
--- having less different hues.
---
--- - Compute for each hue two variants of non-base colors: with background and
--- foreground lightness values.
---
--- - Compute two variants of accent color (with background and foreground
--- lightness) based on `config.accent`.
---
--- Notes:
--- - Some output colors can have not exact values of generated Oklch channels.
--- This is due to actually computed colors being impossible to represent via
--- '#rrggbb' hex string. In this case a process called gamut clipping is done
--- to reduce lightness and chroma in optimal way while maintaining same hue.
--- For more information see |MiniColors-gamut-clip|.
---
--- - Not all colors are actually used in highlight groups and are present for the
--- sake of completeness.
---
---@param config table Configuration for palette. Same structure as |MiniHues.config|.
--- Needs to have <background> and <foreground> fields.
---
---@return table Palette with the following fields:
--- - <bg> and <fg> with supplied `background` and `foreground` colors.
--- - Fields like <bg_*> and <fg_*> are essentially <bg> and <fg> but with
--- different lightness values: `_edge`/`_edge2` - closer to edge lightness,
--- `_mid`/`_mid2` - closer to middle lightness.
--- - Fields for non-base colors (<red>, <orange>, <yellow>, <green>, <cyan>,
--- <azure>, <blue>, <purple>) have the same lightness as foreground.
--- - Fields for non-base colors with <_bg> suffix have the same lightness as
--- background.
--- - <accent> and <accent_bg> represent accent colors with foreground and
--- background lightness values.
MiniHues.make_palette = function(config)
config = vim.tbl_deep_extend('force', MiniHues.config, config or {})
local bg = H.validate_hex(config.background, 'background')
local fg = H.validate_hex(config.foreground, 'foreground')
local n_hues = H.validate_n_hues(config.n_hues)
local saturation = H.validate_one_of(config.saturation, H.saturation_values, 'saturation')
local accent = H.validate_one_of(config.accent, H.accent_values, 'accent')
local bg_lch, fg_lch = H.hex2oklch(bg), H.hex2oklch(fg)
local bg_l, fg_l = bg_lch.l, fg_lch.l
if not ((bg_l <= 50 and 50 < fg_l) or (fg_l <= 50 and 50 < bg_l)) then
H.error('`background` and `foreground` should have opposite lightness.')
end
-- Reference lightness levels
local is_dark = bg_l <= 50
local l_bg_edge = is_dark and 0 or 100
local l_fg_edge = is_dark and 100 or 0
local l_mid = 0.5 * (bg_l + fg_l)
-- Configurable chroma level
local chroma = ({ low = 4, lowmedium = 6, medium = 8, mediumhigh = 12, high = 16 })[saturation]
-- Hues
local hues = H.make_hues(bg_lch.h, fg_lch.h, n_hues)
-- Compute result
--stylua: ignore
local res = {
-- `_edge`/`_mid` are third of the way towards reference (edge/middle)
-- `_edge2`/`_mid2` are two thirds
bg_edge2 = H.oklch2hex({ l = 0.33 * bg_l + 0.67 * l_bg_edge, c = bg_lch.c, h = bg_lch.h }),
bg_edge = H.oklch2hex({ l = 0.67 * bg_l + 0.33 * l_bg_edge, c = bg_lch.c, h = bg_lch.h }),
bg = bg,
bg_mid = H.oklch2hex({ l = 0.67 * bg_l + 0.33 * l_mid, c = bg_lch.c, h = bg_lch.h }),
bg_mid2 = H.oklch2hex({ l = 0.33 * bg_l + 0.67 * l_mid, c = bg_lch.c, h = bg_lch.h }),
fg_edge2 = H.oklch2hex({ l = 0.33 * fg_l + 0.67 * l_fg_edge, c = fg_lch.c, h = fg_lch.h }),
fg_edge = H.oklch2hex({ l = 0.67 * fg_l + 0.33 * l_fg_edge, c = fg_lch.c, h = fg_lch.h }),
fg = fg,
fg_mid = H.oklch2hex({ l = 0.67 * fg_l + 0.33 * l_mid, c = fg_lch.c, h = fg_lch.h }),
fg_mid2 = H.oklch2hex({ l = 0.33 * fg_l + 0.67 * l_mid, c = fg_lch.c, h = fg_lch.h }),
red = H.oklch2hex({ l = fg_l, c = chroma, h = hues.red }),
red_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.red }),
orange = H.oklch2hex({ l = fg_l, c = chroma, h = hues.orange }),
orange_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.orange }),
yellow = H.oklch2hex({ l = fg_l, c = chroma, h = hues.yellow }),
yellow_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.yellow }),
green = H.oklch2hex({ l = fg_l, c = chroma, h = hues.green }),
green_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.green }),
cyan = H.oklch2hex({ l = fg_l, c = chroma, h = hues.cyan }),
cyan_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.cyan }),
azure = H.oklch2hex({ l = fg_l, c = chroma, h = hues.azure }),
azure_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.azure }),
blue = H.oklch2hex({ l = fg_l, c = chroma, h = hues.blue }),
blue_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.blue }),
purple = H.oklch2hex({ l = fg_l, c = chroma, h = hues.purple }),
purple_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues.purple }),
}
-- Manage 'bg' and 'fg' accents separately to ensure that corresponding
-- background and foreground colors match exactly
--stylua: ignore
if accent == 'bg' then
res.accent = H.oklch2hex({ l = fg_l, c = chroma, h = bg_lch.h })
res.accent_bg = bg
elseif accent == 'fg' then
res.accent = fg
res.accent_bg = H.oklch2hex({ l = bg_l, c = chroma, h = fg_lch.h })
else
res.accent = H.oklch2hex({ l = fg_l, c = chroma, h = hues[accent] })
res.accent_bg = H.oklch2hex({ l = bg_l, c = chroma, h = hues[accent] })
end
return res
end
-- stylua: ignore
--- Apply palette
---
--- Create color scheme highlight groups and terminal colors based on supplied
--- palette. This is useful if you want to tweak palette colors.
--- For regular usage prefer |MiniHues.setup()|.
---
---@param palette table Table with structure as |MiniHues.make_palette()| output.
---@param plugins table|nil Table with boolean values indicating whether to create
--- highlight groups for specific plugins. See |MiniHues.config| for more details.
--- Default: the value from |MiniHues.config|.
---
---@usage >lua
--- local palette = require('mini.hues').make_palette({
--- background = '#11262d',
--- foreground = '#c0c8cc',
--- })
--- palette.cyan = '#76e0a6'
--- palette.cyan_bg = '#004629'
--- require('mini.hues').apply_palette(palette)
--- <
MiniHues.apply_palette = function(palette, plugins)
if type(palette) ~= 'table' then H.error('`palette` should be table with palette colors.') end
plugins = plugins or MiniHues.config.plugins
if type(plugins) ~= 'table' then H.error('`plugins` should be table with plugin integrations data.') end
-- Prepare highlighting application. Notes:
-- - Clear current highlight only if other theme was loaded previously.
-- - No need to `syntax reset` because *all* syntax groups are defined later.
if vim.g.colors_name then vim.cmd('highlight clear') end
-- As this doesn't create colorscheme, don't store any name. Not doing it
-- might cause some issues with `syntax on`.
vim.g.colors_name = nil
local p = palette
local hi = function(name, data) vim.api.nvim_set_hl(0, name, data) end
local has_integration = function(name)
local entry = plugins[name]
if entry == nil then return plugins.default end
return entry
end
-- NOTE: recommendations for adding new highlight groups:
-- - Put all related groups (like for new plugin) in single paragraph.
-- - Sort within group alphabetically (by hl-group name) ignoring case.
-- - Link all repeated groups within paragraph (lowers execution time).
-- - Align by commas.
-- Builtin highlighting groups
hi('ColorColumn', { fg=nil, bg=p.bg_mid2 })
hi('ComplMatchIns', { fg=nil, bg=nil })
hi('Conceal', { fg=p.azure, bg=nil })
hi('CurSearch', { fg=p.bg, bg=p.yellow })
hi('Cursor', { fg=p.bg, bg=p.fg })
hi('CursorColumn', { fg=nil, bg=p.bg_mid })
hi('CursorIM', { link='Cursor' })
hi('CursorLine', { fg=nil, bg=p.bg_mid })
hi('CursorLineFold', { fg=p.bg_mid2, bg=nil })
hi('CursorLineNr', { fg=p.accent, bg=nil, bold=true })
hi('CursorLineSign', { fg=p.bg_mid2, bg=nil })
hi('DiffAdd', { fg=nil, bg=p.green_bg })
hi('DiffChange', { fg=nil, bg=p.cyan_bg })
hi('DiffDelete', { fg=nil, bg=p.red_bg })
hi('DiffText', { fg=nil, bg=p.yellow_bg })
hi('Directory', { fg=p.azure, bg=nil })
hi('EndOfBuffer', { fg=p.bg_mid2, bg=nil })
hi('ErrorMsg', { fg=p.red, bg=nil })
hi('FloatBorder', { fg=p.accent, bg=p.bg_edge })
hi('FloatTitle', { fg=p.accent, bg=p.bg_edge, bold=true })
hi('FoldColumn', { fg=p.bg_mid2, bg=nil })
hi('Folded', { fg=p.fg_mid2, bg=p.bg_edge })
hi('IncSearch', { fg=p.bg, bg=p.yellow })
hi('lCursor', { fg=p.bg, bg=p.fg })
hi('LineNr', { fg=p.bg_mid2, bg=nil })
hi('LineNrAbove', { link='LineNr' })
hi('LineNrBelow', { link='LineNr' })
hi('MatchParen', { fg=nil, bg=p.bg_mid2, bold=true })
hi('ModeMsg', { fg=p.green, bg=nil })
hi('MoreMsg', { fg=p.azure, bg=nil })
hi('MsgArea', { link='Normal' })
hi('MsgSeparator', { fg=p.fg_mid2, bg=p.bg_mid2 })
hi('NonText', { fg=p.bg_mid2, bg=nil })
hi('Normal', { fg=p.fg, bg=p.bg })
hi('NormalFloat', { fg=p.fg, bg=p.bg_edge })
hi('NormalNC', { link='Normal' })
hi('Pmenu', { fg=p.fg, bg=p.bg_mid })
hi('PmenuExtra', { link='Pmenu' })
hi('PmenuExtraSel', { link='PmenuSel' })
hi('PmenuKind', { link='Pmenu' })
hi('PmenuKindSel', { link='PmenuSel' })
hi('PmenuMatch', { fg=p.fg, bg=p.bg_mid, bold=true })
hi('PmenuMatchSel', { fg=nil, bg=nil, bold=true, blend=0, reverse=true })
hi('PmenuSbar', { link='Pmenu' })
hi('PmenuSel', { fg=nil, bg=nil, blend=0, reverse=true })
hi('PmenuThumb', { fg=nil, bg=p.bg_mid2 })
hi('Question', { fg=p.azure, bg=nil })
hi('QuickFixLine', { fg=nil, bg=nil, bold=true })
hi('Search', { fg=p.bg, bg=p.accent })
hi('SignColumn', { fg=p.bg_mid2, bg=nil })
hi('SpecialKey', { fg=p.bg_mid2, bg=nil })
hi('SpellBad', { fg=nil, bg=nil, sp=p.red, undercurl=true })
hi('SpellCap', { fg=nil, bg=nil, sp=p.cyan, undercurl=true })
hi('SpellLocal', { fg=nil, bg=nil, sp=p.yellow, undercurl=true })
hi('SpellRare', { fg=nil, bg=nil, sp=p.blue, undercurl=true })
hi('StatusLine', { fg=p.fg_mid, bg=p.accent_bg })
hi('StatusLineNC', { fg=p.fg_mid, bg=p.bg_edge })
hi('Substitute', { fg=p.bg, bg=p.blue })
hi('TabLine', { fg=p.fg_mid, bg=p.bg_edge })
hi('TabLineFill', { link='Tabline' })
hi('TabLineSel', { fg=p.accent, bg=p.bg_edge })
hi('TermCursor', { fg=nil, bg=nil, reverse=true })
hi('TermCursorNC', { fg=nil, bg=nil, reverse=true })
hi('Title', { fg=p.accent, bg=nil })
hi('VertSplit', { fg=p.accent, bg=nil })
hi('Visual', { fg=nil, bg=p.bg_mid2 })
hi('VisualNOS', { fg=nil, bg=p.bg_mid })
hi('WarningMsg', { fg=p.yellow, bg=nil })
hi('Whitespace', { fg=p.bg_mid2, bg=nil })
hi('WildMenu', { link='PmenuSel' })
hi('WinBar', { link='StatusLine' })
hi('WinBarNC', { link='StatusLineNC' })
hi('WinSeparator', { fg=p.accent, bg=nil })
-- Standard syntax (affects treesitter)
hi('Boolean', { link='Constant' })
hi('Character', { link='Constant' })
hi('Comment', { fg=p.fg_mid2, bg=nil })
hi('Conditional', { link='Statement' })
hi('Constant', { fg=p.purple, bg=nil })
hi('Debug', { link='Special' })
hi('Define', { link='PreProc' })
hi('Delimiter', { fg=p.orange, bg=nil })
hi('Error', { fg=nil, bg=p.red_bg })
hi('Exception', { link='Statement' })
hi('Float', { link='Constant' })
hi('Function', { fg=p.azure, bg=nil })
hi('Identifier', { fg=p.yellow, bg=nil })
hi('Ignore', { fg=nil, bg=nil })
hi('Include', { link='PreProc' })
hi('Keyword', { link='Statement' })
hi('Label', { link='Statement' })
hi('Macro', { link='PreProc' })
hi('Number', { link='Constant' })
hi('Operator', { fg=p.fg, bg=nil })
hi('PreCondit', { link='PreProc' })
hi('PreProc', { fg=p.blue, bg=nil })
hi('Repeat', { link='Statement' })
hi('Special', { fg=p.cyan, bg=nil })
hi('SpecialChar', { link='Special' })
hi('SpecialComment', { link='Special' })
hi('Statement', { fg=p.fg, bg=nil, bold=true })
hi('StorageClass', { link='Type' })
hi('String', { fg=p.green, bg=nil })
hi('Structure', { link='Type' })
hi('Tag', { link='Special' })
hi('Todo', { fg=p.accent, bg=p.accent_bg, bold=true })
hi('Type', { fg=p.fg, bg=nil })
hi('Typedef', { link='Type' })
-- Other community standard
hi('Bold', { fg=nil, bg=nil, bold=true })
hi('Italic', { fg=nil, bg=nil, italic=true })
hi('Underlined', { fg=nil, bg=nil, underline=true })
-- Patch diff
hi('diffAdded', { fg=p.green, bg=nil })
hi('diffChanged', { fg=p.cyan, bg=nil })
hi('diffFile', { fg=p.yellow, bg=nil })
hi('diffLine', { fg=p.blue, bg=nil })
hi('diffRemoved', { fg=p.red, bg=nil })
hi('Added', { fg=p.green, bg=nil })
hi('Changed', { fg=p.cyan, bg=nil })
hi('Removed', { fg=p.red, bg=nil })
-- Git commit
hi('gitcommitBranch', { fg=p.orange, bg=nil, bold=true })
hi('gitcommitComment', { link='Comment' })
hi('gitcommitDiscarded', { link='Comment' })
hi('gitcommitDiscardedFile', { fg=p.yellow, bg=nil, bold=true })
hi('gitcommitDiscardedType', { fg=p.azure, bg=nil })
hi('gitcommitHeader', { link='Title' })
hi('gitcommitOverflow', { fg=p.yellow, bg=nil })
hi('gitcommitSelected', { link='Comment' })
hi('gitcommitSelectedFile', { fg=p.green, bg=nil, bold=true })
hi('gitcommitSelectedType', { link='gitcommitDiscardedType' })
hi('gitcommitSummary', { fg=p.green, bg=nil })
hi('gitcommitUnmergedFile', { link='gitcommitDiscardedFile' })
hi('gitcommitUnmergedType', { link='gitcommitDiscardedType' })
hi('gitcommitUntracked', { link='Comment' })
hi('gitcommitUntrackedFile', { fg=p.cyan, bg=nil })
-- Built-in diagnostic
-- Logic:
-- - Error is red.
-- - Distance from hue to error hue should increase the less important it is
-- (warning - info - ok - hint).
hi('DiagnosticError', { fg=p.red, bg=nil })
hi('DiagnosticHint', { fg=p.cyan, bg=nil })
hi('DiagnosticInfo', { fg=p.blue, bg=nil })
hi('DiagnosticOk', { fg=p.green, bg=nil })
hi('DiagnosticWarn', { fg=p.yellow, bg=nil })
hi('DiagnosticUnderlineError', { fg=nil, bg=nil, sp=p.red, underline=true })
hi('DiagnosticUnderlineHint', { fg=nil, bg=nil, sp=p.cyan, underline=true })
hi('DiagnosticUnderlineInfo', { fg=nil, bg=nil, sp=p.blue, underline=true })
hi('DiagnosticUnderlineOk', { fg=nil, bg=nil, sp=p.green, underline=true })
hi('DiagnosticUnderlineWarn', { fg=nil, bg=nil, sp=p.yellow, underline=true })
hi('DiagnosticFloatingError', { fg=p.red, bg=p.bg_edge })
hi('DiagnosticFloatingHint', { fg=p.cyan, bg=p.bg_edge })
hi('DiagnosticFloatingInfo', { fg=p.blue, bg=p.bg_edge })
hi('DiagnosticFloatingOk', { fg=p.green, bg=p.bg_edge })
hi('DiagnosticFloatingWarn', { fg=p.yellow, bg=p.bg_edge })
hi('DiagnosticVirtualTextError', { link='DiagnosticError' })
hi('DiagnosticVirtualTextWarn', { link='DiagnosticWarn' })
hi('DiagnosticVirtualTextInfo', { link='DiagnosticInfo' })
hi('DiagnosticVirtualTextHint', { link='DiagnosticHint' })
hi('DiagnosticVirtualTextOk', { link='DiagnosticOk' })
hi('DiagnosticSignError', { link='DiagnosticError' })
hi('DiagnosticSignWarn', { link='DiagnosticWarn' })
hi('DiagnosticSignInfo', { link='DiagnosticInfo' })
hi('DiagnosticSignHint', { link='DiagnosticHint' })
hi('DiagnosticSignOk', { link='DiagnosticOk' })
hi('DiagnosticDeprecated', { fg=nil, bg=nil, sp=p.red, strikethrough=true })
hi('DiagnosticUnnecessary', { link='Comment' })
-- Built-in LSP
hi('LspReferenceText', { fg=nil, bg=p.bg_mid2 })
hi('LspReferenceRead', { link='LspReferenceText' })
hi('LspReferenceWrite', { link='LspReferenceText' })
hi('LspSignatureActiveParameter', { link='LspReferenceText' })
hi('LspCodeLens', { link='Comment' })
hi('LspCodeLensSeparator', { link='Comment' })
-- Built-in snippets
hi('SnippetTabstop', { fg=nil, bg=p.yellow_bg })
-- Built-in markdown syntax
hi('markdownH1', { link='@markup.heading.1' })
hi('markdownH2', { link='@markup.heading.2' })
hi('markdownH3', { link='@markup.heading.3' })
hi('markdownH4', { link='@markup.heading.4' })
hi('markdownH5', { link='@markup.heading.5' })
hi('markdownH6', { link='@markup.heading.6' })
-- Tree-sitter
-- Sources:
-- - `:h treesitter-highlight-groups`
-- - https://github.com/nvim-treesitter/nvim-treesitter/blob/master/CONTRIBUTING.md#highlights
hi('@text.literal', { link='Special' })
hi('@text.reference', { link='Identifier' })
hi('@text.title', { link='Title' })
hi('@text.uri', { link='Underlined' })
hi('@text.todo', { link='Todo' })
hi('@text.note', { link='MoreMsg' })
hi('@text.warning', { link='WarningMsg' })
hi('@text.danger', { link='ErrorMsg' })
hi('@text.strong', { fg=nil, bg=nil, bold=true })
hi('@text.emphasis', { fg=nil, bg=nil, italic=true })
hi('@text.strike', { fg=nil, bg=nil, strikethrough=true })
hi('@text.underline', { link='Underlined' })
hi('@comment', { link='Comment' })
hi('@punctuation', { link='Delimiter' })
hi('@constant', { link='Constant' })
hi('@constant.builtin', { link='Special' })
hi('@constant.macro', { link='Macro' })
hi('@define', { link='Define' })
hi('@macro', { link='Macro' })
hi('@string', { link='String' })
hi('@string.escape', { link='SpecialChar' })
hi('@string.special', { link='SpecialChar' })
hi('@character', { link='Character' })
hi('@character.special', { link='SpecialChar' })
hi('@number', { link='Number' })
hi('@boolean', { link='Boolean' })
hi('@float', { link='Float' })
hi('@function', { link='Function' })
hi('@function.builtin', { link='Special' })
hi('@function.call', { link='Function' })
hi('@function.macro', { link='Macro' })
hi('@parameter', { fg=p.blue, bg=nil })
hi('@method', { link='Function' })
hi('@method.call', { link='Function' })
hi('@field', { link='Identifier' })
hi('@property', { link='Identifier' })
hi('@constructor', { link='Special' })
hi('@conditional', { link='Conditional' })
hi('@repeat', { link='Repeat' })
hi('@label', { link='Label' })
hi('@operator', { link='Operator' })
hi('@keyword', { link='Keyword' })
hi('@keyword.return', { fg=p.orange, bg=nil, bold=true })
hi('@exception', { link='Exception' })
hi('@variable', { fg=p.fg, bg=nil })
hi('@variable.builtin', { link='Special' })
hi('@type', { link='Type' })
hi('@type.builtin', { link='Special' })
hi('@type.definition', { link='Typedef' })
hi('@storageclass', { link='StorageClass' })
hi('@structure', { link='Structure' })
hi('@namespace', { link='Identifier' })
hi('@include', { link='Include' })
hi('@preproc', { link='PreProc' })
hi('@debug', { link='Debug' })
hi('@tag', { link='Tag' })
hi('@symbol', { link='Keyword' })
hi('@none', { link='Normal' })
-- Semantic tokens
if vim.fn.has('nvim-0.9') == 1 then
-- Source: `:h lsp-semantic-highlight`
hi('@lsp.type.class', { link='@structure' })
hi('@lsp.type.decorator', { link='@function' })
hi('@lsp.type.enum', { link='@type' })
hi('@lsp.type.enumMember', { link='@constant' })
hi('@lsp.type.function', { link='@function' })
hi('@lsp.type.interface', { link='@type' })
hi('@lsp.type.macro', { link='@macro' })
hi('@lsp.type.method', { link='@method' })
hi('@lsp.type.namespace', { link='@namespace' })
hi('@lsp.type.parameter', { link='@parameter' })
hi('@lsp.type.property', { link='@property' })
hi('@lsp.type.struct', { link='@structure' })
hi('@lsp.type.type', { link='@type' })
hi('@lsp.type.typeParameter', { link='@type.definition' })
hi('@lsp.type.variable', { link='@variable' })
hi('@lsp.mod.deprecated', { fg=p.red, bg=nil })
end
-- New tree-sitter groups
if vim.fn.has('nvim-0.9') == 1 then
-- Sources:
-- - `:h treesitter-highlight-groups`
-- - https://github.com/nvim-treesitter/nvim-treesitter/commit/1ae9b0e4558fe7868f8cda2db65239cfb14836d0
-- NOTE: commented groups are the same as in Neovim<0.10 defined earlier
-- @variable
-- @variable.builtin
hi('@variable.parameter', { link='@parameter' })
hi('@variable.member', { link='@field' })
-- @constant
-- @constant.builtin
-- @constant.macro
hi('@module', { link='@namespace' })
hi('@module.builtin', { link='@variable.builtin' })
-- @label
-- @string
hi('@string.documentation', { link='@string' })
hi('@string.regexp', { link='SpecialChar' })
-- @string.escape
-- @string.special
hi('@string.special.symbol', { link='@constant' })
hi('@string.special.path', { link='Directory' })
hi('@string.special.url', { link='@markup.link.url' })
hi('@string.special.vimdoc', { link='@constant' })
-- @character
-- @character.special
-- @boolean
-- @number
hi('@number.float', { link='@float' })
-- @type
-- @type.builtin
-- @type.definition
hi('@type.qualifier', { link='StorageClass' })
hi('@attribute', { link='Macro' })
-- @property
-- @function
-- @function.builtin
-- @function.call
-- @function.macro
hi('@function.method', { link='@method' })
hi('@function.method.call', { link='@method.call' })
-- @constructor
-- @operator
-- @keyword
hi('@keyword.coroutine', { link='@keyword' })
hi('@keyword.function', { link='@keyword' })
hi('@keyword.operator', { link='@keyword' })
hi('@keyword.import', { fg=p.blue, bg=nil, bold=true })
hi('@keyword.storage', { fg=p.fg, bg=nil, bold=true })
hi('@keyword.repeat', { link='@keyword' })
-- @keyword.return
hi('@keyword.debug', { fg=p.cyan, bg=nil, bold=true })
hi('@keyword.exception', { link='@keyword' })
hi('@keyword.conditional', { link='@keyword' })
hi('@keyword.conditional.ternary', { link='keyword' })
hi('@keyword.directive', { fg=p.blue, bg=nil, bold=true })
hi('@keyword.directive.define', { link='@keyword.directive' })
hi('@punctuation.delimiter', { link='@punctuation' })
hi('@punctuation.bracket', { link='@punctuation' })
hi('@punctuation.special', { link='Special' })
-- @comment
hi('@comment.documentation', { link='@comment' })
hi('@comment.error', { link='@text.danger' })
hi('@comment.warning', { link='@text.warning' })
hi('@comment.todo', { link='@text.todo' })
hi('@comment.note', { link='@text.note' })
hi('@markup.strong', { link='@text.strong' })
hi('@markup.italic', { link='@text.emphasis' })
hi('@markup.strikethrough', { link='@text.strike' })
hi('@markup.underline', { link='@text.underline' })
hi('@markup.heading', { link='@text.title' })
hi('@markup.heading.1', { fg=p.orange, bg=nil })
hi('@markup.heading.2', { fg=p.yellow, bg=nil })
hi('@markup.heading.3', { fg=p.green, bg=nil })
hi('@markup.heading.4', { fg=p.cyan, bg=nil })
hi('@markup.heading.5', { fg=p.azure, bg=nil })
hi('@markup.heading.6', { fg=p.blue, bg=nil })
hi('@markup.quote', { link='@string.special' })
hi('@markup.math', { link='@string.special' })
hi('@markup.environment', { link='@module' })
hi('@markup.link', { link='@text.reference' })
hi('@markup.link.label', { link='@markup.link' })
hi('@markup.link.url', { fg=p.fg, bg=nil, underline=true })
hi('@markup.raw', { link='@text.literal' })
hi('@markup.raw.block', { link='@markup.raw' })
hi('@markup.list', { link='@punctuation.special' })
hi('@markup.list.checked', { link='DiagnosticOk' })
hi('@markup.list.unchecked', { link='DiagnosticWarn' })
hi('@diff.plus', { link='diffAdded' })
hi('@diff.minus', { link='diffRemoved' })
hi('@diff.delta', { link='diffChanged' })
-- @tag
hi('@tag.attribute', { link='@tag' })
hi('@tag.delimiter', { link='@punctuation' })
end
-- Plugins
-- echasnovski/mini.nvim
if has_integration('echasnovski/mini.nvim') then
hi('MiniAnimateCursor', { fg=nil, bg=nil, reverse=true, nocombine=true })
hi('MiniAnimateNormalFloat', { link='NormalFloat' })
hi('MiniClueBorder', { link='FloatBorder' })
hi('MiniClueDescGroup', { link='DiagnosticFloatingWarn' })
hi('MiniClueDescSingle', { link='NormalFloat' })
hi('MiniClueNextKey', { link='DiagnosticFloatingHint' })
hi('MiniClueNextKeyWithPostkeys', { link='DiagnosticFloatingError' })
hi('MiniClueSeparator', { link='DiagnosticFloatingInfo' })
hi('MiniClueTitle', { link='FloatTitle' })
hi('MiniCompletionActiveParameter', { link='LspSignatureActiveParameter' })
hi('MiniCompletionInfoBorderOutdated', { link='DiagnosticFloatingWarn' })
hi('MiniCursorword', { fg=nil, bg=nil, underline=true })
hi('MiniCursorwordCurrent', { fg=nil, bg=nil, underline=true })
hi('MiniDepsChangeAdded', { link='diffAdded' })
hi('MiniDepsChangeRemoved', { link='diffRemoved' })
hi('MiniDepsHint', { link='DiagnosticHint' })
hi('MiniDepsInfo', { link='DiagnosticInfo' })
hi('MiniDepsMsgBreaking', { link='DiagnosticWarn' })
hi('MiniDepsPlaceholder', { link='Comment' })
hi('MiniDepsTitle', { link='Title' })
hi('MiniDepsTitleError', { link='DiffDelete' })
hi('MiniDepsTitleSame', { link='DiffText' })
hi('MiniDepsTitleUpdate', { link='DiffAdd' })
hi('MiniDiffSignAdd', { link='diffAdded' })
hi('MiniDiffSignChange', { link='diffChanged' })
hi('MiniDiffSignDelete', { link='diffRemoved' })
hi('MiniDiffOverAdd', { link='DiffAdd' })
hi('MiniDiffOverChange', { link='DiffText' })
hi('MiniDiffOverChangeBuf', { link='MiniDiffOverChange' })
hi('MiniDiffOverContext', { link='DiffChange' })
hi('MiniDiffOverContextBuf', {})
hi('MiniDiffOverDelete', { link='DiffDelete' })
hi('MiniFilesBorder', { link='FloatBorder' })
hi('MiniFilesBorderModified', { link='DiagnosticFloatingWarn' })
hi('MiniFilesCursorLine', { link='CursorLine' })
hi('MiniFilesDirectory', { link='Directory' })
hi('MiniFilesFile', { fg=p.fg, bg=nil })
hi('MiniFilesNormal', { link='NormalFloat' })
hi('MiniFilesTitle', { link='FloatTitle' })
hi('MiniFilesTitleFocused', { fg=p.fg, bg=p.bg_edge, bold=true })
hi('MiniHipatternsFixme', { fg=p.bg, bg=p.red, bold=true })
hi('MiniHipatternsHack', { fg=p.bg, bg=p.yellow, bold=true })
hi('MiniHipatternsNote', { fg=p.bg, bg=p.cyan, bold=true })
hi('MiniHipatternsTodo', { fg=p.bg, bg=p.blue, bold=true })
hi('MiniIconsAzure', { fg=p.azure, bg=nil })
hi('MiniIconsBlue', { fg=p.blue, bg=nil })
hi('MiniIconsCyan', { fg=p.cyan, bg=nil })
hi('MiniIconsGreen', { fg=p.green, bg=nil })
hi('MiniIconsGrey', { fg=p.fg_edge, bg=nil })
hi('MiniIconsOrange', { fg=p.orange, bg=nil })
hi('MiniIconsPurple', { fg=p.purple, bg=nil })
hi('MiniIconsRed', { fg=p.red, bg=nil })
hi('MiniIconsYellow', { fg=p.yellow, bg=nil })
hi('MiniIndentscopeSymbol', { fg=p.accent, bg=nil })
hi('MiniIndentscopeSymbolOff', { fg=p.red, bg=nil })
hi('MiniJump', { fg=nil, bg=nil, sp=p.accent, undercurl=true })
hi('MiniJump2dDim', { fg=p.bg_mid2, bg=nil })
hi('MiniJump2dSpot', { fg=p.fg_edge2, bg=p.bg_edge2, bold=true, nocombine=true })
hi('MiniJump2dSpotAhead', { fg=p.fg_edge, bg=p.bg_edge2, nocombine=true })
hi('MiniJump2dSpotUnique', { link='MiniJump2dSpot' })
hi('MiniMapNormal', { fg=p.fg_mid2, bg=p.bg_edge })
hi('MiniMapSymbolCount', { fg=p.fg_mid2, bg=nil })
hi('MiniMapSymbolLine', { fg=p.accent, bg=nil })
hi('MiniMapSymbolView', { fg=p.accent, bg=nil })
hi('MiniNotifyBorder', { link='FloatBorder' })
hi('MiniNotifyLspProgress', { link='MiniNotifyNormal' })
hi('MiniNotifyNormal', { link='NormalFloat' })
hi('MiniNotifyTitle', { link='FloatTitle' })
hi('MiniOperatorsExchangeFrom', { link='IncSearch' })
hi('MiniPickBorder', { link='FloatBorder' })
hi('MiniPickBorderBusy', { link='DiagnosticFloatingWarn' })
hi('MiniPickBorderText', { link='FloatTitle' })
hi('MiniPickCursor', { blend=100, nocombine=true })
hi('MiniPickIconDirectory', { link='Directory' })
hi('MiniPickIconFile', { link='MiniPickNormal' })
hi('MiniPickHeader', { link='DiagnosticFloatingHint' })
hi('MiniPickMatchCurrent', { link='CursorLine' })
hi('MiniPickMatchMarked', { link='Visual' })
hi('MiniPickMatchRanges', { link='DiagnosticFloatingHint' })
hi('MiniPickNormal', { link='NormalFloat' })
hi('MiniPickPreviewLine', { link='CursorLine' })
hi('MiniPickPreviewRegion', { link='IncSearch' })
hi('MiniPickPrompt', { link='MiniPickMatchRanges' })
hi('MiniPickPromptCaret', { link='DiagnosticFloatingInfo' })
hi('MiniPickPromptPrefix', { link='DiagnosticFloatingInfo' })
hi('MiniSnippetsCurrent', { fg=nil, bg=nil, sp=p.yellow, underdouble=true })
hi('MiniSnippetsCurrentReplace', { fg=nil, bg=nil, sp=p.red, underdouble=true })
hi('MiniSnippetsFinal', { fg=nil, bg=nil, sp=p.green, underdouble=true })
hi('MiniSnippetsUnvisited', { fg=nil, bg=nil, sp=p.cyan, underdouble=true })
hi('MiniSnippetsVisited', { fg=nil, bg=nil, sp=p.blue, underdouble=true })
hi('MiniStarterCurrent', { link='MiniStarterItem' })
hi('MiniStarterFooter', { link='Comment' })
hi('MiniStarterHeader', { fg=p.accent, bg=nil, bold=true })
hi('MiniStarterInactive', { link='Comment' })
hi('MiniStarterItem', { fg=nil, bg=nil })
hi('MiniStarterItemBullet', { fg=p.fg_mid2, bg=nil })
hi('MiniStarterItemPrefix', { fg=p.yellow, bg=nil, bold=true })
hi('MiniStarterSection', { fg=p.purple, bg=nil })
hi('MiniStarterQuery', { fg=p.green, bg=nil, bold=true })
hi('MiniStatuslineDevinfo', { fg=p.fg_mid, bg=p.bg_mid })
hi('MiniStatuslineFileinfo', { link='MiniStatuslineDevinfo' })
hi('MiniStatuslineFilename', { fg=p.fg_mid, bg=p.accent_bg })
hi('MiniStatuslineInactive', { link='StatusLineNC' })
hi('MiniStatuslineModeCommand', { fg=p.bg, bg=p.yellow, bold=true })
hi('MiniStatuslineModeInsert', { fg=p.bg, bg=p.azure, bold=true })
0