Created
November 30, 2023 17:03
-
-
Save echasnovski/a04648c10d0b70e187e06068d2317e00 to your computer and use it in GitHub Desktop.
Experimentation script for the new Neovim color scheme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Code for tweaking new default Neovim color scheme for PR #????? | |
-- It defines an overall look based on a handful of hyperparameters. | |
-- | |
-- General goals: | |
-- - Be "Neovim branded", i.e. follow outlined example from | |
-- https://github.com/neovim/neovim/issues/14790 | |
-- That generally means to mostly have "green-blue" feel plus at least one | |
-- reserved for very occasional attention: red for severe, yellow for mild. | |
-- - Be extra minimal for `notermguicolors` while allowing more shades for | |
-- when `termguicolors` is set. | |
-- - Be accessible, i.e. have enough contrast ratios (CR): | |
-- - Fully passable `Normal` highlight group: CR>=7. | |
-- - Passable `Visual` highlight group (with `Normal` foreground): CR>=4.5. | |
-- - Passable comment in current line (foreground from `Comment` and | |
-- background from `CursorLine`): CR>=4.5. | |
-- - Passable diff highlight groups: CR>=4.5. | |
-- - Passable 'Search' highlight group: CR>=4.5. | |
-- - Have dark and light variants be a simple exchange of dark and light | |
-- palettes (as this is easier to implement). | |
-- - Be usable for more than one person. | |
-- What this script does: | |
-- - Computes dark and light palettes based on hyperparameters. | |
-- - Creates a buffer with the following information about palettes: | |
-- - Dark and light palettes themselves. | |
-- - Values of target contrast ratios. | |
-- - Their 8-bit color approximations to be used with `ctermfg`/`ctermbg`. | |
-- - Copy-pasteable lines defining colors in 'src/nvim/highlight_group.c'. | |
-- - Enables the currently defined color scheme. | |
-- NOTE: All manipulation is done in Oklch color space. | |
-- Get interactive view at https://bottosson.github.io/misc/colorpicker/ | |
-- Install https://github.com/echasnovski/mini.colors to have this working | |
local colors = require('mini.colors') | |
-- Hyperparameters ============================================================ | |
-- REFERENCE LIGHTNESS VALUES | |
-- They are applied both to dark and light pallete, and indicate how far from | |
-- corresponding edge (0 for dark and 100 for light) it should be. | |
-- Level meaning for dark color scheme (reverse for light one): | |
-- - Level 1 is background for floating windows. | |
-- - Level 2 is basic lightness. Used in `Normal` (both bg and fg). | |
-- - Level 3 is `CursorLine` background. | |
-- - Level 4 is `Visual` background and `Comment` foreground. | |
-- | |
-- Value for level 2 is taken from #14790 (as lightness of #1e1e1e). | |
-- Others are the result of experiments to have passable contrast ratios. | |
local l = { 6, 13, 20, 35 } | |
-- REFERENCE CHROMA VALUES | |
-- Chosen experimentally. Darker colors usually need higher chroma to appear | |
-- visibly different (combined with proper gamut clipping) | |
local c = { grey = 1, light = 10, dark = 15 } | |
-- REFERENCE HUE VALUES | |
-- - Grey is used for UI background and foreground. It is not exactly an | |
-- achromatic grey, but a "colored grey" (very desaturated colors). It adds | |
-- at least some character to the color scheme. | |
-- Choice 270 implements "cold" UI. Tweak to get a different feel. Examples: | |
-- - 90 for warm. | |
-- - 180 for neutral cyan. | |
-- - 0 for neutral pink. | |
-- - Red hue is taken roughly the same as in reference #D96D6A | |
-- - Green hue is taken roughly the same as in reference #87FFAF | |
-- - Cyan hue is taken roughly the same as in reference #00E6E6 | |
-- - Yellow, blue, and magenta are chosen to be visibly different from others. | |
local h = { | |
grey = 270, | |
red = 25, | |
yellow = 90, | |
green = 150, | |
cyan = 195, | |
blue = 240, | |
magenta = 330, | |
} | |
-- WHETHER TO OPEN A BUFFER WITH DATA | |
local show_data_buffer = true | |
-- WHETHER TO APPLY CURRENT COLOR SCHEME | |
local apply_colorscheme = true | |
-- Palettes =================================================================== | |
local convert = function(L, C, H) return colors.convert({ l = L, c = C, h = H }, 'hex', { gamut_clip = 'cusp' }) end | |
local round = function(x) return math.floor(10 * x + 0.5) / 10 end | |
--stylua: ignore | |
local palette_dark = { | |
grey1 = convert(l[1], c.grey, h.grey), -- NormalFloat | |
grey2 = convert(l[2], c.grey, h.grey), -- Normal bg | |
grey3 = convert(l[3], c.grey, h.grey), -- CursorLine | |
grey4 = convert(l[4], c.grey, h.grey), -- Visual | |
red = convert(l[2], c.dark, h.red), -- DiffDelete | |
yellow = convert(l[2], c.dark, h.yellow), -- Search | |
green = convert(l[2], c.dark, h.green), -- DiffAdd | |
cyan = convert(l[2], c.dark, h.cyan), -- DiffChange | |
blue = convert(l[2], c.dark, h.blue), | |
magenta = convert(l[2], c.dark, h.magenta), | |
} | |
--stylua: ignore | |
local palette_light = { | |
grey1 = convert(100 - l[1], c.grey, h.grey), | |
grey2 = convert(100 - l[2], c.grey, h.grey), -- Normal fg | |
grey3 = convert(100 - l[3], c.grey, h.grey), | |
grey4 = convert(100 - l[4], c.grey, h.grey), -- Comment | |
red = convert(100 - l[2], c.light, h.red), -- DiagnosticError | |
yellow = convert(100 - l[2], c.light, h.yellow), -- DiagnosticWarn | |
green = convert(100 - l[2], c.light, h.green), -- String, DiagnosticOk | |
cyan = convert(100 - l[2], c.light, h.cyan), -- Function, DiagnosticInfo | |
blue = convert(100 - l[2], c.light, h.blue), -- Identifier, DiagnosticHint | |
magenta = convert(100 - l[2], c.light, h.magenta), | |
} | |
-- 8-bit color approximations ================================================= | |
local convert_to_8bit = function(hex) return require('mini.colors').convert(hex, '8-bit') end | |
local cterm_palette_dark = vim.tbl_map(convert_to_8bit, palette_dark) | |
local cterm_palette_light = vim.tbl_map(convert_to_8bit, palette_light) | |
-- Oklch color representations ================================================ | |
local convert_to_oklch = function(hex) | |
local res = require('mini.colors').convert(hex, 'oklch') | |
return vim.tbl_map(round, res) | |
end | |
local oklch_palette_dark = vim.tbl_map(convert_to_oklch, palette_dark) | |
local oklch_palette_light = vim.tbl_map(convert_to_oklch, palette_light) | |
-- Contrast ratios ============================================================ | |
local correct_channel = function(x) return x <= 0.04045 and (x / 12.92) or math.pow((x + 0.055) / 1.055, 2.4) end | |
-- Source: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef | |
local get_luminance = function(hex) | |
local rgb = colors.convert(hex, 'rgb') | |
-- Convert decimal color to [0; 1] | |
local r, g, b = rgb.r / 255, rgb.g / 255, rgb.b / 255 | |
-- Correct channels | |
local R, G, B = correct_channel(r), correct_channel(g), correct_channel(b) | |
return 0.2126 * R + 0.7152 * G + 0.0722 * B | |
end | |
-- Source: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef | |
local get_contrast_ratio = function(hex_fg, hex_bg) | |
local lum_fg, lum_bg = get_luminance(hex_fg), get_luminance(hex_bg) | |
local res = (math.max(lum_bg, lum_fg) + 0.05) / (math.min(lum_bg, lum_fg) + 0.05) | |
-- Track only one decimal digit | |
return round(res) | |
end | |
--stylua: ignore | |
local contrast_ratios = { | |
dark_normal = get_contrast_ratio(palette_light.grey2, palette_dark.grey2), | |
dark_cur_line = get_contrast_ratio(palette_light.grey2, palette_dark.grey3), | |
dark_visual = get_contrast_ratio(palette_light.grey2, palette_dark.grey4), | |
light_normal = get_contrast_ratio(palette_dark.grey2, palette_light.grey2), | |
light_cur_line = get_contrast_ratio(palette_dark.grey2, palette_light.grey3), | |
light_visual = get_contrast_ratio(palette_dark.grey2, palette_light.grey4), | |
dark_comment = get_contrast_ratio(palette_light.grey4, palette_dark.grey2), | |
dark_comment_cur = get_contrast_ratio(palette_light.grey4, palette_dark.grey3), | |
dark_comment_vis = get_contrast_ratio(palette_light.grey4, palette_dark.grey4), | |
light_comment = get_contrast_ratio(palette_dark.grey4, palette_light.grey2), | |
light_comment_cur = get_contrast_ratio(palette_dark.grey4, palette_light.grey3), | |
light_comment_vis = get_contrast_ratio(palette_dark.grey4, palette_light.grey4), | |
dark_red = get_contrast_ratio(palette_light.red, palette_dark.grey2), | |
light_red = get_contrast_ratio(palette_dark.red, palette_light.grey2), | |
dark_yellow = get_contrast_ratio(palette_light.yellow, palette_dark.grey2), | |
light_yellow = get_contrast_ratio(palette_dark.yellow, palette_light.grey2), | |
dark_green = get_contrast_ratio(palette_light.green, palette_dark.grey2), | |
light_green = get_contrast_ratio(palette_dark.green, palette_light.grey2), | |
dark_cyan = get_contrast_ratio(palette_light.cyan, palette_dark.grey2), | |
light_cyan = get_contrast_ratio(palette_dark.cyan, palette_light.grey2), | |
dark_blue = get_contrast_ratio(palette_light.blue, palette_dark.grey2), | |
light_blue = get_contrast_ratio(palette_dark.blue, palette_light.grey2), | |
dark_magenta = get_contrast_ratio(palette_light.magenta, palette_dark.grey2), | |
light_magenta = get_contrast_ratio(palette_dark.magenta, palette_light.grey2), | |
} | |
-- Buffer with data =========================================================== | |
local table_to_lines = function(tbl) | |
local keys = vim.tbl_keys(tbl) | |
table.sort(keys) | |
-- Compute key_width for a pretty alignment | |
local key_width = 0 | |
for _, key in ipairs(keys) do | |
key_width = math.max(key_width, key:len()) | |
end | |
local formatstring = '%-' .. key_width .. 's = %s' | |
local res = {} | |
for _, key in ipairs(keys) do | |
local value_str = vim.inspect(tbl[key], { newline = ' ', indent = '' }) | |
table.insert(res, string.format(formatstring, key, value_str)) | |
end | |
return res | |
end | |
--stylua: ignore | |
local color_src_names = { | |
blue = 'Blue', | |
cyan = 'Cyan', | |
green = 'Green', | |
grey1 = 'Grey1', | |
grey2 = 'Grey2', | |
grey3 = 'Grey3', | |
grey4 = 'Grey4', | |
magenta = 'Magenta', | |
red = 'Red', | |
yellow = 'Yellow', | |
} | |
local color_names = vim.tbl_keys(color_src_names) | |
table.sort(color_names) | |
local make_color_def_lines = function(bg, palette, palette_8bit) | |
local prefix = bg == 'dark' and 'NvimDark' or 'NvimLight' | |
local res = {} | |
for _, color in ipairs(color_names) do | |
local r, g, b = palette[color]:match('^#(..)(..)(..)$') | |
local cterm_color = palette_8bit[color] | |
--stylua: ignore | |
local src_l = string.format( | |
'{ "%s%s", RGB_(0x%s, 0x%s, 0x%s) }, // cterm=%d', | |
prefix, color_src_names[color], r, g, b, cterm_color | |
) | |
table.insert(res, src_l) | |
end | |
return res | |
end | |
local make_color_use_lines = function(bg, palette_8bit) | |
local res = {} | |
for _, color in ipairs(color_names) do | |
-- Produce color usage for dark background | |
local src_name = (bg == 'dark' and 'NvimDark' or 'NvimLight') .. color_src_names[color] | |
local suffix = bg == 'dark' and 'bg' or 'fg' | |
local gui = string.format('gui%s=%s', suffix, src_name) | |
local cterm = string.format('cterm%s=%s', suffix, palette_8bit[color]) | |
table.insert(res, gui .. ' ' .. cterm) | |
end | |
return res | |
end | |
local create_data_buffer = function() | |
-- Create buffer lines | |
local lines = {} | |
vim.list_extend(lines, { '--- Hex palettes ---' }) | |
vim.list_extend(lines, { 'Dark:' }) | |
vim.list_extend(lines, table_to_lines(palette_dark)) | |
vim.list_extend(lines, { '' }) | |
vim.list_extend(lines, { 'Light:' }) | |
vim.list_extend(lines, table_to_lines(palette_light)) | |
vim.list_extend(lines, { '', '' }) | |
vim.list_extend(lines, { '--- Contrast ratios ---' }) | |
vim.list_extend(lines, table_to_lines(contrast_ratios)) | |
vim.list_extend(lines, { '', '' }) | |
vim.list_extend(lines, { '--- 8-bit palettes ---' }) | |
vim.list_extend(lines, { 'Dark:' }) | |
vim.list_extend(lines, table_to_lines(cterm_palette_dark)) | |
vim.list_extend(lines, { '' }) | |
vim.list_extend(lines, { 'Light:' }) | |
vim.list_extend(lines, table_to_lines(cterm_palette_light)) | |
vim.list_extend(lines, { '', '' }) | |
vim.list_extend(lines, { '--- Oklch palettes ---' }) | |
vim.list_extend(lines, { 'Dark:' }) | |
vim.list_extend(lines, table_to_lines(oklch_palette_dark)) | |
vim.list_extend(lines, { '' }) | |
vim.list_extend(lines, { 'Light:' }) | |
vim.list_extend(lines, table_to_lines(oklch_palette_light)) | |
vim.list_extend(lines, { '', '' }) | |
vim.list_extend(lines, { "--- 'src/nvim/highlight_group.c' code ---" }) | |
vim.list_extend(lines, make_color_def_lines('dark', palette_dark, cterm_palette_dark)) | |
vim.list_extend(lines, make_color_def_lines('light', palette_light, cterm_palette_light)) | |
vim.list_extend(lines, { '' }) | |
vim.list_extend(lines, make_color_use_lines('dark', cterm_palette_dark)) | |
vim.list_extend(lines, make_color_use_lines('light', cterm_palette_light)) | |
-- Create and set buffer | |
local buf_id = vim.api.nvim_create_buf(true, true) | |
vim.api.nvim_buf_set_lines(buf_id, 0, -1, false, lines) | |
vim.api.nvim_set_current_buf(buf_id) | |
end | |
if show_data_buffer then create_data_buffer() end | |
-- Highlight groups =========================================================== | |
-- A function which defines highlight groups same way as the PR. | |
-- Uncomment later call to this function for quick prototyping. | |
local enable_colorscheme = function() | |
vim.cmd('hi clear') | |
vim.g.colors_name = 'neovim_colors' | |
-- In 'background=dark' dark colors are used for background and light - for | |
-- foreground. In 'background=light' they reverse. | |
-- Inline comments show basic highlight group assuming dark background | |
local is_dark = vim.o.background == 'dark' | |
local bg = is_dark and palette_dark or palette_light | |
local fg = is_dark and palette_light or palette_dark | |
-- Source for actual groups: 'src/nvim/highlight_group.c' in Neovim source code | |
--stylua: ignore start | |
local hi = function(name, data) vim.api.nvim_set_hl(0, name, data) end | |
-- General UI | |
hi('ColorColumn', { fg=nil, bg=bg.grey4 }) | |
hi('Conceal', { fg=bg.grey4, bg=nil }) | |
hi('CurSearch', { link='Search' }) | |
hi('Cursor', { fg=nil, bg=nil }) | |
hi('CursorColumn', { fg=nil, bg=bg.grey3 }) | |
hi('CursorIM', { link='Cursor' }) | |
hi('CursorLine', { fg=nil, bg=bg.grey3 }) | |
hi('CursorLineFold', { link='FoldColumn' }) | |
hi('CursorLineNr', { fg=nil, bg=nil, bold=true }) | |
hi('CursorLineSign', { link='SignColumn' }) | |
hi('DiffAdd', { fg=fg.grey1, bg=bg.green }) | |
hi('DiffChange', { fg=fg.grey1, bg=bg.grey4 }) | |
hi('DiffDelete', { fg=fg.red, bg=nil, bold=true }) | |
hi('DiffText', { fg=fg.grey1, bg=bg.cyan }) | |
hi('Directory', { fg=fg.cyan, bg=nil }) | |
hi('EndOfBuffer', { link='NonText' }) | |
hi('ErrorMsg', { fg=fg.red, bg=nil }) | |
hi('FloatBorder', { link='NormalFloat' }) | |
hi('FloatShadow', { fg=bg.grey1, bg=nil, blend=80 }) | |
hi('FloatShadowThrough', { fg=bg.grey1, bg=nil, blend=100 }) | |
hi('FloatTitle', { link='Title' }) | |
hi('FoldColumn', { link='SignColumn' }) | |
hi('Folded', { fg=fg.grey4, bg=bg.grey3 }) | |
hi('IncSearch', { link='Search' }) | |
hi('lCursor', { fg=bg.grey2, bg=fg.grey2 }) | |
hi('LineNr', { fg=bg.grey4, bg=nil }) | |
hi('LineNrAbove', { link='LineNr' }) | |
hi('LineNrBelow', { link='LineNr' }) | |
hi('MatchParen', { fg=nil, bg=bg.grey4, bold=true }) | |
hi('ModeMsg', { fg=fg.green, bg=nil }) | |
hi('MoreMsg', { fg=fg.cyan, bg=nil }) | |
hi('MsgArea', { fg=nil, bg=nil }) | |
hi('MsgSeparator', { link='StatusLine' }) | |
hi('NonText', { fg=bg.grey4, bg=nil }) | |
hi('Normal', { fg=fg.grey2, bg=bg.grey2 }) | |
hi('NormalFloat', { fg=fg.grey2, bg=bg.grey1 }) | |
hi('NormalNC', { fg=nil, bg=nil }) | |
hi('PMenu', { fg=fg.grey2, bg=bg.grey3 }) | |
hi('PMenuExtra', { link='PMenu' }) | |
hi('PMenuExtraSel', { link='PMenuSel' }) | |
hi('PMenuKind', { link='PMenu' }) | |
hi('PMenuKindSel', { link='PMenuSel' }) | |
hi('PMenuSbar', { link='PMenu' }) | |
hi('PMenuSel', { fg=bg.grey3, bg=fg.grey2, blend=0 }) | |
hi('PMenuThumb', { fg=nil, bg=bg.grey4 }) | |
hi('Question', { fg=fg.cyan, bg=nil }) | |
hi('QuickFixLine', { fg=nil, bg=nil, bold=true }) | |
hi('RedrawDebugNormal', { fg=nil, bg=nil, reverse=true }) | |
hi('RedrawDebugClear', { fg=nil, bg=bg.cyan }) | |
hi('RedrawDebugComposed', { fg=nil, bg=bg.green }) | |
hi('RedrawDebugRecompose', { fg=nil, bg=bg.red }) | |
hi('Search', { fg=fg.grey1, bg=bg.yellow}) | |
hi('SignColumn', { fg=bg.grey4, bg=nil }) | |
hi('SpecialKey', { fg=bg.grey4, bg=nil }) | |
hi('SpellBad', { fg=nil, bg=nil, sp=fg.red, undercurl=true }) | |
hi('SpellCap', { fg=nil, bg=nil, sp=fg.yellow, undercurl=true }) | |
hi('SpellLocal', { fg=nil, bg=nil, sp=fg.green, undercurl=true }) | |
hi('SpellRare', { fg=nil, bg=nil, sp=fg.cyan, undercurl=true }) | |
hi('StatusLine', { fg=fg.grey3, bg=bg.grey1 }) | |
hi('StatusLineNC', { fg=fg.grey4, bg=bg.grey1 }) | |
hi('Substitute', { link='Search' }) | |
hi('TabLine', { fg=fg.grey3, bg=bg.grey1 }) | |
hi('TabLineFill', { link='Tabline' }) | |
hi('TabLineSel', { fg=nil, bg=nil, bold = true }) | |
hi('TermCursor', { fg=nil, bg=nil, reverse=true }) | |
hi('TermCursorNC', { fg=nil, bg=nil, reverse=true }) | |
hi('Title', { fg=nil, bg=nil, bold=true }) | |
hi('VertSplit', { link='WinSeparator' }) | |
hi('Visual', { fg=nil, bg=bg.grey4 }) | |
hi('VisualNOS', { link='Visual' }) | |
hi('WarningMsg', { fg=fg.yellow, bg=nil }) | |
hi('Whitespace', { link='NonText' }) | |
hi('WildMenu', { link='PMenuSel' }) | |
hi('WinBar', { link='StatusLine' }) | |
hi('WinBarNC', { link='StatusLineNC' }) | |
hi('WinSeparator', { link='Normal' }) | |
-- Syntax (`:h group-name`) | |
hi('Comment', { fg=fg.grey4, bg=nil }) | |
hi('Constant', { fg=fg.grey2, bg=nil }) | |
hi('String', { fg=fg.green, bg=nil }) | |
hi('Character', { link='Constant' }) | |
hi('Number', { link='Constant' }) | |
hi('Boolean', { link='Constant' }) | |
hi('Float', { link='Number' }) | |
hi('Identifier', { fg=fg.blue, bg=nil }) -- frequent but important to get "main" branded color | |
hi('Function', { fg=fg.cyan, bg=nil }) -- not so frequent but important to get "main" branded color | |
hi('Statement', { fg=fg.grey2, bg=nil, bold=true }) -- bold choice (get it?) for accessibility | |
hi('Conditional', { link='Statement' }) | |
hi('Repeat', { link='Statement' }) | |
hi('Label', { link='Statement' }) | |
hi('Operator', { fg=fg.grey2, bg=nil }) -- seems too much to be bold for mostly singl-character words | |
hi('Keyword', { link='Statement' }) | |
hi('Exception', { link='Statement' }) | |
hi('PreProc', { fg=fg.grey2, bg=nil }) | |
hi('Include', { link='PreProc' }) | |
hi('Define', { link='PreProc' }) | |
hi('Macro', { link='PreProc' }) | |
hi('PreCondit', { link='PreProc' }) | |
hi('Type', { fg=fg.grey2, bg=nil }) | |
hi('StorageClass', { link='Type' }) | |
hi('Structure', { link='Type' }) | |
hi('Typedef', { link='Type' }) | |
hi('Special', { fg=fg.grey2, bg=nil }) | |
hi('Tag', { link='Special' }) | |
hi('SpecialChar', { link='Special' }) | |
hi('Delimiter', { fg=nil, bg=nil }) | |
hi('SpecialComment', { link='Special' }) | |
hi('Debug', { link='Special' }) | |
hi('LspInlayHint', { link='NonText' }) | |
hi('SnippetTabstop', { link='Visual' }) | |
hi('Underlined', { fg=nil, bg=nil, underline=true }) | |
hi('Ignore', { link='Normal' }) | |
hi('Error', { fg=bg.grey1, bg=fg.red }) | |
hi('Todo', { fg=fg.grey1, bg=nil, bold=true }) | |
hi('diffAdded', { fg=fg.green, bg=nil }) | |
hi('diffRemoved', { fg=fg.red, bg=nil }) | |
-- Built-in diagnostic | |
hi('DiagnosticError', { fg=fg.red, bg=nil }) | |
hi('DiagnosticWarn', { fg=fg.yellow, bg=nil }) | |
hi('DiagnosticInfo', { fg=fg.cyan, bg=nil }) | |
hi('DiagnosticHint', { fg=fg.blue, bg=nil }) | |
hi('DiagnosticOk', { fg=fg.green, bg=nil }) | |
hi('DiagnosticUnderlineError', { fg=nil, bg=nil, sp=fg.red, underline=true }) | |
hi('DiagnosticUnderlineWarn', { fg=nil, bg=nil, sp=fg.yellow, underline=true }) | |
hi('DiagnosticUnderlineInfo', { fg=nil, bg=nil, sp=fg.cyan, underline=true }) | |
hi('DiagnosticUnderlineHint', { fg=nil, bg=nil, sp=fg.blue, underline=true }) | |
hi('DiagnosticUnderlineOk', { fg=nil, bg=nil, sp=fg.green, underline=true }) | |
hi('DiagnosticFloatingError', { fg=fg.red, bg=bg.grey1 }) | |
hi('DiagnosticFloatingWarn', { fg=fg.yellow, bg=bg.grey1 }) | |
hi('DiagnosticFloatingInfo', { fg=fg.cyan, bg=bg.grey1 }) | |
hi('DiagnosticFloatingHint', { fg=fg.blue, bg=bg.grey1 }) | |
hi('DiagnosticFloatingOk', { fg=fg.green, bg=bg.grey1 }) | |
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=fg.red, strikethrough=true }) | |
hi('DiagnosticUnnecessary', { link='Comment' }) | |
-- Tree-sitter | |
-- - Text | |
hi('@text.literal', { link='Comment' }) | |
hi('@text.reference', { link='Identifier' }) | |
hi('@text.title', { link='Title' }) | |
hi('@text.uri', { link='Underlined' }) | |
hi('@text.underline', { link='Underlined' }) | |
hi('@text.todo', { link='Todo' }) | |
-- - Miscs | |
hi('@comment', { link='Comment' }) | |
hi('@punctuation', { link='Delimiter' }) | |
-- - Constants | |
hi('@constant', { link='Constant' }) | |
hi('@constant.builtin', { link='Special' }) | |
hi('@constant.macro', { link='Define' }) | |
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' }) | |
-- - Functions | |
hi('@function', { link='Function' }) | |
hi('@function.builtin', { link='Special' }) | |
hi('@function.macro', { link='Macro' }) | |
hi('@parameter', { link='Identifier' }) | |
hi('@method', { link='Function' }) | |
hi('@field', { link='Identifier' }) | |
hi('@property', { link='Identifier' }) | |
hi('@constructor', { link='Special' }) | |
-- - Keywords | |
hi('@conditional', { link='Conditional' }) | |
hi('@repeat', { link='Repeat' }) | |
hi('@label', { link='Label' }) | |
hi('@operator', { link='Operator' }) | |
hi('@keyword', { link='Keyword' }) | |
hi('@exception', { link='Exception' }) | |
hi('@variable', { fg=nil, bg=nil }) -- using default foreground reduces visual overload | |
hi('@type', { link='Type' }) | |
hi('@type.definition', { link='Typedef' }) | |
hi('@storageclass', { link='StorageClass' }) | |
hi('@namespace', { link='Identifier' }) | |
hi('@include', { link='Include' }) | |
hi('@preproc', { link='PreProc' }) | |
hi('@debug', { link='Debug' }) | |
hi('@tag', { link='Tag' }) | |
-- - LSP semantic tokens | |
hi('@lsp.type.class', { link='Structure' }) | |
hi('@lsp.type.comment', { link='Comment' }) | |
hi('@lsp.type.decorator', { link='Function' }) | |
hi('@lsp.type.enum', { link='Structure' }) | |
hi('@lsp.type.enumMember', { link='Constant' }) | |
hi('@lsp.type.function', { link='Function' }) | |
hi('@lsp.type.interface', { link='Structure' }) | |
hi('@lsp.type.macro', { link='Macro' }) | |
hi('@lsp.type.method', { link='Function' }) | |
hi('@lsp.type.namespace', { link='Structure' }) | |
hi('@lsp.type.parameter', { link='Identifier' }) | |
hi('@lsp.type.property', { link='Identifier' }) | |
hi('@lsp.type.struct', { link='Structure' }) | |
hi('@lsp.type.type', { link='Type' }) | |
hi('@lsp.type.typeParameter', { link='TypeDef' }) | |
hi('@lsp.type.variable', { link='@variable' }) -- links to tree-sitter group to reduce overload | |
-- Terminal colors (not ideal) | |
vim.g.terminal_color_0 = bg.grey2 | |
vim.g.terminal_color_1 = fg.red | |
vim.g.terminal_color_2 = fg.green | |
vim.g.terminal_color_3 = fg.yellow | |
vim.g.terminal_color_4 = fg.blue | |
vim.g.terminal_color_5 = fg.magenta | |
vim.g.terminal_color_6 = fg.cyan | |
vim.g.terminal_color_7 = fg.grey2 | |
vim.g.terminal_color_8 = bg.grey2 | |
vim.g.terminal_color_9 = fg.red | |
vim.g.terminal_color_10 = fg.green | |
vim.g.terminal_color_11 = fg.yellow | |
vim.g.terminal_color_12 = fg.blue | |
vim.g.terminal_color_13 = fg.magenta | |
vim.g.terminal_color_14 = fg.cyan | |
vim.g.terminal_color_15 = fg.grey2 | |
--stylua: ignore end | |
end | |
-- Comment this to not enable color scheme | |
if apply_colorscheme then enable_colorscheme() end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment