highlight_group.c (118677B)
1 // highlight_group.c: code for managing highlight groups 2 3 #include <assert.h> 4 #include <ctype.h> 5 #include <stdbool.h> 6 #include <stdint.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #include "klib/kvec.h" 12 #include "nvim/api/keysets_defs.h" 13 #include "nvim/api/private/defs.h" 14 #include "nvim/api/private/dispatch.h" 15 #include "nvim/api/private/helpers.h" 16 #include "nvim/api/private/validate.h" 17 #include "nvim/ascii_defs.h" 18 #include "nvim/autocmd.h" 19 #include "nvim/autocmd_defs.h" 20 #include "nvim/buffer_defs.h" 21 #include "nvim/charset.h" 22 #include "nvim/cmdexpand_defs.h" 23 #include "nvim/cursor_shape.h" 24 #include "nvim/decoration_provider.h" 25 #include "nvim/drawscreen.h" 26 #include "nvim/errors.h" 27 #include "nvim/eval.h" 28 #include "nvim/eval/typval_defs.h" 29 #include "nvim/eval/vars.h" 30 #include "nvim/ex_docmd.h" 31 #include "nvim/garray.h" 32 #include "nvim/garray_defs.h" 33 #include "nvim/gettext_defs.h" 34 #include "nvim/globals.h" 35 #include "nvim/grid_defs.h" 36 #include "nvim/highlight.h" 37 #include "nvim/highlight_group.h" 38 #include "nvim/lua/executor.h" 39 #include "nvim/macros_defs.h" 40 #include "nvim/map_defs.h" 41 #include "nvim/memory.h" 42 #include "nvim/memory_defs.h" 43 #include "nvim/message.h" 44 #include "nvim/option.h" 45 #include "nvim/option_defs.h" 46 #include "nvim/option_vars.h" 47 #include "nvim/os/time.h" 48 #include "nvim/runtime.h" 49 #include "nvim/strings.h" 50 #include "nvim/types_defs.h" 51 #include "nvim/ui.h" 52 #include "nvim/ui_defs.h" 53 #include "nvim/vim_defs.h" 54 55 /// \addtogroup SG_SET 56 /// @{ 57 enum { 58 SG_CTERM = 2, // cterm has been set 59 SG_GUI = 4, // gui has been set 60 SG_LINK = 8, // link has been set 61 }; 62 /// @} 63 64 #define MAX_SYN_NAME 200 65 66 // builtin |highlight-groups| 67 static garray_T highlight_ga = GA_EMPTY_INIT_VALUE; 68 69 // arena for object with same lifetime as highlight_ga (aka hl_table) 70 Arena highlight_arena = ARENA_EMPTY; 71 72 Map(cstr_t, int) highlight_unames = MAP_INIT; 73 74 /// The "term", "cterm" and "gui" arguments can be any combination of the 75 /// following names, separated by commas (but no spaces!). 76 static char *(hl_name_table[]) = 77 { "bold", "standout", "underline", 78 "undercurl", "underdouble", "underdotted", "underdashed", 79 "italic", "reverse", "inverse", "strikethrough", "altfont", 80 "dim", "blink", "conceal", "overline", "nocombine", "NONE" }; 81 static int hl_attr_table[] = 82 { HL_BOLD, HL_STANDOUT, HL_UNDERLINE, 83 HL_UNDERCURL, HL_UNDERDOUBLE, HL_UNDERDOTTED, HL_UNDERDASHED, 84 HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_ALTFONT, 85 HL_DIM, HL_BLINK, HL_CONCEALED, HL_OVERLINE, HL_NOCOMBINE, 0 }; 86 87 /// Structure that stores information about a highlight group. 88 /// The ID of a highlight group is also called group ID. It is the index in 89 /// the highlight_ga array PLUS ONE. 90 typedef struct { 91 char *sg_name; ///< highlight group name 92 char *sg_name_u; ///< uppercase of sg_name 93 bool sg_cleared; ///< "hi clear" was used 94 int sg_attr; ///< Screen attr @see ATTR_ENTRY 95 int sg_link; ///< link to this highlight group ID 96 int sg_deflink; ///< default link; restored in highlight_clear() 97 int sg_set; ///< combination of flags in \ref SG_SET 98 sctx_T sg_deflink_sctx; ///< script where the default link was set 99 sctx_T sg_script_ctx; ///< script in which the group was last set for terminal UIs 100 int sg_cterm; ///< "cterm=" highlighting attr 101 ///< (combination of \ref HlAttrFlags) 102 int sg_cterm_fg; ///< terminal fg color number + 1 103 int sg_cterm_bg; ///< terminal bg color number + 1 104 bool sg_cterm_bold; ///< bold attr was set for light color for RGB UIs 105 int sg_gui; ///< "gui=" highlighting attributes 106 ///< (combination of \ref HlAttrFlags) 107 RgbValue sg_rgb_fg; ///< RGB foreground color 108 RgbValue sg_rgb_bg; ///< RGB background color 109 RgbValue sg_rgb_sp; ///< RGB special color 110 int sg_rgb_fg_idx; ///< RGB foreground color index 111 int sg_rgb_bg_idx; ///< RGB background color index 112 int sg_rgb_sp_idx; ///< RGB special color index 113 114 int sg_blend; ///< blend level (0-100 inclusive), -1 if unset 115 116 int sg_parent; ///< parent of @nested.group 117 } HlGroup; 118 119 enum { 120 kColorIdxNone = -1, 121 kColorIdxHex = -2, 122 kColorIdxFg = -3, 123 kColorIdxBg = -4, 124 }; 125 126 #include "highlight_group.c.generated.h" 127 128 static const char e_highlight_group_name_not_found_str[] 129 = N_("E411: Highlight group not found: %s"); 130 static const char e_group_has_settings_highlight_link_ignored[] 131 = N_("E414: Group has settings, highlight link ignored"); 132 static const char e_unexpected_equal_sign_str[] 133 = N_("E415: Unexpected equal sign: %s"); 134 static const char e_missing_equal_sign_str_2[] 135 = N_("E416: Missing equal sign: %s"); 136 static const char e_missing_argument_str[] 137 = N_("E417: Missing argument: %s"); 138 139 #define hl_table ((HlGroup *)((highlight_ga.ga_data))) 140 141 // The default highlight groups. These are compiled-in for fast startup and 142 // they still work when the runtime files can't be found. 143 144 static const char *highlight_init_both[] = { 145 "Cursor guifg=bg guibg=fg", 146 "CursorLineNr gui=bold cterm=bold", 147 "PmenuMatch gui=bold cterm=bold", 148 "PmenuMatchSel gui=bold cterm=bold", 149 "PmenuSel gui=reverse cterm=reverse,underline blend=0", 150 "RedrawDebugNormal gui=reverse cterm=reverse", 151 "TabLineSel gui=bold cterm=NONE", 152 "TermCursor gui=reverse cterm=reverse", 153 "Underlined gui=underline cterm=underline", 154 "lCursor guifg=bg guibg=fg", 155 156 // UI 157 "default link CursorIM Cursor", 158 "default link CursorLineFold FoldColumn", 159 "default link CursorLineSign SignColumn", 160 "default link DiffTextAdd DiffText", 161 "default link EndOfBuffer NonText", 162 "default link FloatBorder NormalFloat", 163 "default link FloatFooter FloatTitle", 164 "default link FloatTitle Title", 165 "default link FoldColumn SignColumn", 166 "default link IncSearch CurSearch", 167 "default link LineNrAbove LineNr", 168 "default link LineNrBelow LineNr", 169 "default link MsgSeparator StatusLine", 170 "default link MsgArea NONE", 171 "default link NormalNC NONE", 172 "default link PmenuExtra Pmenu", 173 "default link PmenuExtraSel PmenuSel", 174 "default link PmenuKind Pmenu", 175 "default link PmenuKindSel PmenuSel", 176 "default link PmenuSbar Pmenu", 177 "default link PmenuBorder Pmenu", 178 "default link PmenuShadow FloatShadow", 179 "default link PmenuShadowThrough FloatShadowThrough", 180 "default link PreInsert Added", 181 "default link ComplMatchIns NONE", 182 "default link ComplHint NonText", 183 "default link ComplHintMore MoreMsg", 184 "default link Substitute Search", 185 "default link StatusLineTerm StatusLine", 186 "default link StatusLineTermNC StatusLineNC", 187 "default link StderrMsg ErrorMsg", 188 "default link StdoutMsg NONE", 189 "default link TabLine StatusLineNC", 190 "default link TabLineFill TabLine", 191 "default link VertSplit WinSeparator", 192 "default link VisualNOS Visual", 193 "default link Whitespace NonText", 194 "default link WildMenu PmenuSel", 195 "default link WinSeparator Normal", 196 197 // Syntax 198 "default link Character Constant", 199 "default link Number Constant", 200 "default link Boolean Constant", 201 "default link Float Number", 202 "default link Conditional Statement", 203 "default link Repeat Statement", 204 "default link Label Statement", 205 "default link Keyword Statement", 206 "default link Exception Statement", 207 "default link Include PreProc", 208 "default link Define PreProc", 209 "default link Macro PreProc", 210 "default link PreCondit PreProc", 211 "default link StorageClass Type", 212 "default link Structure Type", 213 "default link Typedef Type", 214 "default link Tag Special", 215 "default link SpecialChar Special", 216 "default link SpecialComment Special", 217 "default link Debug Special", 218 // Used by HLF_8 (very common). None of the HLF_* things use the other Special* groups. 219 "default link SpecialKey Special", 220 "default link Ignore Normal", 221 222 // Built-in LSP 223 "default link LspCodeLens NonText", 224 "default link LspCodeLensSeparator LspCodeLens", 225 "default link LspInlayHint NonText", 226 "default link LspReferenceRead LspReferenceText", 227 "default link LspReferenceText Visual", 228 "default link LspReferenceWrite LspReferenceText", 229 "default link LspReferenceTarget LspReferenceText", 230 "default link LspSignatureActiveParameter Visual", 231 "default link SnippetTabstop Visual", 232 "default link SnippetTabstopActive SnippetTabstop", 233 234 // Diagnostic 235 "default link DiagnosticFloatingError DiagnosticError", 236 "default link DiagnosticFloatingWarn DiagnosticWarn", 237 "default link DiagnosticFloatingInfo DiagnosticInfo", 238 "default link DiagnosticFloatingHint DiagnosticHint", 239 "default link DiagnosticFloatingOk DiagnosticOk", 240 "default link DiagnosticVirtualTextError DiagnosticError", 241 "default link DiagnosticVirtualTextWarn DiagnosticWarn", 242 "default link DiagnosticVirtualTextInfo DiagnosticInfo", 243 "default link DiagnosticVirtualTextHint DiagnosticHint", 244 "default link DiagnosticVirtualTextOk DiagnosticOk", 245 "default link DiagnosticVirtualLinesError DiagnosticError", 246 "default link DiagnosticVirtualLinesWarn DiagnosticWarn", 247 "default link DiagnosticVirtualLinesInfo DiagnosticInfo", 248 "default link DiagnosticVirtualLinesHint DiagnosticHint", 249 "default link DiagnosticVirtualLinesOk DiagnosticOk", 250 "default link DiagnosticSignError DiagnosticError", 251 "default link DiagnosticSignWarn DiagnosticWarn", 252 "default link DiagnosticSignInfo DiagnosticInfo", 253 "default link DiagnosticSignHint DiagnosticHint", 254 "default link DiagnosticSignOk DiagnosticOk", 255 "default link DiagnosticUnnecessary Comment", 256 257 // Treesitter standard groups 258 "default link @variable.builtin Special", 259 "default link @variable.parameter.builtin Special", 260 261 "default link @constant Constant", 262 "default link @constant.builtin Special", 263 264 "default link @module Structure", 265 "default link @module.builtin Special", 266 "default link @label Label", 267 268 "default link @string String", 269 "default link @string.regexp @string.special", 270 "default link @string.escape @string.special", 271 "default link @string.special SpecialChar", 272 "default link @string.special.url Underlined", 273 274 "default link @character Character", 275 "default link @character.special SpecialChar", 276 277 "default link @boolean Boolean", 278 "default link @number Number", 279 "default link @number.float Float", 280 281 "default link @type Type", 282 "default link @type.builtin Special", 283 284 "default link @attribute Macro", 285 "default link @attribute.builtin Special", 286 "default link @property Identifier", 287 288 "default link @function Function", 289 "default link @function.builtin Special", 290 291 "default link @constructor Special", 292 "default link @operator Operator", 293 294 "default link @keyword Keyword", 295 296 "default link @punctuation Delimiter", // fallback for subgroups; never used itself 297 "default link @punctuation.special Special", 298 299 "default link @comment Comment", 300 301 "default link @comment.error DiagnosticError", 302 "default link @comment.warning DiagnosticWarn", 303 "default link @comment.note DiagnosticInfo", 304 "default link @comment.todo Todo", 305 306 "@markup.strong gui=bold cterm=bold", 307 "@markup.italic gui=italic cterm=italic", 308 "@markup.strikethrough gui=strikethrough cterm=strikethrough", 309 "@markup.underline gui=underline cterm=underline", 310 311 "default link @markup Special", // fallback for subgroups; never used itself 312 "default link @markup.heading Title", 313 "default link @markup.link Underlined", 314 315 "default link @diff.plus Added", 316 "default link @diff.minus Removed", 317 "default link @diff.delta Changed", 318 319 "default link @tag Tag", 320 "default link @tag.builtin Special", 321 322 // :help 323 // Highlight "===" and "---" heading delimiters specially. 324 "default @markup.heading.1.delimiter.vimdoc guibg=bg guifg=bg guisp=fg gui=underdouble,nocombine ctermbg=NONE ctermfg=NONE cterm=underdouble,nocombine", 325 "default @markup.heading.2.delimiter.vimdoc guibg=bg guifg=bg guisp=fg gui=underline,nocombine ctermbg=NONE ctermfg=NONE cterm=underline,nocombine", 326 327 // LSP semantic tokens 328 "default link @lsp.type.class @type", 329 "default link @lsp.type.comment @comment", 330 "default link @lsp.type.decorator @attribute", 331 "default link @lsp.type.enum @type", 332 "default link @lsp.type.enumMember @constant", 333 "default link @lsp.type.event @type", 334 "default link @lsp.type.function @function", 335 "default link @lsp.type.interface @type", 336 "default link @lsp.type.keyword @keyword", 337 "default link @lsp.type.macro @constant.macro", 338 "default link @lsp.type.method @function.method", 339 "default link @lsp.type.modifier @type.qualifier", 340 "default link @lsp.type.namespace @module", 341 "default link @lsp.type.number @number", 342 "default link @lsp.type.operator @operator", 343 "default link @lsp.type.parameter @variable.parameter", 344 "default link @lsp.type.property @property", 345 "default link @lsp.type.regexp @string.regexp", 346 "default link @lsp.type.string @string", 347 "default link @lsp.type.struct @type", 348 "default link @lsp.type.type @type", 349 "default link @lsp.type.typeParameter @type.definition", 350 "default link @lsp.type.variable @variable", 351 352 "default link @lsp.mod.deprecated DiagnosticDeprecated", 353 354 NULL 355 }; 356 357 // Default colors only used with a light background. 358 static const char *highlight_init_light[] = { 359 "Normal guifg=NvimDarkGrey2 guibg=NvimLightGrey2 ctermfg=NONE ctermbg=NONE", 360 361 // UI 362 "Added guifg=NvimDarkGreen ctermfg=2", 363 "Changed guifg=NvimDarkCyan ctermfg=6", 364 "ColorColumn guibg=NvimLightGrey4 cterm=reverse", 365 "Conceal guifg=NvimLightGrey4", 366 "CurSearch guifg=NvimLightGrey1 guibg=NvimDarkYellow ctermfg=15 ctermbg=3", 367 "CursorColumn guibg=NvimLightGrey3", 368 "CursorLine guibg=NvimLightGrey3", 369 "DiffAdd guifg=NvimDarkGrey1 guibg=NvimLightGreen ctermfg=15 ctermbg=2", 370 "DiffChange guifg=NvimDarkGrey1 guibg=NvimLightGrey4", 371 "DiffDelete guifg=NvimDarkRed gui=bold ctermfg=1 cterm=bold", 372 "DiffText guifg=NvimDarkGrey1 guibg=NvimLightCyan ctermfg=15 ctermbg=6", 373 "Directory guifg=NvimDarkCyan ctermfg=6", 374 "ErrorMsg guifg=NvimDarkRed ctermfg=1", 375 "FloatShadow guibg=NvimLightGrey4 ctermbg=0 blend=80", 376 "FloatShadowThrough guibg=NvimLightGrey4 ctermbg=0 blend=100", 377 "Folded guifg=NvimDarkGrey4 guibg=NvimLightGrey1", 378 "LineNr guifg=NvimLightGrey4", 379 "MatchParen guibg=NvimLightGrey4 gui=bold cterm=bold,underline", 380 "ModeMsg guifg=NvimDarkGreen ctermfg=2", 381 "MoreMsg guifg=NvimDarkCyan ctermfg=6", 382 "NonText guifg=NvimLightGrey4", 383 "NormalFloat guibg=NvimLightGrey1", 384 "OkMsg guifg=NvimDarkGreen ctermfg=2", 385 "Pmenu guibg=NvimLightGrey3 cterm=reverse", 386 "PmenuThumb guibg=NvimLightGrey4", 387 "Question guifg=NvimDarkCyan ctermfg=6", 388 "QuickFixLine guifg=NvimDarkCyan ctermfg=6", 389 "RedrawDebugClear guibg=NvimLightYellow ctermfg=15 ctermbg=3", 390 "RedrawDebugComposed guibg=NvimLightGreen ctermfg=15 ctermbg=2", 391 "RedrawDebugRecompose guibg=NvimLightRed ctermfg=15 ctermbg=1", 392 "Removed guifg=NvimDarkRed ctermfg=1", 393 "Search guifg=NvimDarkGrey1 guibg=NvimLightYellow ctermfg=15 ctermbg=3", 394 "SignColumn guifg=NvimLightGrey4", 395 "SpellBad guisp=NvimDarkRed gui=undercurl cterm=undercurl", 396 "SpellCap guisp=NvimDarkYellow gui=undercurl cterm=undercurl", 397 "SpellLocal guisp=NvimDarkGreen gui=undercurl cterm=undercurl", 398 "SpellRare guisp=NvimDarkCyan gui=undercurl cterm=undercurl", 399 "StatusLine guifg=NvimDarkGrey2 guibg=NvimLightGrey4 cterm=reverse", 400 "StatusLineNC guifg=NvimDarkGrey3 guibg=NvimLightGrey3 cterm=bold,underline", 401 "Title guifg=NvimDarkGrey2 gui=bold cterm=bold", 402 "Visual guibg=NvimLightGrey4 ctermfg=15 ctermbg=0", 403 "WarningMsg guifg=NvimDarkYellow ctermfg=3", 404 "WinBar guifg=NvimDarkGrey4 guibg=NvimLightGrey1 gui=bold cterm=bold", 405 "WinBarNC guifg=NvimDarkGrey4 guibg=NvimLightGrey1 cterm=bold", 406 407 // Syntax 408 "Constant guifg=NvimDarkGrey2", // Use only `Normal` foreground to be usable on different background 409 "Operator guifg=NvimDarkGrey2", 410 "PreProc guifg=NvimDarkGrey2", 411 "Type guifg=NvimDarkGrey2", 412 "Delimiter guifg=NvimDarkGrey2", 413 414 "Comment guifg=NvimDarkGrey4", 415 "String guifg=NvimDarkGreen ctermfg=2", 416 "Identifier guifg=NvimDarkBlue ctermfg=4", 417 "Function guifg=NvimDarkCyan ctermfg=6", 418 "Statement guifg=NvimDarkGrey2 gui=bold cterm=bold", 419 "Special guifg=NvimDarkCyan ctermfg=6", 420 "Error guifg=NvimDarkGrey1 guibg=NvimLightRed ctermfg=15 ctermbg=1", 421 "Todo guifg=NvimDarkGrey2 gui=bold cterm=bold", 422 423 // Diagnostic 424 "DiagnosticError guifg=NvimDarkRed ctermfg=1", 425 "DiagnosticWarn guifg=NvimDarkYellow ctermfg=3", 426 "DiagnosticInfo guifg=NvimDarkCyan ctermfg=6", 427 "DiagnosticHint guifg=NvimDarkBlue ctermfg=4", 428 "DiagnosticOk guifg=NvimDarkGreen ctermfg=2", 429 "DiagnosticUnderlineError guisp=NvimDarkRed gui=underline cterm=underline", 430 "DiagnosticUnderlineWarn guisp=NvimDarkYellow gui=underline cterm=underline", 431 "DiagnosticUnderlineInfo guisp=NvimDarkCyan gui=underline cterm=underline", 432 "DiagnosticUnderlineHint guisp=NvimDarkBlue gui=underline cterm=underline", 433 "DiagnosticUnderlineOk guisp=NvimDarkGreen gui=underline cterm=underline", 434 "DiagnosticDeprecated guisp=NvimDarkRed gui=strikethrough cterm=strikethrough", 435 436 // Treesitter standard groups 437 "@variable guifg=NvimDarkGrey2", 438 NULL 439 }; 440 441 // Default colors only used with a dark background. 442 static const char *highlight_init_dark[] = { 443 "Normal guifg=NvimLightGrey2 guibg=NvimDarkGrey2 ctermfg=NONE ctermbg=NONE", 444 445 // UI 446 "Added guifg=NvimLightGreen ctermfg=10", 447 "Changed guifg=NvimLightCyan ctermfg=14", 448 "ColorColumn guibg=NvimDarkGrey4 cterm=reverse", 449 "Conceal guifg=NvimDarkGrey4", 450 "CurSearch guifg=NvimDarkGrey1 guibg=NvimLightYellow ctermfg=0 ctermbg=11", 451 "CursorColumn guibg=NvimDarkGrey3", 452 "CursorLine guibg=NvimDarkGrey3", 453 "DiffAdd guifg=NvimLightGrey1 guibg=NvimDarkGreen ctermfg=0 ctermbg=10", 454 "DiffChange guifg=NvimLightGrey1 guibg=NvimDarkGrey4", 455 "DiffDelete guifg=NvimLightRed gui=bold ctermfg=9 cterm=bold", 456 "DiffText guifg=NvimLightGrey1 guibg=NvimDarkCyan ctermfg=0 ctermbg=14", 457 "Directory guifg=NvimLightCyan ctermfg=14", 458 "ErrorMsg guifg=NvimLightRed ctermfg=9", 459 "FloatShadow guibg=NvimDarkGrey4 ctermbg=0 blend=80", 460 "FloatShadowThrough guibg=NvimDarkGrey4 ctermbg=0 blend=100", 461 "Folded guifg=NvimLightGrey4 guibg=NvimDarkGrey1", 462 "LineNr guifg=NvimDarkGrey4", 463 "MatchParen guibg=NvimDarkGrey4 gui=bold cterm=bold,underline", 464 "ModeMsg guifg=NvimLightGreen ctermfg=10", 465 "MoreMsg guifg=NvimLightCyan ctermfg=14", 466 "NonText guifg=NvimDarkGrey4", 467 "NormalFloat guibg=NvimDarkGrey1", 468 "OkMsg guifg=NvimLightGreen ctermfg=10", 469 "Pmenu guibg=NvimDarkGrey3 cterm=reverse", 470 "PmenuThumb guibg=NvimDarkGrey4", 471 "Question guifg=NvimLightCyan ctermfg=14", 472 "QuickFixLine guifg=NvimLightCyan ctermfg=14", 473 "RedrawDebugClear guibg=NvimDarkYellow ctermfg=0 ctermbg=11", 474 "RedrawDebugComposed guibg=NvimDarkGreen ctermfg=0 ctermbg=10", 475 "RedrawDebugRecompose guibg=NvimDarkRed ctermfg=0 ctermbg=9", 476 "Removed guifg=NvimLightRed ctermfg=9", 477 "Search guifg=NvimLightGrey1 guibg=NvimDarkYellow ctermfg=0 ctermbg=11", 478 "SignColumn guifg=NvimDarkGrey4", 479 "SpellBad guisp=NvimLightRed gui=undercurl cterm=undercurl", 480 "SpellCap guisp=NvimLightYellow gui=undercurl cterm=undercurl", 481 "SpellLocal guisp=NvimLightGreen gui=undercurl cterm=undercurl", 482 "SpellRare guisp=NvimLightCyan gui=undercurl cterm=undercurl", 483 "StatusLine guifg=NvimLightGrey2 guibg=NvimDarkGrey4 cterm=reverse", 484 "StatusLineNC guifg=NvimLightGrey3 guibg=NvimDarkGrey3 cterm=bold,underline", 485 "Title guifg=NvimLightGrey2 gui=bold cterm=bold", 486 "Visual guibg=NvimDarkGrey4 ctermfg=0 ctermbg=15", 487 "WarningMsg guifg=NvimLightYellow ctermfg=11", 488 "WinBar guifg=NvimLightGrey4 guibg=NvimDarkGrey1 gui=bold cterm=bold", 489 "WinBarNC guifg=NvimLightGrey4 guibg=NvimDarkGrey1 cterm=bold", 490 491 // Syntax 492 "Constant guifg=NvimLightGrey2", // Use only `Normal` foreground to be usable on different background 493 "Operator guifg=NvimLightGrey2", 494 "PreProc guifg=NvimLightGrey2", 495 "Type guifg=NvimLightGrey2", 496 "Delimiter guifg=NvimLightGrey2", 497 498 "Comment guifg=NvimLightGrey4", 499 "String guifg=NvimLightGreen ctermfg=10", 500 "Identifier guifg=NvimLightBlue ctermfg=12", 501 "Function guifg=NvimLightCyan ctermfg=14", 502 "Statement guifg=NvimLightGrey2 gui=bold cterm=bold", 503 "Special guifg=NvimLightCyan ctermfg=14", 504 "Error guifg=NvimLightGrey1 guibg=NvimDarkRed ctermfg=0 ctermbg=9", 505 "Todo guifg=NvimLightGrey2 gui=bold cterm=bold", 506 507 // Diagnostic 508 "DiagnosticError guifg=NvimLightRed ctermfg=9", 509 "DiagnosticWarn guifg=NvimLightYellow ctermfg=11", 510 "DiagnosticInfo guifg=NvimLightCyan ctermfg=14", 511 "DiagnosticHint guifg=NvimLightBlue ctermfg=12", 512 "DiagnosticOk guifg=NvimLightGreen ctermfg=10", 513 "DiagnosticUnderlineError guisp=NvimLightRed gui=underline cterm=underline", 514 "DiagnosticUnderlineWarn guisp=NvimLightYellow gui=underline cterm=underline", 515 "DiagnosticUnderlineInfo guisp=NvimLightCyan gui=underline cterm=underline", 516 "DiagnosticUnderlineHint guisp=NvimLightBlue gui=underline cterm=underline", 517 "DiagnosticUnderlineOk guisp=NvimLightGreen gui=underline cterm=underline", 518 "DiagnosticDeprecated guisp=NvimLightRed gui=strikethrough cterm=strikethrough", 519 520 // Treesitter standard groups 521 "@variable guifg=NvimLightGrey2", 522 NULL 523 }; 524 525 const char *const highlight_init_cmdline[] = { 526 // XXX When modifying a list modify it in both valid and invalid halves. 527 // TODO(ZyX-I): merge valid and invalid groups via a macros. 528 529 // NvimInternalError should appear only when highlighter has a bug. 530 "NvimInternalError ctermfg=Red ctermbg=Red guifg=Red guibg=Red", 531 532 // Highlight groups (links) used by parser: 533 534 "default link NvimAssignment Operator", 535 "default link NvimPlainAssignment NvimAssignment", 536 "default link NvimAugmentedAssignment NvimAssignment", 537 "default link NvimAssignmentWithAddition NvimAugmentedAssignment", 538 "default link NvimAssignmentWithSubtraction NvimAugmentedAssignment", 539 "default link NvimAssignmentWithConcatenation NvimAugmentedAssignment", 540 541 "default link NvimOperator Operator", 542 543 "default link NvimUnaryOperator NvimOperator", 544 "default link NvimUnaryPlus NvimUnaryOperator", 545 "default link NvimUnaryMinus NvimUnaryOperator", 546 "default link NvimNot NvimUnaryOperator", 547 548 "default link NvimBinaryOperator NvimOperator", 549 "default link NvimComparison NvimBinaryOperator", 550 "default link NvimComparisonModifier NvimComparison", 551 "default link NvimBinaryPlus NvimBinaryOperator", 552 "default link NvimBinaryMinus NvimBinaryOperator", 553 "default link NvimConcat NvimBinaryOperator", 554 "default link NvimConcatOrSubscript NvimConcat", 555 "default link NvimOr NvimBinaryOperator", 556 "default link NvimAnd NvimBinaryOperator", 557 "default link NvimMultiplication NvimBinaryOperator", 558 "default link NvimDivision NvimBinaryOperator", 559 "default link NvimMod NvimBinaryOperator", 560 561 "default link NvimTernary NvimOperator", 562 "default link NvimTernaryColon NvimTernary", 563 564 "default link NvimParenthesis Delimiter", 565 "default link NvimLambda NvimParenthesis", 566 "default link NvimNestingParenthesis NvimParenthesis", 567 "default link NvimCallingParenthesis NvimParenthesis", 568 569 "default link NvimSubscript NvimParenthesis", 570 "default link NvimSubscriptBracket NvimSubscript", 571 "default link NvimSubscriptColon NvimSubscript", 572 "default link NvimCurly NvimSubscript", 573 574 "default link NvimContainer NvimParenthesis", 575 "default link NvimDict NvimContainer", 576 "default link NvimList NvimContainer", 577 578 "default link NvimIdentifier Identifier", 579 "default link NvimIdentifierScope NvimIdentifier", 580 "default link NvimIdentifierScopeDelimiter NvimIdentifier", 581 "default link NvimIdentifierName NvimIdentifier", 582 "default link NvimIdentifierKey NvimIdentifier", 583 584 "default link NvimColon Delimiter", 585 "default link NvimComma Delimiter", 586 "default link NvimArrow Delimiter", 587 588 "default link NvimRegister SpecialChar", 589 "default link NvimNumber Number", 590 "default link NvimFloat NvimNumber", 591 "default link NvimNumberPrefix Type", 592 593 "default link NvimOptionSigil Type", 594 "default link NvimOptionName NvimIdentifier", 595 "default link NvimOptionScope NvimIdentifierScope", 596 "default link NvimOptionScopeDelimiter NvimIdentifierScopeDelimiter", 597 598 "default link NvimEnvironmentSigil NvimOptionSigil", 599 "default link NvimEnvironmentName NvimIdentifier", 600 601 "default link NvimString String", 602 "default link NvimStringBody NvimString", 603 "default link NvimStringQuote NvimString", 604 "default link NvimStringSpecial SpecialChar", 605 606 "default link NvimSingleQuote NvimStringQuote", 607 "default link NvimSingleQuotedBody NvimStringBody", 608 "default link NvimSingleQuotedQuote NvimStringSpecial", 609 610 "default link NvimDoubleQuote NvimStringQuote", 611 "default link NvimDoubleQuotedBody NvimStringBody", 612 "default link NvimDoubleQuotedEscape NvimStringSpecial", 613 614 "default link NvimFigureBrace NvimInternalError", 615 "default link NvimSingleQuotedUnknownEscape NvimInternalError", 616 617 "default link NvimSpacing Normal", 618 619 // NvimInvalid groups: 620 621 "default link NvimInvalidSingleQuotedUnknownEscape NvimInternalError", 622 623 "default link NvimInvalid Error", 624 625 "default link NvimInvalidAssignment NvimInvalid", 626 "default link NvimInvalidPlainAssignment NvimInvalidAssignment", 627 "default link NvimInvalidAugmentedAssignment NvimInvalidAssignment", 628 "default link NvimInvalidAssignmentWithAddition NvimInvalidAugmentedAssignment", 629 "default link NvimInvalidAssignmentWithSubtraction NvimInvalidAugmentedAssignment", 630 "default link NvimInvalidAssignmentWithConcatenation NvimInvalidAugmentedAssignment", 631 632 "default link NvimInvalidOperator NvimInvalid", 633 634 "default link NvimInvalidUnaryOperator NvimInvalidOperator", 635 "default link NvimInvalidUnaryPlus NvimInvalidUnaryOperator", 636 "default link NvimInvalidUnaryMinus NvimInvalidUnaryOperator", 637 "default link NvimInvalidNot NvimInvalidUnaryOperator", 638 639 "default link NvimInvalidBinaryOperator NvimInvalidOperator", 640 "default link NvimInvalidComparison NvimInvalidBinaryOperator", 641 "default link NvimInvalidComparisonModifier NvimInvalidComparison", 642 "default link NvimInvalidBinaryPlus NvimInvalidBinaryOperator", 643 "default link NvimInvalidBinaryMinus NvimInvalidBinaryOperator", 644 "default link NvimInvalidConcat NvimInvalidBinaryOperator", 645 "default link NvimInvalidConcatOrSubscript NvimInvalidConcat", 646 "default link NvimInvalidOr NvimInvalidBinaryOperator", 647 "default link NvimInvalidAnd NvimInvalidBinaryOperator", 648 "default link NvimInvalidMultiplication NvimInvalidBinaryOperator", 649 "default link NvimInvalidDivision NvimInvalidBinaryOperator", 650 "default link NvimInvalidMod NvimInvalidBinaryOperator", 651 652 "default link NvimInvalidTernary NvimInvalidOperator", 653 "default link NvimInvalidTernaryColon NvimInvalidTernary", 654 655 "default link NvimInvalidDelimiter NvimInvalid", 656 657 "default link NvimInvalidParenthesis NvimInvalidDelimiter", 658 "default link NvimInvalidLambda NvimInvalidParenthesis", 659 "default link NvimInvalidNestingParenthesis NvimInvalidParenthesis", 660 "default link NvimInvalidCallingParenthesis NvimInvalidParenthesis", 661 662 "default link NvimInvalidSubscript NvimInvalidParenthesis", 663 "default link NvimInvalidSubscriptBracket NvimInvalidSubscript", 664 "default link NvimInvalidSubscriptColon NvimInvalidSubscript", 665 "default link NvimInvalidCurly NvimInvalidSubscript", 666 667 "default link NvimInvalidContainer NvimInvalidParenthesis", 668 "default link NvimInvalidDict NvimInvalidContainer", 669 "default link NvimInvalidList NvimInvalidContainer", 670 671 "default link NvimInvalidValue NvimInvalid", 672 673 "default link NvimInvalidIdentifier NvimInvalidValue", 674 "default link NvimInvalidIdentifierScope NvimInvalidIdentifier", 675 "default link NvimInvalidIdentifierScopeDelimiter NvimInvalidIdentifier", 676 "default link NvimInvalidIdentifierName NvimInvalidIdentifier", 677 "default link NvimInvalidIdentifierKey NvimInvalidIdentifier", 678 679 "default link NvimInvalidColon NvimInvalidDelimiter", 680 "default link NvimInvalidComma NvimInvalidDelimiter", 681 "default link NvimInvalidArrow NvimInvalidDelimiter", 682 683 "default link NvimInvalidRegister NvimInvalidValue", 684 "default link NvimInvalidNumber NvimInvalidValue", 685 "default link NvimInvalidFloat NvimInvalidNumber", 686 "default link NvimInvalidNumberPrefix NvimInvalidNumber", 687 688 "default link NvimInvalidOptionSigil NvimInvalidIdentifier", 689 "default link NvimInvalidOptionName NvimInvalidIdentifier", 690 "default link NvimInvalidOptionScope NvimInvalidIdentifierScope", 691 "default link NvimInvalidOptionScopeDelimiter NvimInvalidIdentifierScopeDelimiter", 692 693 "default link NvimInvalidEnvironmentSigil NvimInvalidOptionSigil", 694 "default link NvimInvalidEnvironmentName NvimInvalidIdentifier", 695 696 // Invalid string bodies and specials are still highlighted as valid ones to 697 // minimize the red area. 698 "default link NvimInvalidString NvimInvalidValue", 699 "default link NvimInvalidStringBody NvimStringBody", 700 "default link NvimInvalidStringQuote NvimInvalidString", 701 "default link NvimInvalidStringSpecial NvimStringSpecial", 702 703 "default link NvimInvalidSingleQuote NvimInvalidStringQuote", 704 "default link NvimInvalidSingleQuotedBody NvimInvalidStringBody", 705 "default link NvimInvalidSingleQuotedQuote NvimInvalidStringSpecial", 706 707 "default link NvimInvalidDoubleQuote NvimInvalidStringQuote", 708 "default link NvimInvalidDoubleQuotedBody NvimInvalidStringBody", 709 "default link NvimInvalidDoubleQuotedEscape NvimInvalidStringSpecial", 710 "default link NvimInvalidDoubleQuotedUnknownEscape NvimInvalidValue", 711 712 "default link NvimInvalidFigureBrace NvimInvalidDelimiter", 713 714 "default link NvimInvalidSpacing ErrorMsg", 715 716 // Not actually invalid, but we show the user that they are doing something 717 // wrong. 718 "default link NvimDoubleQuotedUnknownEscape NvimInvalidValue", 719 NULL, 720 }; 721 722 /// Returns the number of highlight groups. 723 int highlight_num_groups(void) 724 { 725 return highlight_ga.ga_len; 726 } 727 728 /// Returns the name of a highlight group. 729 char *highlight_group_name(int id) 730 { 731 return hl_table[id].sg_name; 732 } 733 734 /// Returns the ID of the link to a highlight group. 735 int highlight_link_id(int id) 736 { 737 return hl_table[id].sg_link; 738 } 739 740 /// Create default links for Nvim* highlight groups used for cmdline coloring 741 void syn_init_cmdline_highlight(bool reset, bool init) 742 { 743 for (size_t i = 0; highlight_init_cmdline[i] != NULL; i++) { 744 do_highlight(highlight_init_cmdline[i], reset, init); 745 } 746 } 747 748 /// Load colors from a file if "g:colors_name" is set, otherwise load builtin 749 /// colors 750 /// 751 /// @param both include groups where 'bg' doesn't matter 752 /// @param reset clear groups first 753 void init_highlight(bool both, bool reset) 754 { 755 static bool had_both = false; 756 757 // Try finding the color scheme file. Used when a color file was loaded 758 // and 'background' or 't_Co' is changed. 759 char *p = get_var_value("g:colors_name"); 760 if (p != NULL) { 761 // Value of g:colors_name could be freed in load_colors() and make 762 // p invalid, so copy it. 763 char *copy_p = xstrdup(p); 764 bool okay = load_colors(copy_p); 765 xfree(copy_p); 766 if (okay) { 767 return; 768 } 769 } 770 771 // Didn't use a color file, use the compiled-in colors. 772 if (both) { 773 had_both = true; 774 const char *const *const pp = highlight_init_both; 775 for (size_t i = 0; pp[i] != NULL; i++) { 776 do_highlight(pp[i], reset, true); 777 } 778 } else if (!had_both) { 779 // Don't do anything before the call with both == true from main(). 780 // Not everything has been setup then, and that call will overrule 781 // everything anyway. 782 return; 783 } 784 785 const char *const *const pp = ((*p_bg == 'l') 786 ? highlight_init_light 787 : highlight_init_dark); 788 for (size_t i = 0; pp[i] != NULL; i++) { 789 do_highlight(pp[i], reset, true); 790 } 791 792 syn_init_cmdline_highlight(false, false); 793 } 794 795 /// Load color file "name". 796 /// 797 /// @return OK for success, FAIL for failure. 798 int load_colors(char *name) 799 { 800 static bool recursive = false; 801 802 // When being called recursively, this is probably because setting 803 // 'background' caused the highlighting to be reloaded. This means it is 804 // working, thus we should return OK. 805 if (recursive) { 806 return OK; 807 } 808 809 recursive = true; 810 size_t buflen = strlen(name) + 12; 811 char *buf = xmalloc(buflen); 812 apply_autocmds(EVENT_COLORSCHEMEPRE, name, curbuf->b_fname, false, curbuf); 813 snprintf(buf, buflen, "colors/%s.*", name); 814 int retval = source_runtime_vim_lua(buf, DIP_START + DIP_OPT); 815 xfree(buf); 816 if (retval == OK) { 817 apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, false, curbuf); 818 } 819 820 recursive = false; 821 822 return retval; 823 } 824 825 static char *(color_names[28]) = { 826 "Black", "DarkBlue", "DarkGreen", "DarkCyan", 827 "DarkRed", "DarkMagenta", "Brown", "DarkYellow", 828 "Gray", "Grey", "LightGray", "LightGrey", 829 "DarkGray", "DarkGrey", 830 "Blue", "LightBlue", "Green", "LightGreen", 831 "Cyan", "LightCyan", "Red", "LightRed", "Magenta", 832 "LightMagenta", "Yellow", "LightYellow", "White", "NONE" 833 }; 834 // indices: 835 // 0, 1, 2, 3, 836 // 4, 5, 6, 7, 837 // 8, 9, 10, 11, 838 // 12, 13, 839 // 14, 15, 16, 17, 840 // 18, 19, 20, 21, 22, 841 // 23, 24, 25, 26, 27 842 static int color_numbers_16[28] = { 0, 1, 2, 3, 843 4, 5, 6, 6, 844 7, 7, 7, 7, 845 8, 8, 846 9, 9, 10, 10, 847 11, 11, 12, 12, 13, 848 13, 14, 14, 15, -1 }; 849 // for xterm with 88 colors... 850 static int color_numbers_88[28] = { 0, 4, 2, 6, 851 1, 5, 32, 72, 852 84, 84, 7, 7, 853 82, 82, 854 12, 43, 10, 61, 855 14, 63, 9, 74, 13, 856 75, 11, 78, 15, -1 }; 857 // for xterm with 256 colors... 858 static int color_numbers_256[28] = { 0, 4, 2, 6, 859 1, 5, 130, 3, 860 248, 248, 7, 7, 861 242, 242, 862 12, 81, 10, 121, 863 14, 159, 9, 224, 13, 864 225, 11, 229, 15, -1 }; 865 // for terminals with less than 16 colors... 866 static int color_numbers_8[28] = { 0, 4, 2, 6, 867 1, 5, 3, 3, 868 7, 7, 7, 7, 869 0 + 8, 0 + 8, 870 4 + 8, 4 + 8, 2 + 8, 2 + 8, 871 6 + 8, 6 + 8, 1 + 8, 1 + 8, 5 + 8, 872 5 + 8, 3 + 8, 3 + 8, 7 + 8, -1 }; 873 874 // Lookup the "cterm" value to be used for color with index "idx" in 875 // color_names[]. 876 // "boldp" will be set to kTrue or kFalse for a foreground color when using 8 877 // colors, otherwise it will be unchanged. 878 static int lookup_color(const int idx, const bool foreground, TriState *const boldp) 879 { 880 int color = color_numbers_16[idx]; 881 882 // Use the _16 table to check if it's a valid color name. 883 if (color < 0) { 884 return -1; 885 } 886 887 if (t_colors == 8) { 888 // t_Co is 8: use the 8 colors table 889 color = color_numbers_8[idx]; 890 if (foreground) { 891 // set/reset bold attribute to get light foreground 892 // colors (on some terminals, e.g. "linux") 893 if (color & 8) { 894 *boldp = kTrue; 895 } else { 896 *boldp = kFalse; 897 } 898 } 899 color &= 7; // truncate to 8 colors 900 } else if (t_colors == 16) { 901 color = color_numbers_8[idx]; 902 } else if (t_colors == 88) { 903 color = color_numbers_88[idx]; 904 } else if (t_colors >= 256) { 905 color = color_numbers_256[idx]; 906 } 907 return color; 908 } 909 910 void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id) 911 { 912 int idx = id - 1; // Index is ID minus one. 913 bool is_default = attrs.rgb_ae_attr & HL_DEFAULT; 914 915 // Return if "default" was used and the group already has settings 916 if (is_default && hl_has_settings(idx, true) && !dict->force) { 917 return; 918 } 919 920 HlGroup *g = &hl_table[idx]; 921 g->sg_cleared = false; 922 923 if (link_id > 0) { 924 g->sg_link = link_id; 925 g->sg_script_ctx = current_sctx; 926 g->sg_script_ctx.sc_lnum += SOURCING_LNUM; 927 nlua_set_sctx(&g->sg_script_ctx); 928 g->sg_set |= SG_LINK; 929 if (is_default) { 930 g->sg_deflink = link_id; 931 g->sg_deflink_sctx = current_sctx; 932 g->sg_deflink_sctx.sc_lnum += SOURCING_LNUM; 933 nlua_set_sctx(&g->sg_deflink_sctx); 934 } 935 } else { 936 g->sg_link = 0; 937 } 938 939 g->sg_gui = attrs.rgb_ae_attr &~HL_DEFAULT; 940 941 g->sg_rgb_fg = attrs.rgb_fg_color; 942 g->sg_rgb_bg = attrs.rgb_bg_color; 943 g->sg_rgb_sp = attrs.rgb_sp_color; 944 945 struct { 946 int *dest; RgbValue val; Object name; 947 } cattrs[] = { 948 { &g->sg_rgb_fg_idx, g->sg_rgb_fg, 949 HAS_KEY(dict, highlight, fg) ? dict->fg : dict->foreground }, 950 { &g->sg_rgb_bg_idx, g->sg_rgb_bg, 951 HAS_KEY(dict, highlight, bg) ? dict->bg : dict->background }, 952 { &g->sg_rgb_sp_idx, g->sg_rgb_sp, HAS_KEY(dict, highlight, sp) ? dict->sp : dict->special }, 953 { NULL, -1, NIL }, 954 }; 955 956 for (int j = 0; cattrs[j].dest; j++) { 957 if (cattrs[j].val < 0) { 958 *cattrs[j].dest = kColorIdxNone; 959 } else if (cattrs[j].name.type == kObjectTypeString && cattrs[j].name.data.string.size) { 960 name_to_color(cattrs[j].name.data.string.data, cattrs[j].dest); 961 } else { 962 *cattrs[j].dest = kColorIdxHex; 963 } 964 } 965 966 g->sg_cterm = attrs.cterm_ae_attr &~HL_DEFAULT; 967 g->sg_cterm_bg = attrs.cterm_bg_color; 968 g->sg_cterm_fg = attrs.cterm_fg_color; 969 g->sg_cterm_bold = g->sg_cterm & HL_BOLD; 970 g->sg_blend = attrs.hl_blend; 971 972 g->sg_script_ctx = current_sctx; 973 g->sg_script_ctx.sc_lnum += SOURCING_LNUM; 974 nlua_set_sctx(&g->sg_script_ctx); 975 976 g->sg_attr = hl_get_syn_attr(0, id, attrs); 977 978 // 'Normal' is special 979 if (strcmp(g->sg_name_u, "NORMAL") == 0) { 980 cterm_normal_fg_color = g->sg_cterm_fg; 981 cterm_normal_bg_color = g->sg_cterm_bg; 982 bool did_changed = false; 983 if (normal_bg != g->sg_rgb_bg || normal_fg != g->sg_rgb_fg || normal_sp != g->sg_rgb_sp) { 984 did_changed = true; 985 } 986 normal_fg = g->sg_rgb_fg; 987 normal_bg = g->sg_rgb_bg; 988 normal_sp = g->sg_rgb_sp; 989 990 if (did_changed) { 991 highlight_attr_set_all(); 992 } 993 ui_default_colors_set(); 994 } else { 995 // a cursor style uses this syn_id, make sure its attribute is updated. 996 if (cursor_mode_uses_syn_id(id)) { 997 ui_mode_info_set(); 998 } 999 } 1000 1001 if (!updating_screen) { 1002 redraw_all_later(UPD_NOT_VALID); 1003 } 1004 need_highlight_changed = true; 1005 } 1006 1007 /// Handle ":highlight" command 1008 /// 1009 /// When using ":highlight clear" this is called recursively for each group with 1010 /// forceit and init being both true. 1011 /// 1012 /// @param[in] line Command arguments. 1013 /// @param[in] forceit True when bang is given, allows to link group even if 1014 /// it has its own settings. 1015 /// @param[in] init True when initializing. 1016 void do_highlight(const char *line, const bool forceit, const bool init) 1017 FUNC_ATTR_NONNULL_ALL 1018 { 1019 // If no argument, list current highlighting. 1020 if (!init && ends_excmd((uint8_t)(*line))) { 1021 msg_ext_set_kind("list_cmd"); 1022 for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) { 1023 // TODO(brammool): only call when the group has attributes set 1024 highlight_list_one(i); 1025 } 1026 return; 1027 } 1028 1029 bool dodefault = false; 1030 1031 // Isolate the name. 1032 const char *name_end = skiptowhite(line); 1033 const char *linep = skipwhite(name_end); 1034 1035 // Check for "default" argument. 1036 if (strncmp(line, "default", (size_t)(name_end - line)) == 0) { 1037 dodefault = true; 1038 line = linep; 1039 name_end = skiptowhite(line); 1040 linep = skipwhite(name_end); 1041 } 1042 1043 bool doclear = false; 1044 bool dolink = false; 1045 1046 // Check for "clear" or "link" argument. 1047 if (strncmp(line, "clear", (size_t)(name_end - line)) == 0) { 1048 doclear = true; 1049 } else if (strncmp(line, "link", (size_t)(name_end - line)) == 0) { 1050 dolink = true; 1051 } 1052 1053 // ":highlight {group-name}": list highlighting for one group. 1054 if (!doclear && !dolink && ends_excmd((uint8_t)(*linep))) { 1055 int id = syn_name2id_len(line, (size_t)(name_end - line)); 1056 if (id == 0) { 1057 semsg(_(e_highlight_group_name_not_found_str), line); 1058 } else { 1059 msg_ext_set_kind("list_cmd"); 1060 highlight_list_one(id); 1061 } 1062 return; 1063 } 1064 1065 // Handle ":highlight link {from} {to}" command. 1066 if (dolink) { 1067 const char *from_start = linep; 1068 int to_id; 1069 HlGroup *hlgroup = NULL; 1070 1071 const char *from_end = skiptowhite(from_start); 1072 const char *to_start = skipwhite(from_end); 1073 const char *to_end = skiptowhite(to_start); 1074 1075 if (ends_excmd((uint8_t)(*from_start)) 1076 || ends_excmd((uint8_t)(*to_start))) { 1077 semsg(_("E412: Not enough arguments: \":highlight link %s\""), 1078 from_start); 1079 return; 1080 } 1081 1082 if (!ends_excmd(*skipwhite(to_end))) { 1083 semsg(_("E413: Too many arguments: \":highlight link %s\""), from_start); 1084 return; 1085 } 1086 1087 int from_id = syn_check_group(from_start, (size_t)(from_end - from_start)); 1088 if (strncmp(to_start, "NONE", 4) == 0) { 1089 to_id = 0; 1090 } else { 1091 to_id = syn_check_group(to_start, (size_t)(to_end - to_start)); 1092 } 1093 1094 if (from_id > 0) { 1095 hlgroup = &hl_table[from_id - 1]; 1096 if (dodefault && (forceit || hlgroup->sg_deflink == 0)) { 1097 hlgroup->sg_deflink = to_id; 1098 hlgroup->sg_deflink_sctx = current_sctx; 1099 hlgroup->sg_deflink_sctx.sc_lnum += SOURCING_LNUM; 1100 nlua_set_sctx(&hlgroup->sg_deflink_sctx); 1101 } 1102 } 1103 1104 if (from_id > 0 && (!init || hlgroup->sg_set == 0)) { 1105 // Don't allow a link when there already is some highlighting 1106 // for the group, unless '!' is used 1107 if (to_id > 0 && !forceit && !init 1108 && hl_has_settings(from_id - 1, dodefault)) { 1109 if (SOURCING_NAME == NULL && !dodefault) { 1110 emsg(_(e_group_has_settings_highlight_link_ignored)); 1111 } 1112 } else if (hlgroup->sg_link != to_id 1113 || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid 1114 || hlgroup->sg_cleared) { 1115 if (!init) { 1116 hlgroup->sg_set |= SG_LINK; 1117 } 1118 hlgroup->sg_link = to_id; 1119 hlgroup->sg_script_ctx = current_sctx; 1120 hlgroup->sg_script_ctx.sc_lnum += SOURCING_LNUM; 1121 nlua_set_sctx(&hlgroup->sg_script_ctx); 1122 hlgroup->sg_cleared = false; 1123 redraw_all_later(UPD_SOME_VALID); 1124 1125 // Only call highlight changed() once after multiple changes 1126 need_highlight_changed = true; 1127 } 1128 } 1129 1130 return; 1131 } 1132 1133 if (doclear) { 1134 // ":highlight clear [group]" command. 1135 line = linep; 1136 if (ends_excmd((uint8_t)(*line))) { 1137 do_unlet(S_LEN("g:colors_name"), true); 1138 restore_cterm_colors(); 1139 1140 // Clear all default highlight groups and load the defaults. 1141 for (int j = 0; j < highlight_ga.ga_len; j++) { 1142 highlight_clear(j); 1143 } 1144 init_highlight(true, true); 1145 highlight_changed(); 1146 redraw_all_later(UPD_NOT_VALID); 1147 return; 1148 } 1149 name_end = skiptowhite(line); 1150 linep = skipwhite(name_end); 1151 } 1152 1153 // Find the group name in the table. If it does not exist yet, add it. 1154 int id = syn_check_group(line, (size_t)(name_end - line)); 1155 if (id == 0) { // Failed (out of memory). 1156 return; 1157 } 1158 int idx = id - 1; // Index is ID minus one. 1159 1160 // Return if "default" was used and the group already has settings 1161 if (dodefault && hl_has_settings(idx, true)) { 1162 return; 1163 } 1164 1165 // Make a copy so we can check if any attribute actually changed 1166 HlGroup item_before = hl_table[idx]; 1167 bool is_normal_group = (strcmp(hl_table[idx].sg_name_u, "NORMAL") == 0); 1168 1169 // Clear the highlighting for ":hi clear {group}" and ":hi clear". 1170 if (doclear || (forceit && init)) { 1171 highlight_clear(idx); 1172 if (!doclear) { 1173 hl_table[idx].sg_set = 0; 1174 } 1175 } 1176 1177 bool did_change = false; 1178 bool error = false; 1179 1180 char key[64]; 1181 char arg[512]; 1182 if (!doclear) { 1183 const char *arg_start; 1184 1185 while (!ends_excmd((uint8_t)(*linep))) { 1186 const char *key_start = linep; 1187 if (*linep == '=') { 1188 semsg(_(e_unexpected_equal_sign_str), key_start); 1189 error = true; 1190 break; 1191 } 1192 1193 // Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg", 1194 // "guibg" or "guisp"). 1195 while (*linep && !ascii_iswhite(*linep) && *linep != '=') { 1196 linep++; 1197 } 1198 size_t key_len = (size_t)(linep - key_start); 1199 if (key_len > sizeof(key) - 1) { 1200 emsg(_("E423: Illegal argument")); 1201 error = true; 1202 break; 1203 } 1204 vim_memcpy_up(key, key_start, key_len); 1205 key[key_len] = NUL; 1206 linep = skipwhite(linep); 1207 1208 if (strcmp(key, "NONE") == 0) { 1209 if (!init || hl_table[idx].sg_set == 0) { 1210 if (!init) { 1211 hl_table[idx].sg_set |= SG_CTERM + SG_GUI; 1212 } 1213 highlight_clear(idx); 1214 } 1215 continue; 1216 } 1217 1218 // Check for the equal sign. 1219 if (*linep != '=') { 1220 semsg(_(e_missing_equal_sign_str_2), key_start); 1221 error = true; 1222 break; 1223 } 1224 linep++; 1225 1226 // Isolate the argument. 1227 linep = skipwhite(linep); 1228 if (*linep == '\'') { // guifg='color name' 1229 arg_start = ++linep; 1230 linep = strchr(linep, '\''); 1231 if (linep == NULL) { 1232 semsg(_(e_invarg2), key_start); 1233 error = true; 1234 break; 1235 } 1236 } else { 1237 arg_start = linep; 1238 linep = skiptowhite(linep); 1239 } 1240 if (linep == arg_start) { 1241 semsg(_(e_missing_argument_str), key_start); 1242 error = true; 1243 break; 1244 } 1245 size_t arg_len = (size_t)(linep - arg_start); 1246 if (arg_len > sizeof(arg) - 1) { 1247 emsg(_("E423: Illegal argument")); 1248 error = true; 1249 break; 1250 } 1251 memcpy(arg, arg_start, arg_len); 1252 arg[arg_len] = NUL; 1253 1254 if (*linep == '\'') { 1255 linep++; 1256 } 1257 1258 // Store the argument. 1259 if (strcmp(key, "TERM") == 0 1260 || strcmp(key, "CTERM") == 0 1261 || strcmp(key, "GUI") == 0) { 1262 int attr = 0; 1263 int off = 0; 1264 int i; 1265 while (arg[off] != NUL) { 1266 for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) { 1267 int len = (int)strlen(hl_name_table[i]); 1268 if (STRNICMP(arg + off, hl_name_table[i], len) == 0) { 1269 if (hl_attr_table[i] & HL_UNDERLINE_MASK) { 1270 attr &= ~HL_UNDERLINE_MASK; 1271 } 1272 attr |= hl_attr_table[i]; 1273 off += len; 1274 break; 1275 } 1276 } 1277 if (i < 0) { 1278 semsg(_("E418: Illegal value: %s"), arg); 1279 error = true; 1280 break; 1281 } 1282 if (arg[off] == ',') { // Another one follows. 1283 off++; 1284 } 1285 } 1286 if (error) { 1287 break; 1288 } 1289 if (*key == 'C') { 1290 if (!init || !(hl_table[idx].sg_set & SG_CTERM)) { 1291 if (!init) { 1292 hl_table[idx].sg_set |= SG_CTERM; 1293 } 1294 hl_table[idx].sg_cterm = attr; 1295 hl_table[idx].sg_cterm_bold = false; 1296 } 1297 } else if (*key == 'G') { 1298 if (!init || !(hl_table[idx].sg_set & SG_GUI)) { 1299 if (!init) { 1300 hl_table[idx].sg_set |= SG_GUI; 1301 } 1302 hl_table[idx].sg_gui = attr; 1303 } 1304 } 1305 } else if (strcmp(key, "FONT") == 0) { 1306 // in non-GUI fonts are simply ignored 1307 } else if (strcmp(key, "CTERMFG") == 0 || strcmp(key, "CTERMBG") == 0) { 1308 if (!init || !(hl_table[idx].sg_set & SG_CTERM)) { 1309 if (!init) { 1310 hl_table[idx].sg_set |= SG_CTERM; 1311 } 1312 1313 // When setting the foreground color, and previously the "bold" 1314 // flag was set for a light color, reset it now 1315 if (key[5] == 'F' && hl_table[idx].sg_cterm_bold) { 1316 hl_table[idx].sg_cterm &= ~HL_BOLD; 1317 hl_table[idx].sg_cterm_bold = false; 1318 } 1319 1320 int color; 1321 if (ascii_isdigit(*arg)) { 1322 color = atoi(arg); 1323 } else if (STRICMP(arg, "fg") == 0) { 1324 if (cterm_normal_fg_color) { 1325 color = cterm_normal_fg_color - 1; 1326 } else { 1327 emsg(_("E419: FG color unknown")); 1328 error = true; 1329 break; 1330 } 1331 } else if (STRICMP(arg, "bg") == 0) { 1332 if (cterm_normal_bg_color > 0) { 1333 color = cterm_normal_bg_color - 1; 1334 } else { 1335 emsg(_("E420: BG color unknown")); 1336 error = true; 1337 break; 1338 } 1339 } else { 1340 // Reduce calls to STRICMP a bit, it can be slow. 1341 int off = TOUPPER_ASC(*arg); 1342 int i; 1343 for (i = ARRAY_SIZE(color_names); --i >= 0;) { 1344 if (off == color_names[i][0] 1345 && STRICMP(arg + 1, color_names[i] + 1) == 0) { 1346 break; 1347 } 1348 } 1349 if (i < 0) { 1350 semsg(_("E421: Color name or number not recognized: %s"), 1351 key_start); 1352 error = true; 1353 break; 1354 } 1355 1356 TriState bold = kNone; 1357 color = lookup_color(i, key[5] == 'F', &bold); 1358 1359 // set/reset bold attribute to get light foreground 1360 // colors (on some terminals, e.g. "linux") 1361 if (bold == kTrue) { 1362 hl_table[idx].sg_cterm |= HL_BOLD; 1363 hl_table[idx].sg_cterm_bold = true; 1364 } else if (bold == kFalse) { 1365 hl_table[idx].sg_cterm &= ~HL_BOLD; 1366 } 1367 } 1368 // Add one to the argument, to avoid zero. Zero is used for 1369 // "NONE", then "color" is -1. 1370 if (key[5] == 'F') { 1371 hl_table[idx].sg_cterm_fg = color + 1; 1372 if (is_normal_group) { 1373 cterm_normal_fg_color = color + 1; 1374 } 1375 } else { 1376 hl_table[idx].sg_cterm_bg = color + 1; 1377 if (is_normal_group) { 1378 cterm_normal_bg_color = color + 1; 1379 if (!ui_rgb_attached()) { 1380 if (color >= 0) { 1381 int dark = -1; 1382 1383 if (t_colors < 16) { 1384 dark = (color == 0 || color == 4); 1385 } else if (color < 16) { 1386 // Limit the heuristic to the standard 16 colors 1387 dark = (color < 7 || color == 8); 1388 } 1389 // Set the 'background' option if the value is 1390 // wrong. 1391 if (dark != -1 1392 && dark != (*p_bg == 'd') 1393 && !option_was_set(kOptBackground)) { 1394 set_option_value_give_err(kOptBackground, 1395 CSTR_AS_OPTVAL(dark ? "dark" : "light"), 0); 1396 reset_option_was_set(kOptBackground); 1397 } 1398 } 1399 } 1400 } 1401 } 1402 } 1403 } else if (strcmp(key, "GUIFG") == 0) { 1404 int *indexp = &hl_table[idx].sg_rgb_fg_idx; 1405 1406 if (!init || !(hl_table[idx].sg_set & SG_GUI)) { 1407 if (!init) { 1408 hl_table[idx].sg_set |= SG_GUI; 1409 } 1410 1411 RgbValue old_color = hl_table[idx].sg_rgb_fg; 1412 int old_idx = hl_table[idx].sg_rgb_fg_idx; 1413 1414 if (strcmp(arg, "NONE") != 0) { 1415 hl_table[idx].sg_rgb_fg = name_to_color(arg, indexp); 1416 } else { 1417 hl_table[idx].sg_rgb_fg = -1; 1418 hl_table[idx].sg_rgb_fg_idx = kColorIdxNone; 1419 } 1420 1421 did_change = hl_table[idx].sg_rgb_fg != old_color || hl_table[idx].sg_rgb_fg != old_idx; 1422 } 1423 1424 if (is_normal_group) { 1425 normal_fg = hl_table[idx].sg_rgb_fg; 1426 } 1427 } else if (strcmp(key, "GUIBG") == 0) { 1428 int *indexp = &hl_table[idx].sg_rgb_bg_idx; 1429 1430 if (!init || !(hl_table[idx].sg_set & SG_GUI)) { 1431 if (!init) { 1432 hl_table[idx].sg_set |= SG_GUI; 1433 } 1434 1435 RgbValue old_color = hl_table[idx].sg_rgb_bg; 1436 int old_idx = hl_table[idx].sg_rgb_bg_idx; 1437 1438 if (strcmp(arg, "NONE") != 0) { 1439 hl_table[idx].sg_rgb_bg = name_to_color(arg, indexp); 1440 } else { 1441 hl_table[idx].sg_rgb_bg = -1; 1442 hl_table[idx].sg_rgb_bg_idx = kColorIdxNone; 1443 } 1444 1445 did_change = hl_table[idx].sg_rgb_bg != old_color || hl_table[idx].sg_rgb_bg != old_idx; 1446 } 1447 1448 if (is_normal_group) { 1449 normal_bg = hl_table[idx].sg_rgb_bg; 1450 } 1451 } else if (strcmp(key, "GUISP") == 0) { 1452 int *indexp = &hl_table[idx].sg_rgb_sp_idx; 1453 1454 if (!init || !(hl_table[idx].sg_set & SG_GUI)) { 1455 if (!init) { 1456 hl_table[idx].sg_set |= SG_GUI; 1457 } 1458 1459 RgbValue old_color = hl_table[idx].sg_rgb_sp; 1460 int old_idx = hl_table[idx].sg_rgb_sp_idx; 1461 1462 if (strcmp(arg, "NONE") != 0) { 1463 hl_table[idx].sg_rgb_sp = name_to_color(arg, indexp); 1464 } else { 1465 hl_table[idx].sg_rgb_sp = -1; 1466 } 1467 1468 did_change = hl_table[idx].sg_rgb_sp != old_color || hl_table[idx].sg_rgb_sp != old_idx; 1469 } 1470 1471 if (is_normal_group) { 1472 normal_sp = hl_table[idx].sg_rgb_sp; 1473 } 1474 } else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) { 1475 // Ignored for now 1476 } else if (strcmp(key, "BLEND") == 0) { 1477 if (strcmp(arg, "NONE") != 0) { 1478 hl_table[idx].sg_blend = (int)strtol(arg, NULL, 10); 1479 } else { 1480 hl_table[idx].sg_blend = -1; 1481 } 1482 } else { 1483 semsg(_("E423: Illegal argument: %s"), key_start); 1484 error = true; 1485 break; 1486 } 1487 hl_table[idx].sg_cleared = false; 1488 1489 // When highlighting has been given for a group, don't link it. 1490 if (!init || !(hl_table[idx].sg_set & SG_LINK)) { 1491 hl_table[idx].sg_link = 0; 1492 } 1493 1494 // Continue with next argument. 1495 linep = skipwhite(linep); 1496 } 1497 } 1498 1499 bool did_highlight_changed = false; 1500 1501 if (!error && is_normal_group) { 1502 // Need to update all groups, because they might be using "bg" and/or 1503 // "fg", which have been changed now. 1504 highlight_attr_set_all(); 1505 1506 if (!ui_has(kUILinegrid) && starting == 0) { 1507 // Older UIs assume that we clear the screen after normal group is 1508 // changed 1509 ui_refresh(); 1510 } else { 1511 // TUI and newer UIs will repaint the screen themselves. UPD_NOT_VALID 1512 // redraw below will still handle usages of guibg=fg etc. 1513 ui_default_colors_set(); 1514 } 1515 did_highlight_changed = true; 1516 redraw_all_later(UPD_NOT_VALID); 1517 } else { 1518 set_hl_attr(idx); 1519 } 1520 hl_table[idx].sg_script_ctx = current_sctx; 1521 hl_table[idx].sg_script_ctx.sc_lnum += SOURCING_LNUM; 1522 nlua_set_sctx(&hl_table[idx].sg_script_ctx); 1523 1524 // Only call highlight_changed() once, after a sequence of highlight 1525 // commands, and only if an attribute actually changed 1526 if ((did_change 1527 || memcmp(&hl_table[idx], &item_before, sizeof(item_before)) != 0) 1528 && !did_highlight_changed) { 1529 // Do not trigger a redraw when highlighting is changed while 1530 // redrawing. This may happen when evaluating 'statusline' changes the 1531 // StatusLine group. 1532 if (!updating_screen) { 1533 redraw_all_later(UPD_NOT_VALID); 1534 } 1535 need_highlight_changed = true; 1536 } 1537 } 1538 1539 #if defined(EXITFREE) 1540 void free_highlight(void) 1541 { 1542 ga_clear(&highlight_ga); 1543 map_destroy(cstr_t, &highlight_unames); 1544 arena_mem_free(arena_finish(&highlight_arena)); 1545 } 1546 1547 #endif 1548 1549 /// Reset the cterm colors to what they were before Vim was started, if 1550 /// possible. Otherwise reset them to zero. 1551 void restore_cterm_colors(void) 1552 { 1553 normal_fg = -1; 1554 normal_bg = -1; 1555 normal_sp = -1; 1556 cterm_normal_fg_color = 0; 1557 cterm_normal_bg_color = 0; 1558 } 1559 1560 /// @param check_link if true also check for an existing link. 1561 /// 1562 /// @return true if highlight group "idx" has any settings. 1563 static bool hl_has_settings(int idx, bool check_link) 1564 { 1565 return hl_table[idx].sg_cleared == 0 1566 && (hl_table[idx].sg_attr != 0 1567 || hl_table[idx].sg_cterm_fg != 0 1568 || hl_table[idx].sg_cterm_bg != 0 1569 || hl_table[idx].sg_rgb_fg_idx != kColorIdxNone 1570 || hl_table[idx].sg_rgb_bg_idx != kColorIdxNone 1571 || hl_table[idx].sg_rgb_sp_idx != kColorIdxNone 1572 || (check_link && (hl_table[idx].sg_set & SG_LINK))); 1573 } 1574 1575 /// Clear highlighting for one group. 1576 static void highlight_clear(int idx) 1577 { 1578 hl_table[idx].sg_cleared = true; 1579 1580 hl_table[idx].sg_attr = 0; 1581 hl_table[idx].sg_cterm = 0; 1582 hl_table[idx].sg_cterm_bold = false; 1583 hl_table[idx].sg_cterm_fg = 0; 1584 hl_table[idx].sg_cterm_bg = 0; 1585 hl_table[idx].sg_gui = 0; 1586 hl_table[idx].sg_rgb_fg = -1; 1587 hl_table[idx].sg_rgb_bg = -1; 1588 hl_table[idx].sg_rgb_sp = -1; 1589 hl_table[idx].sg_rgb_fg_idx = kColorIdxNone; 1590 hl_table[idx].sg_rgb_bg_idx = kColorIdxNone; 1591 hl_table[idx].sg_rgb_sp_idx = kColorIdxNone; 1592 hl_table[idx].sg_blend = -1; 1593 // Restore default link and context if they exist. Otherwise clears. 1594 hl_table[idx].sg_link = hl_table[idx].sg_deflink; 1595 // Since we set the default link, set the location to where the default 1596 // link was set. 1597 hl_table[idx].sg_script_ctx = hl_table[idx].sg_deflink_sctx; 1598 } 1599 1600 /// \addtogroup LIST_XXX 1601 /// @{ 1602 #define LIST_ATTR 1 1603 #define LIST_STRING 2 1604 #define LIST_INT 3 1605 /// @} 1606 1607 static void highlight_list_one(const int id) 1608 { 1609 const HlGroup *sgp = &hl_table[id - 1]; // index is ID minus one 1610 bool didh = false; 1611 1612 if (message_filtered(sgp->sg_name)) { 1613 return; 1614 } 1615 1616 // don't list specialized groups if a parent is used instead 1617 if (sgp->sg_parent && sgp->sg_cleared) { 1618 return; 1619 } 1620 1621 didh = highlight_list_arg(id, didh, LIST_ATTR, 1622 sgp->sg_cterm, NULL, "cterm"); 1623 didh = highlight_list_arg(id, didh, LIST_INT, 1624 sgp->sg_cterm_fg, NULL, "ctermfg"); 1625 didh = highlight_list_arg(id, didh, LIST_INT, 1626 sgp->sg_cterm_bg, NULL, "ctermbg"); 1627 1628 didh = highlight_list_arg(id, didh, LIST_ATTR, 1629 sgp->sg_gui, NULL, "gui"); 1630 char hexbuf[8]; 1631 didh = highlight_list_arg(id, didh, LIST_STRING, 0, 1632 coloridx_to_name(sgp->sg_rgb_fg_idx, sgp->sg_rgb_fg, hexbuf), "guifg"); 1633 didh = highlight_list_arg(id, didh, LIST_STRING, 0, 1634 coloridx_to_name(sgp->sg_rgb_bg_idx, sgp->sg_rgb_bg, hexbuf), "guibg"); 1635 didh = highlight_list_arg(id, didh, LIST_STRING, 0, 1636 coloridx_to_name(sgp->sg_rgb_sp_idx, sgp->sg_rgb_sp, hexbuf), "guisp"); 1637 1638 didh = highlight_list_arg(id, didh, LIST_INT, 1639 sgp->sg_blend + 1, NULL, "blend"); 1640 1641 if (sgp->sg_link && !got_int) { 1642 syn_list_header(didh, 0, id, true); 1643 didh = true; 1644 msg_puts_hl("links to", HLF_D, false); 1645 msg_putchar(' '); 1646 msg_outtrans(hl_table[hl_table[id - 1].sg_link - 1].sg_name, 0, false); 1647 } 1648 1649 if (!didh) { 1650 highlight_list_arg(id, didh, LIST_STRING, 0, "cleared", ""); 1651 } 1652 if (p_verbose > 0) { 1653 last_set_msg(sgp->sg_script_ctx); 1654 } 1655 } 1656 1657 static bool hlgroup2dict(Dict *hl, NS ns_id, int hl_id, Arena *arena) 1658 { 1659 HlGroup *sgp = &hl_table[hl_id - 1]; 1660 int link = ns_id == 0 ? sgp->sg_link : ns_get_hl(&ns_id, hl_id, true, sgp->sg_set); 1661 if (link == -1) { 1662 return false; 1663 } 1664 if (ns_id == 0 && sgp->sg_cleared && sgp->sg_set == 0) { 1665 // table entry was created but not ever set 1666 return false; 1667 } 1668 HlAttrs attr = 1669 syn_attr2entry(ns_id == 0 ? sgp->sg_attr : ns_get_hl(&ns_id, hl_id, false, sgp->sg_set)); 1670 *hl = arena_dict(arena, HLATTRS_DICT_SIZE + 1); 1671 if (attr.rgb_ae_attr & HL_DEFAULT) { 1672 PUT_C(*hl, "default", BOOLEAN_OBJ(true)); 1673 } 1674 if (link > 0) { 1675 assert(1 <= link && link <= highlight_ga.ga_len); 1676 PUT_C(*hl, "link", CSTR_AS_OBJ(hl_table[link - 1].sg_name)); 1677 } 1678 Dict hl_cterm = arena_dict(arena, HLATTRS_DICT_SIZE); 1679 hlattrs2dict(hl, NULL, attr, true, true); 1680 hlattrs2dict(hl, &hl_cterm, attr, false, true); 1681 if (kv_size(hl_cterm)) { 1682 PUT_C(*hl, "cterm", DICT_OBJ(hl_cterm)); 1683 } 1684 return true; 1685 } 1686 1687 Dict ns_get_hl_defs(NS ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err) 1688 { 1689 Boolean link = GET_BOOL_OR_TRUE(opts, get_highlight, link); 1690 int id = -1; 1691 if (HAS_KEY(opts, get_highlight, name)) { 1692 Boolean create = GET_BOOL_OR_TRUE(opts, get_highlight, create); 1693 id = create ? syn_check_group(opts->name.data, opts->name.size) 1694 : syn_name2id_len(opts->name.data, opts->name.size); 1695 if (id == 0 && !create) { 1696 Dict attrs = ARRAY_DICT_INIT; 1697 return attrs; 1698 } 1699 } else if (HAS_KEY(opts, get_highlight, id)) { 1700 id = (int)opts->id; 1701 } 1702 1703 if (id != -1) { 1704 VALIDATE(1 <= id && id <= highlight_ga.ga_len, "%s", "Highlight id out of bounds", { 1705 goto cleanup; 1706 }); 1707 Dict attrs = ARRAY_DICT_INIT; 1708 hlgroup2dict(&attrs, ns_id, link ? id : syn_get_final_id(id), arena); 1709 return attrs; 1710 } 1711 if (ERROR_SET(err)) { 1712 goto cleanup; 1713 } 1714 1715 Dict rv = arena_dict(arena, (size_t)highlight_ga.ga_len); 1716 for (int i = 1; i <= highlight_ga.ga_len; i++) { 1717 Dict attrs = ARRAY_DICT_INIT; 1718 if (!hlgroup2dict(&attrs, ns_id, i, arena)) { 1719 continue; 1720 } 1721 PUT_C(rv, hl_table[(link ? i : syn_get_final_id(i)) - 1].sg_name, DICT_OBJ(attrs)); 1722 } 1723 1724 return rv; 1725 1726 cleanup: 1727 return (Dict)ARRAY_DICT_INIT; 1728 } 1729 1730 /// Outputs a highlight when doing ":hi MyHighlight" 1731 /// 1732 /// @param type one of \ref LIST_XXX 1733 /// @param iarg integer argument used if \p type == LIST_INT 1734 /// @param sarg string used if \p type == LIST_STRING 1735 static bool highlight_list_arg(const int id, bool didh, const int type, int iarg, const char *sarg, 1736 const char *const name) 1737 { 1738 if (got_int) { 1739 return false; 1740 } 1741 1742 if (type == LIST_STRING ? (sarg == NULL) : (iarg == 0)) { 1743 return didh; 1744 } 1745 1746 char buf[100]; 1747 const char *ts = buf; 1748 if (type == LIST_INT) { 1749 snprintf(buf, sizeof(buf), "%d", iarg - 1); 1750 } else if (type == LIST_STRING) { 1751 ts = sarg; 1752 } else { // type == LIST_ATTR 1753 buf[0] = NUL; 1754 for (int i = 0; hl_attr_table[i] != 0; i++) { 1755 if (((hl_attr_table[i] & HL_UNDERLINE_MASK) 1756 && ((iarg & HL_UNDERLINE_MASK) == hl_attr_table[i])) 1757 || (!(hl_attr_table[i] & HL_UNDERLINE_MASK) 1758 && (iarg & hl_attr_table[i]))) { 1759 if (buf[0] != NUL) { 1760 xstrlcat(buf, ",", 100); 1761 } 1762 xstrlcat(buf, hl_name_table[i], 100); 1763 if (!(hl_attr_table[i] & HL_UNDERLINE_MASK)) { 1764 iarg &= ~hl_attr_table[i]; // don't want "inverse" 1765 } 1766 } 1767 } 1768 } 1769 1770 syn_list_header(didh, vim_strsize(ts) + (int)strlen(name) + 1, id, false); 1771 didh = true; 1772 if (!got_int) { 1773 if (*name != NUL) { 1774 msg_puts_hl(name, HLF_D, false); 1775 msg_puts_hl("=", HLF_D, false); 1776 } 1777 msg_outtrans(ts, 0, false); 1778 } 1779 return didh; 1780 } 1781 1782 /// Check whether highlight group has attribute 1783 /// 1784 /// @param[in] id Highlight group to check. 1785 /// @param[in] flag Attribute to check. 1786 /// @param[in] modec 'g' for GUI, 'c' for term. 1787 /// 1788 /// @return "1" if highlight group has attribute, NULL otherwise. 1789 const char *highlight_has_attr(const int id, const int flag, const int modec) 1790 FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE 1791 { 1792 if (id <= 0 || id > highlight_ga.ga_len) { 1793 return NULL; 1794 } 1795 1796 int attr; 1797 1798 if (modec == 'g') { 1799 attr = hl_table[id - 1].sg_gui; 1800 } else { 1801 attr = hl_table[id - 1].sg_cterm; 1802 } 1803 1804 if (flag & HL_UNDERLINE_MASK) { 1805 int ul = attr & HL_UNDERLINE_MASK; 1806 return ul == flag ? "1" : NULL; 1807 } else { 1808 return (attr & flag) ? "1" : NULL; 1809 } 1810 } 1811 1812 /// Return color name of the given highlight group 1813 /// 1814 /// @param[in] id Highlight group to work with. 1815 /// @param[in] what What to return: one of "font", "fg", "bg", "sp", "fg#", 1816 /// "bg#" or "sp#". 1817 /// @param[in] modec 'g' for GUI, 'c' for cterm and 't' for term. 1818 /// 1819 /// @return color name, possibly in a static buffer. Buffer will be overwritten 1820 /// on next highlight_color() call. May return NULL. 1821 const char *highlight_color(const int id, const char *const what, const int modec) 1822 FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL 1823 { 1824 static char name[20]; 1825 bool fg = false; 1826 bool sp = false; 1827 bool font = false; 1828 1829 if (id <= 0 || id > highlight_ga.ga_len) { 1830 return NULL; 1831 } 1832 1833 if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') { 1834 fg = true; 1835 } else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o' 1836 && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') { 1837 font = true; 1838 } else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') { 1839 sp = true; 1840 } else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) { 1841 return NULL; 1842 } 1843 1844 int n; 1845 1846 if (modec == 'g') { 1847 if (what[2] == '#' && ui_rgb_attached()) { 1848 if (fg) { 1849 n = hl_table[id - 1].sg_rgb_fg; 1850 } else if (sp) { 1851 n = hl_table[id - 1].sg_rgb_sp; 1852 } else { 1853 n = hl_table[id - 1].sg_rgb_bg; 1854 } 1855 if (n < 0 || n > 0xffffff) { 1856 return NULL; 1857 } 1858 snprintf(name, sizeof(name), "#%06x", n); 1859 return name; 1860 } 1861 if (fg) { 1862 return coloridx_to_name(hl_table[id - 1].sg_rgb_fg_idx, hl_table[id - 1].sg_rgb_fg, name); 1863 } else if (sp) { 1864 return coloridx_to_name(hl_table[id - 1].sg_rgb_sp_idx, hl_table[id - 1].sg_rgb_sp, name); 1865 } else { 1866 return coloridx_to_name(hl_table[id - 1].sg_rgb_bg_idx, hl_table[id - 1].sg_rgb_bg, name); 1867 } 1868 } 1869 if (font || sp) { 1870 return NULL; 1871 } 1872 if (modec == 'c') { 1873 if (fg) { 1874 n = hl_table[id - 1].sg_cterm_fg - 1; 1875 } else { 1876 n = hl_table[id - 1].sg_cterm_bg - 1; 1877 } 1878 if (n < 0) { 1879 return NULL; 1880 } 1881 snprintf(name, sizeof(name), "%d", n); 1882 return name; 1883 } 1884 // term doesn't have color. 1885 return NULL; 1886 } 1887 1888 /// Output the syntax list header. 1889 /// 1890 /// @param did_header did header already 1891 /// @param outlen length of string that comes 1892 /// @param id highlight group id 1893 /// @param force_newline always start a new line 1894 /// @return true when started a new line. 1895 bool syn_list_header(const bool did_header, const int outlen, const int id, bool force_newline) 1896 { 1897 int endcol = 19; 1898 bool newline = true; 1899 int name_col = 0; 1900 bool adjust = true; 1901 1902 if (!did_header) { 1903 if (!ui_has(kUIMessages) || msg_col > 0) { 1904 msg_putchar('\n'); 1905 } 1906 if (got_int) { 1907 return true; 1908 } 1909 msg_col = name_col = msg_outtrans(hl_table[id - 1].sg_name, 0, false); 1910 endcol = 15; 1911 } else if ((ui_has(kUIMessages) || msg_silent) && !force_newline) { 1912 msg_putchar(' '); 1913 adjust = false; 1914 } else if (msg_col + outlen + 1 >= Columns || force_newline) { 1915 msg_putchar('\n'); 1916 if (got_int) { 1917 return true; 1918 } 1919 } else { 1920 if (msg_col >= endcol) { // wrap around is like starting a new line 1921 newline = false; 1922 } 1923 } 1924 1925 if (adjust) { 1926 if (msg_col >= endcol) { 1927 // output at least one space 1928 endcol = msg_col + 1; 1929 } 1930 1931 msg_advance(endcol); 1932 } 1933 1934 // Show "xxx" with the attributes. 1935 if (!did_header) { 1936 if (endcol == Columns - 1 && endcol <= name_col) { 1937 msg_putchar(' '); 1938 } 1939 msg_puts_hl("xxx", id, false); 1940 msg_putchar(' '); 1941 } 1942 1943 return newline; 1944 } 1945 1946 /// Set the attribute numbers for a highlight group. 1947 /// Called after one of the attributes has changed. 1948 /// @param idx corrected highlight index 1949 static void set_hl_attr(int idx) 1950 { 1951 HlAttrs at_en = HLATTRS_INIT; 1952 HlGroup *sgp = hl_table + idx; 1953 1954 at_en.cterm_ae_attr = (int32_t)sgp->sg_cterm; 1955 at_en.cterm_fg_color = (int16_t)sgp->sg_cterm_fg; 1956 at_en.cterm_bg_color = (int16_t)sgp->sg_cterm_bg; 1957 at_en.rgb_ae_attr = (int32_t)sgp->sg_gui; 1958 // FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is 1959 // initialized with 0 (by garray functions), check for sg_rgb_{f,b}g_name 1960 // before setting attr_entry->{f,g}g_color to a other than -1 1961 at_en.rgb_fg_color = sgp->sg_rgb_fg_idx != kColorIdxNone ? sgp->sg_rgb_fg : -1; 1962 at_en.rgb_bg_color = sgp->sg_rgb_bg_idx != kColorIdxNone ? sgp->sg_rgb_bg : -1; 1963 at_en.rgb_sp_color = sgp->sg_rgb_sp_idx != kColorIdxNone ? sgp->sg_rgb_sp : -1; 1964 at_en.hl_blend = sgp->sg_blend; 1965 1966 sgp->sg_attr = hl_get_syn_attr(0, idx + 1, at_en); 1967 1968 // a cursor style uses this syn_id, make sure its attribute is updated. 1969 if (cursor_mode_uses_syn_id(idx + 1)) { 1970 ui_mode_info_set(); 1971 } 1972 } 1973 1974 int syn_name2id(const char *name) 1975 FUNC_ATTR_NONNULL_ALL 1976 { 1977 if (name[0] == '@') { 1978 // if we look up @aaa.bbb, we have to consider @aaa as well 1979 return syn_check_group(name, strlen(name)); 1980 } 1981 return syn_name2id_len(name, strlen(name)); 1982 } 1983 1984 /// Lookup a highlight group name and return its ID. 1985 /// 1986 /// @param highlight name e.g. 'Cursor', 'Normal' 1987 /// @return the highlight id, else 0 if \p name does not exist 1988 int syn_name2id_len(const char *name, size_t len) 1989 FUNC_ATTR_NONNULL_ALL 1990 { 1991 char name_u[MAX_SYN_NAME + 1]; 1992 1993 if (len == 0 || len > MAX_SYN_NAME) { 1994 return 0; 1995 } 1996 1997 // Avoid using stricmp() too much, it's slow on some systems 1998 // Avoid alloc()/free(), these are slow too. 1999 vim_memcpy_up(name_u, name, len); 2000 name_u[len] = NUL; 2001 2002 // map_get(..., int) returns 0 when no key is present, which is 2003 // the expected value for missing highlight group. 2004 return map_get(cstr_t, int)(&highlight_unames, name_u); 2005 } 2006 2007 /// Lookup a highlight group name and return its attributes. 2008 /// Return zero if not found. 2009 int syn_name2attr(const char *name) 2010 FUNC_ATTR_NONNULL_ALL 2011 { 2012 int id = syn_name2id(name); 2013 2014 if (id != 0) { 2015 return syn_id2attr(id); 2016 } 2017 return 0; 2018 } 2019 2020 /// Return true if highlight group "name" exists. 2021 int highlight_exists(const char *name) 2022 { 2023 return syn_name2id(name) > 0; 2024 } 2025 2026 /// Return the name of highlight group "id". 2027 /// When not a valid ID return an empty string. 2028 char *syn_id2name(int id) 2029 { 2030 if (id <= 0 || id > highlight_ga.ga_len) { 2031 return ""; 2032 } 2033 return hl_table[id - 1].sg_name; 2034 } 2035 2036 /// Find highlight group name in the table and return its ID. 2037 /// If it doesn't exist yet, a new entry is created. 2038 /// 2039 /// @param pp Highlight group name 2040 /// @param len length of \p pp 2041 /// 2042 /// @return 0 for failure else the id of the group 2043 int syn_check_group(const char *name, size_t len) 2044 { 2045 if (len > MAX_SYN_NAME) { 2046 emsg(_(e_highlight_group_name_too_long)); 2047 return 0; 2048 } 2049 int id = syn_name2id_len(name, len); 2050 if (id == 0) { // doesn't exist yet 2051 return syn_add_group(name, len); 2052 } 2053 return id; 2054 } 2055 2056 /// Add new highlight group and return its ID. 2057 /// 2058 /// @param name must be an allocated string, it will be consumed. 2059 /// @return 0 for failure, else the allocated group id 2060 /// @see syn_check_group 2061 static int syn_add_group(const char *name, size_t len) 2062 { 2063 // Check that the name is valid (ASCII letters, digits, '_', '.', '@', '-'). 2064 for (size_t i = 0; i < len; i++) { 2065 int c = (uint8_t)name[i]; 2066 if (!vim_isprintc(c)) { 2067 emsg(_("E669: Unprintable character in group name")); 2068 return 0; 2069 } else if (!ASCII_ISALNUM(c) && c != '_' && c != '.' && c != '@' && c != '-') { 2070 // '.' and '@' are allowed characters for use with treesitter capture names. 2071 msg_source(HLF_W); 2072 emsg(_(e_highlight_group_name_invalid_char)); 2073 return 0; 2074 } 2075 } 2076 2077 int scoped_parent = 0; 2078 if (len > 1 && name[0] == '@') { 2079 char *delim = xmemrchr(name, '.', len); 2080 if (delim) { 2081 scoped_parent = syn_check_group(name, (size_t)(delim - name)); 2082 } 2083 } 2084 2085 // First call for this growarray: init growing array. 2086 if (highlight_ga.ga_data == NULL) { 2087 highlight_ga.ga_itemsize = sizeof(HlGroup); 2088 ga_set_growsize(&highlight_ga, 10); 2089 // 265 builtin groups, will always be used, plus some space 2090 ga_grow(&highlight_ga, 300); 2091 } 2092 2093 if (highlight_ga.ga_len >= MAX_HL_ID) { 2094 emsg(_("E849: Too many highlight and syntax groups")); 2095 return 0; 2096 } 2097 2098 // Append another syntax_highlight entry. 2099 HlGroup *hlgp = GA_APPEND_VIA_PTR(HlGroup, &highlight_ga); 2100 CLEAR_POINTER(hlgp); 2101 hlgp->sg_name = arena_memdupz(&highlight_arena, name, len); 2102 hlgp->sg_rgb_bg = -1; 2103 hlgp->sg_rgb_fg = -1; 2104 hlgp->sg_rgb_sp = -1; 2105 hlgp->sg_rgb_bg_idx = kColorIdxNone; 2106 hlgp->sg_rgb_fg_idx = kColorIdxNone; 2107 hlgp->sg_rgb_sp_idx = kColorIdxNone; 2108 hlgp->sg_blend = -1; 2109 hlgp->sg_name_u = arena_memdupz(&highlight_arena, name, len); 2110 hlgp->sg_parent = scoped_parent; 2111 // will get set to false by caller if settings are added 2112 hlgp->sg_cleared = true; 2113 vim_strup(hlgp->sg_name_u); 2114 2115 int id = highlight_ga.ga_len; // ID is index plus one 2116 2117 map_put(cstr_t, int)(&highlight_unames, hlgp->sg_name_u, id); 2118 2119 return id; 2120 } 2121 2122 /// Translate a group ID to highlight attributes. 2123 /// @see syn_attr2entry 2124 int syn_id2attr(int hl_id) 2125 { 2126 bool optional = false; 2127 return syn_ns_id2attr(-1, hl_id, &optional); 2128 } 2129 2130 int syn_ns_id2attr(int ns_id, int hl_id, bool *optional) 2131 FUNC_ATTR_NONNULL_ALL 2132 { 2133 if (syn_ns_get_final_id(&ns_id, &hl_id)) { 2134 // If the namespace explicitly defines a group to be empty, it is not optional 2135 *optional = false; 2136 } 2137 HlGroup *sgp = &hl_table[hl_id - 1]; // index is ID minus one 2138 2139 int attr = ns_get_hl(&ns_id, hl_id, false, sgp->sg_set); 2140 2141 // if a highlight group is optional, don't use the global value 2142 if (attr >= 0 || (*optional && ns_id > 0)) { 2143 return attr; 2144 } 2145 return sgp->sg_attr; 2146 } 2147 2148 /// Translate a group ID to the final group ID (following links). 2149 int syn_get_final_id(int hl_id) 2150 { 2151 int ns_id = curwin->w_ns_hl_active; 2152 syn_ns_get_final_id(&ns_id, &hl_id); 2153 return hl_id; 2154 } 2155 2156 bool syn_ns_get_final_id(int *ns_id, int *hl_idp) 2157 { 2158 int hl_id = *hl_idp; 2159 bool used = false; 2160 2161 if (hl_id > highlight_ga.ga_len || hl_id < 1) { 2162 *hl_idp = 0; 2163 return false; // Can be called from eval!! 2164 } 2165 2166 // Follow links until there is no more. 2167 // Look out for loops! Break after 100 links. 2168 for (int count = 100; --count >= 0;) { 2169 HlGroup *sgp = &hl_table[hl_id - 1]; // index is ID minus one 2170 2171 // TODO(bfredl): when using "tmp" attribute (no link) the function might be 2172 // called twice. it needs be smart enough to remember attr only to 2173 // syn_id2attr time 2174 int check = ns_get_hl(ns_id, hl_id, true, sgp->sg_set); 2175 if (check == 0) { 2176 *hl_idp = hl_id; 2177 return true; // how dare! it broke the link! 2178 } else if (check > 0) { 2179 used = true; 2180 hl_id = check; 2181 continue; 2182 } 2183 2184 if (sgp->sg_link > 0 && sgp->sg_link <= highlight_ga.ga_len) { 2185 hl_id = sgp->sg_link; 2186 } else if (sgp->sg_cleared && sgp->sg_parent > 0) { 2187 hl_id = sgp->sg_parent; 2188 } else { 2189 break; 2190 } 2191 } 2192 2193 *hl_idp = hl_id; 2194 return used; 2195 } 2196 2197 /// Refresh the color attributes of all highlight groups. 2198 void highlight_attr_set_all(void) 2199 { 2200 for (int idx = 0; idx < highlight_ga.ga_len; idx++) { 2201 HlGroup *sgp = &hl_table[idx]; 2202 if (sgp->sg_rgb_bg_idx == kColorIdxFg) { 2203 sgp->sg_rgb_bg = normal_fg; 2204 } else if (sgp->sg_rgb_bg_idx == kColorIdxBg) { 2205 sgp->sg_rgb_bg = normal_bg; 2206 } 2207 if (sgp->sg_rgb_fg_idx == kColorIdxFg) { 2208 sgp->sg_rgb_fg = normal_fg; 2209 } else if (sgp->sg_rgb_fg_idx == kColorIdxBg) { 2210 sgp->sg_rgb_fg = normal_bg; 2211 } 2212 if (sgp->sg_rgb_sp_idx == kColorIdxFg) { 2213 sgp->sg_rgb_sp = normal_fg; 2214 } else if (sgp->sg_rgb_sp_idx == kColorIdxBg) { 2215 sgp->sg_rgb_sp = normal_bg; 2216 } 2217 set_hl_attr(idx); 2218 } 2219 } 2220 2221 // Apply difference between User[1-9] and HLF_S to HLF_SNC. 2222 static void combine_stl_hlt(int id, int id_S, int id_alt, int hlcnt, int i, int hlf, int *table) 2223 FUNC_ATTR_NONNULL_ALL 2224 { 2225 HlGroup *const hlt = hl_table; 2226 2227 if (id_alt == 0) { 2228 CLEAR_POINTER(&hlt[hlcnt + i]); 2229 hlt[hlcnt + i].sg_cterm = highlight_attr[hlf]; 2230 hlt[hlcnt + i].sg_gui = highlight_attr[hlf]; 2231 } else { 2232 memmove(&hlt[hlcnt + i], &hlt[id_alt - 1], sizeof(HlGroup)); 2233 } 2234 hlt[hlcnt + i].sg_link = 0; 2235 2236 hlt[hlcnt + i].sg_cterm ^= hlt[id - 1].sg_cterm ^ hlt[id_S - 1].sg_cterm; 2237 if (hlt[id - 1].sg_cterm_fg != hlt[id_S - 1].sg_cterm_fg) { 2238 hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg; 2239 } 2240 if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg) { 2241 hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg; 2242 } 2243 hlt[hlcnt + i].sg_gui ^= hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui; 2244 if (hlt[id - 1].sg_rgb_fg != hlt[id_S - 1].sg_rgb_fg) { 2245 hlt[hlcnt + i].sg_rgb_fg = hlt[id - 1].sg_rgb_fg; 2246 } 2247 if (hlt[id - 1].sg_rgb_bg != hlt[id_S - 1].sg_rgb_bg) { 2248 hlt[hlcnt + i].sg_rgb_bg = hlt[id - 1].sg_rgb_bg; 2249 } 2250 if (hlt[id - 1].sg_rgb_sp != hlt[id_S - 1].sg_rgb_sp) { 2251 hlt[hlcnt + i].sg_rgb_sp = hlt[id - 1].sg_rgb_sp; 2252 } 2253 highlight_ga.ga_len = hlcnt + i + 1; 2254 set_hl_attr(hlcnt + i); // At long last we can apply 2255 table[i] = syn_id2attr(hlcnt + i + 1); 2256 } 2257 2258 /// Translate highlight groups into attributes in highlight_attr[] and set up 2259 /// the user highlights User1..9. A set of corresponding highlights to use on 2260 /// top of HLF_SNC is computed. Called only when nvim starts and upon first 2261 /// screen redraw after any :highlight command. 2262 void highlight_changed(void) 2263 { 2264 char userhl[30]; // use 30 to avoid compiler warning 2265 int id_S = -1; 2266 int id_SNC = 0; 2267 2268 need_highlight_changed = false; 2269 2270 // sentinel value. used when no highlight is active 2271 highlight_attr[HLF_NONE] = 0; 2272 2273 /// Translate builtin highlight groups into attributes for quick lookup. 2274 for (int hlf = 1; hlf < HLF_COUNT; hlf++) { 2275 int id = syn_check_group(hlf_names[hlf], strlen(hlf_names[hlf])); 2276 if (id == 0) { 2277 abort(); 2278 } 2279 int ns_id = -1; 2280 int final_id = id; 2281 syn_ns_get_final_id(&ns_id, &final_id); 2282 if (hlf == HLF_SNC) { 2283 id_SNC = final_id; 2284 } else if (hlf == HLF_S) { 2285 id_S = final_id; 2286 } 2287 2288 highlight_attr[hlf] = hl_get_ui_attr(ns_id, hlf, final_id, hlf == HLF_INACTIVE); 2289 2290 if (highlight_attr[hlf] != highlight_attr_last[hlf]) { 2291 if (hlf == HLF_MSG) { 2292 clear_cmdline = true; 2293 HlAttrs attrs = syn_attr2entry(highlight_attr[hlf]); 2294 msg_grid.blending = attrs.hl_blend > -1; 2295 } 2296 ui_call_hl_group_set(cstr_as_string(hlf_names[hlf]), 2297 highlight_attr[hlf]); 2298 highlight_attr_last[hlf] = highlight_attr[hlf]; 2299 } 2300 } 2301 2302 // Setup the user highlights 2303 // 2304 // Temporarily utilize 10 more hl entries: 2305 // 9 for User1-User9 combined with StatusLineNC 2306 // 1 for StatusLine default 2307 // Must to be in there simultaneously in case of table overflows in 2308 // get_attr_entry() 2309 ga_grow(&highlight_ga, 10); 2310 int hlcnt = highlight_ga.ga_len; 2311 if (id_S == -1) { 2312 // Make sure id_S is always valid to simplify code below. Use the last entry 2313 CLEAR_POINTER(&hl_table[hlcnt + 9]); 2314 id_S = hlcnt + 10; 2315 } 2316 for (int i = 0; i < 9; i++) { 2317 snprintf(userhl, sizeof(userhl), "User%d", i + 1); 2318 int id = syn_name2id(userhl); 2319 if (id == 0) { 2320 highlight_user[i] = 0; 2321 highlight_stlnc[i] = 0; 2322 } else { 2323 highlight_user[i] = syn_id2attr(id); 2324 combine_stl_hlt(id, id_S, id_SNC, hlcnt, i, HLF_SNC, highlight_stlnc); 2325 } 2326 } 2327 highlight_ga.ga_len = hlcnt; 2328 2329 decor_provider_invalidate_hl(); 2330 } 2331 2332 /// Handle command line completion for :highlight command. 2333 void set_context_in_highlight_cmd(expand_T *xp, const char *arg) 2334 { 2335 // Default: expand group names. 2336 xp->xp_context = EXPAND_HIGHLIGHT; 2337 xp->xp_pattern = (char *)arg; 2338 include_link = 2; 2339 include_default = 1; 2340 2341 if (*arg == NUL) { 2342 return; 2343 } 2344 2345 // (part of) subcommand already typed 2346 const char *p = skiptowhite(arg); 2347 if (*p == NUL) { 2348 return; 2349 } 2350 2351 // past "default" or group name 2352 include_default = 0; 2353 if (strncmp("default", arg, (unsigned)(p - arg)) == 0) { 2354 arg = skipwhite(p); 2355 xp->xp_pattern = (char *)arg; 2356 p = skiptowhite(arg); 2357 } 2358 if (*p == NUL) { 2359 return; 2360 } 2361 2362 // past group name 2363 include_link = 0; 2364 if (arg[1] == 'i' && arg[0] == 'N') { 2365 highlight_list(); 2366 } 2367 if (strncmp("link", arg, (unsigned)(p - arg)) == 0 2368 || strncmp("clear", arg, (unsigned)(p - arg)) == 0) { 2369 xp->xp_pattern = skipwhite(p); 2370 p = skiptowhite(xp->xp_pattern); 2371 if (*p != NUL) { // past first group name 2372 xp->xp_pattern = skipwhite(p); 2373 p = skiptowhite(xp->xp_pattern); 2374 } 2375 } 2376 if (*p != NUL) { // past group name(s) 2377 xp->xp_context = EXPAND_NOTHING; 2378 } 2379 } 2380 2381 /// List highlighting matches in a nice way. 2382 static void highlight_list(void) 2383 { 2384 for (int i = 10; --i >= 0;) { 2385 highlight_list_two(i, HLF_D); 2386 } 2387 for (int i = 40; --i >= 0;) { 2388 highlight_list_two(99, 0); 2389 } 2390 } 2391 2392 static void highlight_list_two(int cnt, int id) 2393 { 2394 msg_puts_hl(&("N \bI \b! \b"[cnt / 11]), id, false); 2395 msg_clr_eos(); 2396 ui_flush(); 2397 // TODO(justinmk): is this delay needed? ":hi" seems to work without it. 2398 os_delay(cnt == 99 ? 40 : (uint64_t)cnt * 50, false); 2399 } 2400 2401 /// Function given to ExpandGeneric() to obtain the list of group names. 2402 char *get_highlight_name(expand_T *const xp, int idx) 2403 FUNC_ATTR_WARN_UNUSED_RESULT 2404 { 2405 return (char *)get_highlight_name_ext(xp, idx, true); 2406 } 2407 2408 /// Obtain a highlight group name. 2409 /// 2410 /// @param skip_cleared if true don't return a cleared entry. 2411 const char *get_highlight_name_ext(expand_T *xp, int idx, bool skip_cleared) 2412 FUNC_ATTR_WARN_UNUSED_RESULT 2413 { 2414 if (idx < 0) { 2415 return NULL; 2416 } 2417 2418 // Items are never removed from the table, skip the ones that were cleared. 2419 if (skip_cleared && idx < highlight_ga.ga_len && hl_table[idx].sg_cleared) { 2420 return ""; 2421 } 2422 2423 if (idx == highlight_ga.ga_len && include_none != 0) { 2424 return "none"; 2425 } else if (idx == highlight_ga.ga_len + include_none 2426 && include_default != 0) { 2427 return "default"; 2428 } else if (idx == highlight_ga.ga_len + include_none + include_default 2429 && include_link != 0) { 2430 return "link"; 2431 } else if (idx == highlight_ga.ga_len + include_none + include_default + 1 2432 && include_link != 0) { 2433 return "clear"; 2434 } else if (idx >= highlight_ga.ga_len) { 2435 return NULL; 2436 } 2437 return hl_table[idx].sg_name; 2438 } 2439 2440 color_name_table_T color_name_table[] = { 2441 // Colors from rgb.txt 2442 { "AliceBlue", RGB_(0xf0, 0xf8, 0xff) }, 2443 { "AntiqueWhite", RGB_(0xfa, 0xeb, 0xd7) }, 2444 { "AntiqueWhite1", RGB_(0xff, 0xef, 0xdb) }, 2445 { "AntiqueWhite2", RGB_(0xee, 0xdf, 0xcc) }, 2446 { "AntiqueWhite3", RGB_(0xcd, 0xc0, 0xb0) }, 2447 { "AntiqueWhite4", RGB_(0x8b, 0x83, 0x78) }, 2448 { "Aqua", RGB_(0x00, 0xff, 0xff) }, 2449 { "Aquamarine", RGB_(0x7f, 0xff, 0xd4) }, 2450 { "Aquamarine1", RGB_(0x7f, 0xff, 0xd4) }, 2451 { "Aquamarine2", RGB_(0x76, 0xee, 0xc6) }, 2452 { "Aquamarine3", RGB_(0x66, 0xcd, 0xaa) }, 2453 { "Aquamarine4", RGB_(0x45, 0x8b, 0x74) }, 2454 { "Azure", RGB_(0xf0, 0xff, 0xff) }, 2455 { "Azure1", RGB_(0xf0, 0xff, 0xff) }, 2456 { "Azure2", RGB_(0xe0, 0xee, 0xee) }, 2457 { "Azure3", RGB_(0xc1, 0xcd, 0xcd) }, 2458 { "Azure4", RGB_(0x83, 0x8b, 0x8b) }, 2459 { "Beige", RGB_(0xf5, 0xf5, 0xdc) }, 2460 { "Bisque", RGB_(0xff, 0xe4, 0xc4) }, 2461 { "Bisque1", RGB_(0xff, 0xe4, 0xc4) }, 2462 { "Bisque2", RGB_(0xee, 0xd5, 0xb7) }, 2463 { "Bisque3", RGB_(0xcd, 0xb7, 0x9e) }, 2464 { "Bisque4", RGB_(0x8b, 0x7d, 0x6b) }, 2465 { "Black", RGB_(0x00, 0x00, 0x00) }, 2466 { "BlanchedAlmond", RGB_(0xff, 0xeb, 0xcd) }, 2467 { "Blue", RGB_(0x00, 0x00, 0xff) }, 2468 { "Blue1", RGB_(0x0, 0x0, 0xff) }, 2469 { "Blue2", RGB_(0x0, 0x0, 0xee) }, 2470 { "Blue3", RGB_(0x0, 0x0, 0xcd) }, 2471 { "Blue4", RGB_(0x0, 0x0, 0x8b) }, 2472 { "BlueViolet", RGB_(0x8a, 0x2b, 0xe2) }, 2473 { "Brown", RGB_(0xa5, 0x2a, 0x2a) }, 2474 { "Brown1", RGB_(0xff, 0x40, 0x40) }, 2475 { "Brown2", RGB_(0xee, 0x3b, 0x3b) }, 2476 { "Brown3", RGB_(0xcd, 0x33, 0x33) }, 2477 { "Brown4", RGB_(0x8b, 0x23, 0x23) }, 2478 { "BurlyWood", RGB_(0xde, 0xb8, 0x87) }, 2479 { "Burlywood1", RGB_(0xff, 0xd3, 0x9b) }, 2480 { "Burlywood2", RGB_(0xee, 0xc5, 0x91) }, 2481 { "Burlywood3", RGB_(0xcd, 0xaa, 0x7d) }, 2482 { "Burlywood4", RGB_(0x8b, 0x73, 0x55) }, 2483 { "CadetBlue", RGB_(0x5f, 0x9e, 0xa0) }, 2484 { "CadetBlue1", RGB_(0x98, 0xf5, 0xff) }, 2485 { "CadetBlue2", RGB_(0x8e, 0xe5, 0xee) }, 2486 { "CadetBlue3", RGB_(0x7a, 0xc5, 0xcd) }, 2487 { "CadetBlue4", RGB_(0x53, 0x86, 0x8b) }, 2488 { "ChartReuse", RGB_(0x7f, 0xff, 0x00) }, 2489 { "Chartreuse1", RGB_(0x7f, 0xff, 0x0) }, 2490 { "Chartreuse2", RGB_(0x76, 0xee, 0x0) }, 2491 { "Chartreuse3", RGB_(0x66, 0xcd, 0x0) }, 2492 { "Chartreuse4", RGB_(0x45, 0x8b, 0x0) }, 2493 { "Chocolate", RGB_(0xd2, 0x69, 0x1e) }, 2494 { "Chocolate1", RGB_(0xff, 0x7f, 0x24) }, 2495 { "Chocolate2", RGB_(0xee, 0x76, 0x21) }, 2496 { "Chocolate3", RGB_(0xcd, 0x66, 0x1d) }, 2497 { "Chocolate4", RGB_(0x8b, 0x45, 0x13) }, 2498 { "Coral", RGB_(0xff, 0x7f, 0x50) }, 2499 { "Coral1", RGB_(0xff, 0x72, 0x56) }, 2500 { "Coral2", RGB_(0xee, 0x6a, 0x50) }, 2501 { "Coral3", RGB_(0xcd, 0x5b, 0x45) }, 2502 { "Coral4", RGB_(0x8b, 0x3e, 0x2f) }, 2503 { "CornFlowerBlue", RGB_(0x64, 0x95, 0xed) }, 2504 { "Cornsilk", RGB_(0xff, 0xf8, 0xdc) }, 2505 { "Cornsilk1", RGB_(0xff, 0xf8, 0xdc) }, 2506 { "Cornsilk2", RGB_(0xee, 0xe8, 0xcd) }, 2507 { "Cornsilk3", RGB_(0xcd, 0xc8, 0xb1) }, 2508 { "Cornsilk4", RGB_(0x8b, 0x88, 0x78) }, 2509 { "Crimson", RGB_(0xdc, 0x14, 0x3c) }, 2510 { "Cyan", RGB_(0x00, 0xff, 0xff) }, 2511 { "Cyan1", RGB_(0x0, 0xff, 0xff) }, 2512 { "Cyan2", RGB_(0x0, 0xee, 0xee) }, 2513 { "Cyan3", RGB_(0x0, 0xcd, 0xcd) }, 2514 { "Cyan4", RGB_(0x0, 0x8b, 0x8b) }, 2515 { "DarkBlue", RGB_(0x00, 0x00, 0x8b) }, 2516 { "DarkCyan", RGB_(0x00, 0x8b, 0x8b) }, 2517 { "DarkGoldenrod", RGB_(0xb8, 0x86, 0x0b) }, 2518 { "DarkGoldenrod1", RGB_(0xff, 0xb9, 0xf) }, 2519 { "DarkGoldenrod2", RGB_(0xee, 0xad, 0xe) }, 2520 { "DarkGoldenrod3", RGB_(0xcd, 0x95, 0xc) }, 2521 { "DarkGoldenrod4", RGB_(0x8b, 0x65, 0x8) }, 2522 { "DarkGray", RGB_(0xa9, 0xa9, 0xa9) }, 2523 { "DarkGreen", RGB_(0x00, 0x64, 0x00) }, 2524 { "DarkGrey", RGB_(0xa9, 0xa9, 0xa9) }, 2525 { "DarkKhaki", RGB_(0xbd, 0xb7, 0x6b) }, 2526 { "DarkMagenta", RGB_(0x8b, 0x00, 0x8b) }, 2527 { "DarkOliveGreen", RGB_(0x55, 0x6b, 0x2f) }, 2528 { "DarkOliveGreen1", RGB_(0xca, 0xff, 0x70) }, 2529 { "DarkOliveGreen2", RGB_(0xbc, 0xee, 0x68) }, 2530 { "DarkOliveGreen3", RGB_(0xa2, 0xcd, 0x5a) }, 2531 { "DarkOliveGreen4", RGB_(0x6e, 0x8b, 0x3d) }, 2532 { "DarkOrange", RGB_(0xff, 0x8c, 0x00) }, 2533 { "DarkOrange1", RGB_(0xff, 0x7f, 0x0) }, 2534 { "DarkOrange2", RGB_(0xee, 0x76, 0x0) }, 2535 { "DarkOrange3", RGB_(0xcd, 0x66, 0x0) }, 2536 { "DarkOrange4", RGB_(0x8b, 0x45, 0x0) }, 2537 { "DarkOrchid", RGB_(0x99, 0x32, 0xcc) }, 2538 { "DarkOrchid1", RGB_(0xbf, 0x3e, 0xff) }, 2539 { "DarkOrchid2", RGB_(0xb2, 0x3a, 0xee) }, 2540 { "DarkOrchid3", RGB_(0x9a, 0x32, 0xcd) }, 2541 { "DarkOrchid4", RGB_(0x68, 0x22, 0x8b) }, 2542 { "DarkRed", RGB_(0x8b, 0x00, 0x00) }, 2543 { "DarkSalmon", RGB_(0xe9, 0x96, 0x7a) }, 2544 { "DarkSeaGreen", RGB_(0x8f, 0xbc, 0x8f) }, 2545 { "DarkSeaGreen1", RGB_(0xc1, 0xff, 0xc1) }, 2546 { "DarkSeaGreen2", RGB_(0xb4, 0xee, 0xb4) }, 2547 { "DarkSeaGreen3", RGB_(0x9b, 0xcd, 0x9b) }, 2548 { "DarkSeaGreen4", RGB_(0x69, 0x8b, 0x69) }, 2549 { "DarkSlateBlue", RGB_(0x48, 0x3d, 0x8b) }, 2550 { "DarkSlateGray", RGB_(0x2f, 0x4f, 0x4f) }, 2551 { "DarkSlateGray1", RGB_(0x97, 0xff, 0xff) }, 2552 { "DarkSlateGray2", RGB_(0x8d, 0xee, 0xee) }, 2553 { "DarkSlateGray3", RGB_(0x79, 0xcd, 0xcd) }, 2554 { "DarkSlateGray4", RGB_(0x52, 0x8b, 0x8b) }, 2555 { "DarkSlateGrey", RGB_(0x2f, 0x4f, 0x4f) }, 2556 { "DarkTurquoise", RGB_(0x00, 0xce, 0xd1) }, 2557 { "DarkViolet", RGB_(0x94, 0x00, 0xd3) }, 2558 { "DarkYellow", RGB_(0xbb, 0xbb, 0x00) }, 2559 { "DeepPink", RGB_(0xff, 0x14, 0x93) }, 2560 { "DeepPink1", RGB_(0xff, 0x14, 0x93) }, 2561 { "DeepPink2", RGB_(0xee, 0x12, 0x89) }, 2562 { "DeepPink3", RGB_(0xcd, 0x10, 0x76) }, 2563 { "DeepPink4", RGB_(0x8b, 0xa, 0x50) }, 2564 { "DeepSkyBlue", RGB_(0x00, 0xbf, 0xff) }, 2565 { "DeepSkyBlue1", RGB_(0x0, 0xbf, 0xff) }, 2566 { "DeepSkyBlue2", RGB_(0x0, 0xb2, 0xee) }, 2567 { "DeepSkyBlue3", RGB_(0x0, 0x9a, 0xcd) }, 2568 { "DeepSkyBlue4", RGB_(0x0, 0x68, 0x8b) }, 2569 { "DimGray", RGB_(0x69, 0x69, 0x69) }, 2570 { "DimGrey", RGB_(0x69, 0x69, 0x69) }, 2571 { "DodgerBlue", RGB_(0x1e, 0x90, 0xff) }, 2572 { "DodgerBlue1", RGB_(0x1e, 0x90, 0xff) }, 2573 { "DodgerBlue2", RGB_(0x1c, 0x86, 0xee) }, 2574 { "DodgerBlue3", RGB_(0x18, 0x74, 0xcd) }, 2575 { "DodgerBlue4", RGB_(0x10, 0x4e, 0x8b) }, 2576 { "Firebrick", RGB_(0xb2, 0x22, 0x22) }, 2577 { "Firebrick1", RGB_(0xff, 0x30, 0x30) }, 2578 { "Firebrick2", RGB_(0xee, 0x2c, 0x2c) }, 2579 { "Firebrick3", RGB_(0xcd, 0x26, 0x26) }, 2580 { "Firebrick4", RGB_(0x8b, 0x1a, 0x1a) }, 2581 { "FloralWhite", RGB_(0xff, 0xfa, 0xf0) }, 2582 { "ForestGreen", RGB_(0x22, 0x8b, 0x22) }, 2583 { "Fuchsia", RGB_(0xff, 0x00, 0xff) }, 2584 { "Gainsboro", RGB_(0xdc, 0xdc, 0xdc) }, 2585 { "GhostWhite", RGB_(0xf8, 0xf8, 0xff) }, 2586 { "Gold", RGB_(0xff, 0xd7, 0x00) }, 2587 { "Gold1", RGB_(0xff, 0xd7, 0x0) }, 2588 { "Gold2", RGB_(0xee, 0xc9, 0x0) }, 2589 { "Gold3", RGB_(0xcd, 0xad, 0x0) }, 2590 { "Gold4", RGB_(0x8b, 0x75, 0x0) }, 2591 { "Goldenrod", RGB_(0xda, 0xa5, 0x20) }, 2592 { "Goldenrod1", RGB_(0xff, 0xc1, 0x25) }, 2593 { "Goldenrod2", RGB_(0xee, 0xb4, 0x22) }, 2594 { "Goldenrod3", RGB_(0xcd, 0x9b, 0x1d) }, 2595 { "Goldenrod4", RGB_(0x8b, 0x69, 0x14) }, 2596 { "Gray", RGB_(0x80, 0x80, 0x80) }, 2597 { "Gray0", RGB_(0x0, 0x0, 0x0) }, 2598 { "Gray1", RGB_(0x3, 0x3, 0x3) }, 2599 { "Gray10", RGB_(0x1a, 0x1a, 0x1a) }, 2600 { "Gray100", RGB_(0xff, 0xff, 0xff) }, 2601 { "Gray11", RGB_(0x1c, 0x1c, 0x1c) }, 2602 { "Gray12", RGB_(0x1f, 0x1f, 0x1f) }, 2603 { "Gray13", RGB_(0x21, 0x21, 0x21) }, 2604 { "Gray14", RGB_(0x24, 0x24, 0x24) }, 2605 { "Gray15", RGB_(0x26, 0x26, 0x26) }, 2606 { "Gray16", RGB_(0x29, 0x29, 0x29) }, 2607 { "Gray17", RGB_(0x2b, 0x2b, 0x2b) }, 2608 { "Gray18", RGB_(0x2e, 0x2e, 0x2e) }, 2609 { "Gray19", RGB_(0x30, 0x30, 0x30) }, 2610 { "Gray2", RGB_(0x5, 0x5, 0x5) }, 2611 { "Gray20", RGB_(0x33, 0x33, 0x33) }, 2612 { "Gray21", RGB_(0x36, 0x36, 0x36) }, 2613 { "Gray22", RGB_(0x38, 0x38, 0x38) }, 2614 { "Gray23", RGB_(0x3b, 0x3b, 0x3b) }, 2615 { "Gray24", RGB_(0x3d, 0x3d, 0x3d) }, 2616 { "Gray25", RGB_(0x40, 0x40, 0x40) }, 2617 { "Gray26", RGB_(0x42, 0x42, 0x42) }, 2618 { "Gray27", RGB_(0x45, 0x45, 0x45) }, 2619 { "Gray28", RGB_(0x47, 0x47, 0x47) }, 2620 { "Gray29", RGB_(0x4a, 0x4a, 0x4a) }, 2621 { "Gray3", RGB_(0x8, 0x8, 0x8) }, 2622 { "Gray30", RGB_(0x4d, 0x4d, 0x4d) }, 2623 { "Gray31", RGB_(0x4f, 0x4f, 0x4f) }, 2624 { "Gray32", RGB_(0x52, 0x52, 0x52) }, 2625 { "Gray33", RGB_(0x54, 0x54, 0x54) }, 2626 { "Gray34", RGB_(0x57, 0x57, 0x57) }, 2627 { "Gray35", RGB_(0x59, 0x59, 0x59) }, 2628 { "Gray36", RGB_(0x5c, 0x5c, 0x5c) }, 2629 { "Gray37", RGB_(0x5e, 0x5e, 0x5e) }, 2630 { "Gray38", RGB_(0x61, 0x61, 0x61) }, 2631 { "Gray39", RGB_(0x63, 0x63, 0x63) }, 2632 { "Gray4", RGB_(0xa, 0xa, 0xa) }, 2633 { "Gray40", RGB_(0x66, 0x66, 0x66) }, 2634 { "Gray41", RGB_(0x69, 0x69, 0x69) }, 2635 { "Gray42", RGB_(0x6b, 0x6b, 0x6b) }, 2636 { "Gray43", RGB_(0x6e, 0x6e, 0x6e) }, 2637 { "Gray44", RGB_(0x70, 0x70, 0x70) }, 2638 { "Gray45", RGB_(0x73, 0x73, 0x73) }, 2639 { "Gray46", RGB_(0x75, 0x75, 0x75) }, 2640 { "Gray47", RGB_(0x78, 0x78, 0x78) }, 2641 { "Gray48", RGB_(0x7a, 0x7a, 0x7a) }, 2642 { "Gray49", RGB_(0x7d, 0x7d, 0x7d) }, 2643 { "Gray5", RGB_(0xd, 0xd, 0xd) }, 2644 { "Gray50", RGB_(0x7f, 0x7f, 0x7f) }, 2645 { "Gray51", RGB_(0x82, 0x82, 0x82) }, 2646 { "Gray52", RGB_(0x85, 0x85, 0x85) }, 2647 { "Gray53", RGB_(0x87, 0x87, 0x87) }, 2648 { "Gray54", RGB_(0x8a, 0x8a, 0x8a) }, 2649 { "Gray55", RGB_(0x8c, 0x8c, 0x8c) }, 2650 { "Gray56", RGB_(0x8f, 0x8f, 0x8f) }, 2651 { "Gray57", RGB_(0x91, 0x91, 0x91) }, 2652 { "Gray58", RGB_(0x94, 0x94, 0x94) }, 2653 { "Gray59", RGB_(0x96, 0x96, 0x96) }, 2654 { "Gray6", RGB_(0xf, 0xf, 0xf) }, 2655 { "Gray60", RGB_(0x99, 0x99, 0x99) }, 2656 { "Gray61", RGB_(0x9c, 0x9c, 0x9c) }, 2657 { "Gray62", RGB_(0x9e, 0x9e, 0x9e) }, 2658 { "Gray63", RGB_(0xa1, 0xa1, 0xa1) }, 2659 { "Gray64", RGB_(0xa3, 0xa3, 0xa3) }, 2660 { "Gray65", RGB_(0xa6, 0xa6, 0xa6) }, 2661 { "Gray66", RGB_(0xa8, 0xa8, 0xa8) }, 2662 { "Gray67", RGB_(0xab, 0xab, 0xab) }, 2663 { "Gray68", RGB_(0xad, 0xad, 0xad) }, 2664 { "Gray69", RGB_(0xb0, 0xb0, 0xb0) }, 2665 { "Gray7", RGB_(0x12, 0x12, 0x12) }, 2666 { "Gray70", RGB_(0xb3, 0xb3, 0xb3) }, 2667 { "Gray71", RGB_(0xb5, 0xb5, 0xb5) }, 2668 { "Gray72", RGB_(0xb8, 0xb8, 0xb8) }, 2669 { "Gray73", RGB_(0xba, 0xba, 0xba) }, 2670 { "Gray74", RGB_(0xbd, 0xbd, 0xbd) }, 2671 { "Gray75", RGB_(0xbf, 0xbf, 0xbf) }, 2672 { "Gray76", RGB_(0xc2, 0xc2, 0xc2) }, 2673 { "Gray77", RGB_(0xc4, 0xc4, 0xc4) }, 2674 { "Gray78", RGB_(0xc7, 0xc7, 0xc7) }, 2675 { "Gray79", RGB_(0xc9, 0xc9, 0xc9) }, 2676 { "Gray8", RGB_(0x14, 0x14, 0x14) }, 2677 { "Gray80", RGB_(0xcc, 0xcc, 0xcc) }, 2678 { "Gray81", RGB_(0xcf, 0xcf, 0xcf) }, 2679 { "Gray82", RGB_(0xd1, 0xd1, 0xd1) }, 2680 { "Gray83", RGB_(0xd4, 0xd4, 0xd4) }, 2681 { "Gray84", RGB_(0xd6, 0xd6, 0xd6) }, 2682 { "Gray85", RGB_(0xd9, 0xd9, 0xd9) }, 2683 { "Gray86", RGB_(0xdb, 0xdb, 0xdb) }, 2684 { "Gray87", RGB_(0xde, 0xde, 0xde) }, 2685 { "Gray88", RGB_(0xe0, 0xe0, 0xe0) }, 2686 { "Gray89", RGB_(0xe3, 0xe3, 0xe3) }, 2687 { "Gray9", RGB_(0x17, 0x17, 0x17) }, 2688 { "Gray90", RGB_(0xe5, 0xe5, 0xe5) }, 2689 { "Gray91", RGB_(0xe8, 0xe8, 0xe8) }, 2690 { "Gray92", RGB_(0xeb, 0xeb, 0xeb) }, 2691 { "Gray93", RGB_(0xed, 0xed, 0xed) }, 2692 { "Gray94", RGB_(0xf0, 0xf0, 0xf0) }, 2693 { "Gray95", RGB_(0xf2, 0xf2, 0xf2) }, 2694 { "Gray96", RGB_(0xf5, 0xf5, 0xf5) }, 2695 { "Gray97", RGB_(0xf7, 0xf7, 0xf7) }, 2696 { "Gray98", RGB_(0xfa, 0xfa, 0xfa) }, 2697 { "Gray99", RGB_(0xfc, 0xfc, 0xfc) }, 2698 { "Green", RGB_(0x00, 0x80, 0x00) }, 2699 { "Green1", RGB_(0x0, 0xff, 0x0) }, 2700 { "Green2", RGB_(0x0, 0xee, 0x0) }, 2701 { "Green3", RGB_(0x0, 0xcd, 0x0) }, 2702 { "Green4", RGB_(0x0, 0x8b, 0x0) }, 2703 { "GreenYellow", RGB_(0xad, 0xff, 0x2f) }, 2704 { "Grey", RGB_(0x80, 0x80, 0x80) }, 2705 { "Grey0", RGB_(0x0, 0x0, 0x0) }, 2706 { "Grey1", RGB_(0x3, 0x3, 0x3) }, 2707 { "Grey10", RGB_(0x1a, 0x1a, 0x1a) }, 2708 { "Grey100", RGB_(0xff, 0xff, 0xff) }, 2709 { "Grey11", RGB_(0x1c, 0x1c, 0x1c) }, 2710 { "Grey12", RGB_(0x1f, 0x1f, 0x1f) }, 2711 { "Grey13", RGB_(0x21, 0x21, 0x21) }, 2712 { "Grey14", RGB_(0x24, 0x24, 0x24) }, 2713 { "Grey15", RGB_(0x26, 0x26, 0x26) }, 2714 { "Grey16", RGB_(0x29, 0x29, 0x29) }, 2715 { "Grey17", RGB_(0x2b, 0x2b, 0x2b) }, 2716 { "Grey18", RGB_(0x2e, 0x2e, 0x2e) }, 2717 { "Grey19", RGB_(0x30, 0x30, 0x30) }, 2718 { "Grey2", RGB_(0x5, 0x5, 0x5) }, 2719 { "Grey20", RGB_(0x33, 0x33, 0x33) }, 2720 { "Grey21", RGB_(0x36, 0x36, 0x36) }, 2721 { "Grey22", RGB_(0x38, 0x38, 0x38) }, 2722 { "Grey23", RGB_(0x3b, 0x3b, 0x3b) }, 2723 { "Grey24", RGB_(0x3d, 0x3d, 0x3d) }, 2724 { "Grey25", RGB_(0x40, 0x40, 0x40) }, 2725 { "Grey26", RGB_(0x42, 0x42, 0x42) }, 2726 { "Grey27", RGB_(0x45, 0x45, 0x45) }, 2727 { "Grey28", RGB_(0x47, 0x47, 0x47) }, 2728 { "Grey29", RGB_(0x4a, 0x4a, 0x4a) }, 2729 { "Grey3", RGB_(0x8, 0x8, 0x8) }, 2730 { "Grey30", RGB_(0x4d, 0x4d, 0x4d) }, 2731 { "Grey31", RGB_(0x4f, 0x4f, 0x4f) }, 2732 { "Grey32", RGB_(0x52, 0x52, 0x52) }, 2733 { "Grey33", RGB_(0x54, 0x54, 0x54) }, 2734 { "Grey34", RGB_(0x57, 0x57, 0x57) }, 2735 { "Grey35", RGB_(0x59, 0x59, 0x59) }, 2736 { "Grey36", RGB_(0x5c, 0x5c, 0x5c) }, 2737 { "Grey37", RGB_(0x5e, 0x5e, 0x5e) }, 2738 { "Grey38", RGB_(0x61, 0x61, 0x61) }, 2739 { "Grey39", RGB_(0x63, 0x63, 0x63) }, 2740 { "Grey4", RGB_(0xa, 0xa, 0xa) }, 2741 { "Grey40", RGB_(0x66, 0x66, 0x66) }, 2742 { "Grey41", RGB_(0x69, 0x69, 0x69) }, 2743 { "Grey42", RGB_(0x6b, 0x6b, 0x6b) }, 2744 { "Grey43", RGB_(0x6e, 0x6e, 0x6e) }, 2745 { "Grey44", RGB_(0x70, 0x70, 0x70) }, 2746 { "Grey45", RGB_(0x73, 0x73, 0x73) }, 2747 { "Grey46", RGB_(0x75, 0x75, 0x75) }, 2748 { "Grey47", RGB_(0x78, 0x78, 0x78) }, 2749 { "Grey48", RGB_(0x7a, 0x7a, 0x7a) }, 2750 { "Grey49", RGB_(0x7d, 0x7d, 0x7d) }, 2751 { "Grey5", RGB_(0xd, 0xd, 0xd) }, 2752 { "Grey50", RGB_(0x7f, 0x7f, 0x7f) }, 2753 { "Grey51", RGB_(0x82, 0x82, 0x82) }, 2754 { "Grey52", RGB_(0x85, 0x85, 0x85) }, 2755 { "Grey53", RGB_(0x87, 0x87, 0x87) }, 2756 { "Grey54", RGB_(0x8a, 0x8a, 0x8a) }, 2757 { "Grey55", RGB_(0x8c, 0x8c, 0x8c) }, 2758 { "Grey56", RGB_(0x8f, 0x8f, 0x8f) }, 2759 { "Grey57", RGB_(0x91, 0x91, 0x91) }, 2760 { "Grey58", RGB_(0x94, 0x94, 0x94) }, 2761 { "Grey59", RGB_(0x96, 0x96, 0x96) }, 2762 { "Grey6", RGB_(0xf, 0xf, 0xf) }, 2763 { "Grey60", RGB_(0x99, 0x99, 0x99) }, 2764 { "Grey61", RGB_(0x9c, 0x9c, 0x9c) }, 2765 { "Grey62", RGB_(0x9e, 0x9e, 0x9e) }, 2766 { "Grey63", RGB_(0xa1, 0xa1, 0xa1) }, 2767 { "Grey64", RGB_(0xa3, 0xa3, 0xa3) }, 2768 { "Grey65", RGB_(0xa6, 0xa6, 0xa6) }, 2769 { "Grey66", RGB_(0xa8, 0xa8, 0xa8) }, 2770 { "Grey67", RGB_(0xab, 0xab, 0xab) }, 2771 { "Grey68", RGB_(0xad, 0xad, 0xad) }, 2772 { "Grey69", RGB_(0xb0, 0xb0, 0xb0) }, 2773 { "Grey7", RGB_(0x12, 0x12, 0x12) }, 2774 { "Grey70", RGB_(0xb3, 0xb3, 0xb3) }, 2775 { "Grey71", RGB_(0xb5, 0xb5, 0xb5) }, 2776 { "Grey72", RGB_(0xb8, 0xb8, 0xb8) }, 2777 { "Grey73", RGB_(0xba, 0xba, 0xba) }, 2778 { "Grey74", RGB_(0xbd, 0xbd, 0xbd) }, 2779 { "Grey75", RGB_(0xbf, 0xbf, 0xbf) }, 2780 { "Grey76", RGB_(0xc2, 0xc2, 0xc2) }, 2781 { "Grey77", RGB_(0xc4, 0xc4, 0xc4) }, 2782 { "Grey78", RGB_(0xc7, 0xc7, 0xc7) }, 2783 { "Grey79", RGB_(0xc9, 0xc9, 0xc9) }, 2784 { "Grey8", RGB_(0x14, 0x14, 0x14) }, 2785 { "Grey80", RGB_(0xcc, 0xcc, 0xcc) }, 2786 { "Grey81", RGB_(0xcf, 0xcf, 0xcf) }, 2787 { "Grey82", RGB_(0xd1, 0xd1, 0xd1) }, 2788 { "Grey83", RGB_(0xd4, 0xd4, 0xd4) }, 2789 { "Grey84", RGB_(0xd6, 0xd6, 0xd6) }, 2790 { "Grey85", RGB_(0xd9, 0xd9, 0xd9) }, 2791 { "Grey86", RGB_(0xdb, 0xdb, 0xdb) }, 2792 { "Grey87", RGB_(0xde, 0xde, 0xde) }, 2793 { "Grey88", RGB_(0xe0, 0xe0, 0xe0) }, 2794 { "Grey89", RGB_(0xe3, 0xe3, 0xe3) }, 2795 { "Grey9", RGB_(0x17, 0x17, 0x17) }, 2796 { "Grey90", RGB_(0xe5, 0xe5, 0xe5) }, 2797 { "Grey91", RGB_(0xe8, 0xe8, 0xe8) }, 2798 { "Grey92", RGB_(0xeb, 0xeb, 0xeb) }, 2799 { "Grey93", RGB_(0xed, 0xed, 0xed) }, 2800 { "Grey94", RGB_(0xf0, 0xf0, 0xf0) }, 2801 { "Grey95", RGB_(0xf2, 0xf2, 0xf2) }, 2802 { "Grey96", RGB_(0xf5, 0xf5, 0xf5) }, 2803 { "Grey97", RGB_(0xf7, 0xf7, 0xf7) }, 2804 { "Grey98", RGB_(0xfa, 0xfa, 0xfa) }, 2805 { "Grey99", RGB_(0xfc, 0xfc, 0xfc) }, 2806 { "Honeydew", RGB_(0xf0, 0xff, 0xf0) }, 2807 { "Honeydew1", RGB_(0xf0, 0xff, 0xf0) }, 2808 { "Honeydew2", RGB_(0xe0, 0xee, 0xe0) }, 2809 { "Honeydew3", RGB_(0xc1, 0xcd, 0xc1) }, 2810 { "Honeydew4", RGB_(0x83, 0x8b, 0x83) }, 2811 { "HotPink", RGB_(0xff, 0x69, 0xb4) }, 2812 { "HotPink1", RGB_(0xff, 0x6e, 0xb4) }, 2813 { "HotPink2", RGB_(0xee, 0x6a, 0xa7) }, 2814 { "HotPink3", RGB_(0xcd, 0x60, 0x90) }, 2815 { "HotPink4", RGB_(0x8b, 0x3a, 0x62) }, 2816 { "IndianRed", RGB_(0xcd, 0x5c, 0x5c) }, 2817 { "IndianRed1", RGB_(0xff, 0x6a, 0x6a) }, 2818 { "IndianRed2", RGB_(0xee, 0x63, 0x63) }, 2819 { "IndianRed3", RGB_(0xcd, 0x55, 0x55) }, 2820 { "IndianRed4", RGB_(0x8b, 0x3a, 0x3a) }, 2821 { "Indigo", RGB_(0x4b, 0x00, 0x82) }, 2822 { "Ivory", RGB_(0xff, 0xff, 0xf0) }, 2823 { "Ivory1", RGB_(0xff, 0xff, 0xf0) }, 2824 { "Ivory2", RGB_(0xee, 0xee, 0xe0) }, 2825 { "Ivory3", RGB_(0xcd, 0xcd, 0xc1) }, 2826 { "Ivory4", RGB_(0x8b, 0x8b, 0x83) }, 2827 { "Khaki", RGB_(0xf0, 0xe6, 0x8c) }, 2828 { "Khaki1", RGB_(0xff, 0xf6, 0x8f) }, 2829 { "Khaki2", RGB_(0xee, 0xe6, 0x85) }, 2830 { "Khaki3", RGB_(0xcd, 0xc6, 0x73) }, 2831 { "Khaki4", RGB_(0x8b, 0x86, 0x4e) }, 2832 { "Lavender", RGB_(0xe6, 0xe6, 0xfa) }, 2833 { "LavenderBlush", RGB_(0xff, 0xf0, 0xf5) }, 2834 { "LavenderBlush1", RGB_(0xff, 0xf0, 0xf5) }, 2835 { "LavenderBlush2", RGB_(0xee, 0xe0, 0xe5) }, 2836 { "LavenderBlush3", RGB_(0xcd, 0xc1, 0xc5) }, 2837 { "LavenderBlush4", RGB_(0x8b, 0x83, 0x86) }, 2838 { "LawnGreen", RGB_(0x7c, 0xfc, 0x00) }, 2839 { "LemonChiffon", RGB_(0xff, 0xfa, 0xcd) }, 2840 { "LemonChiffon1", RGB_(0xff, 0xfa, 0xcd) }, 2841 { "LemonChiffon2", RGB_(0xee, 0xe9, 0xbf) }, 2842 { "LemonChiffon3", RGB_(0xcd, 0xc9, 0xa5) }, 2843 { "LemonChiffon4", RGB_(0x8b, 0x89, 0x70) }, 2844 { "LightBlue", RGB_(0xad, 0xd8, 0xe6) }, 2845 { "LightBlue1", RGB_(0xbf, 0xef, 0xff) }, 2846 { "LightBlue2", RGB_(0xb2, 0xdf, 0xee) }, 2847 { "LightBlue3", RGB_(0x9a, 0xc0, 0xcd) }, 2848 { "LightBlue4", RGB_(0x68, 0x83, 0x8b) }, 2849 { "LightCoral", RGB_(0xf0, 0x80, 0x80) }, 2850 { "LightCyan", RGB_(0xe0, 0xff, 0xff) }, 2851 { "LightCyan1", RGB_(0xe0, 0xff, 0xff) }, 2852 { "LightCyan2", RGB_(0xd1, 0xee, 0xee) }, 2853 { "LightCyan3", RGB_(0xb4, 0xcd, 0xcd) }, 2854 { "LightCyan4", RGB_(0x7a, 0x8b, 0x8b) }, 2855 { "LightGoldenrod", RGB_(0xee, 0xdd, 0x82) }, 2856 { "LightGoldenrod1", RGB_(0xff, 0xec, 0x8b) }, 2857 { "LightGoldenrod2", RGB_(0xee, 0xdc, 0x82) }, 2858 { "LightGoldenrod3", RGB_(0xcd, 0xbe, 0x70) }, 2859 { "LightGoldenrod4", RGB_(0x8b, 0x81, 0x4c) }, 2860 { "LightGoldenrodYellow", RGB_(0xfa, 0xfa, 0xd2) }, 2861 { "LightGray", RGB_(0xd3, 0xd3, 0xd3) }, 2862 { "LightGreen", RGB_(0x90, 0xee, 0x90) }, 2863 { "LightGrey", RGB_(0xd3, 0xd3, 0xd3) }, 2864 { "LightMagenta", RGB_(0xff, 0xbb, 0xff) }, 2865 { "LightPink", RGB_(0xff, 0xb6, 0xc1) }, 2866 { "LightPink1", RGB_(0xff, 0xae, 0xb9) }, 2867 { "LightPink2", RGB_(0xee, 0xa2, 0xad) }, 2868 { "LightPink3", RGB_(0xcd, 0x8c, 0x95) }, 2869 { "LightPink4", RGB_(0x8b, 0x5f, 0x65) }, 2870 { "LightRed", RGB_(0xff, 0xbb, 0xbb) }, 2871 { "LightSalmon", RGB_(0xff, 0xa0, 0x7a) }, 2872 { "LightSalmon1", RGB_(0xff, 0xa0, 0x7a) }, 2873 { "LightSalmon2", RGB_(0xee, 0x95, 0x72) }, 2874 { "LightSalmon3", RGB_(0xcd, 0x81, 0x62) }, 2875 { "LightSalmon4", RGB_(0x8b, 0x57, 0x42) }, 2876 { "LightSeaGreen", RGB_(0x20, 0xb2, 0xaa) }, 2877 { "LightSkyBlue", RGB_(0x87, 0xce, 0xfa) }, 2878 { "LightSkyBlue1", RGB_(0xb0, 0xe2, 0xff) }, 2879 { "LightSkyBlue2", RGB_(0xa4, 0xd3, 0xee) }, 2880 { "LightSkyBlue3", RGB_(0x8d, 0xb6, 0xcd) }, 2881 { "LightSkyBlue4", RGB_(0x60, 0x7b, 0x8b) }, 2882 { "LightSlateBlue", RGB_(0x84, 0x70, 0xff) }, 2883 { "LightSlateGray", RGB_(0x77, 0x88, 0x99) }, 2884 { "LightSlateGrey", RGB_(0x77, 0x88, 0x99) }, 2885 { "LightSteelBlue", RGB_(0xb0, 0xc4, 0xde) }, 2886 { "LightSteelBlue1", RGB_(0xca, 0xe1, 0xff) }, 2887 { "LightSteelBlue2", RGB_(0xbc, 0xd2, 0xee) }, 2888 { "LightSteelBlue3", RGB_(0xa2, 0xb5, 0xcd) }, 2889 { "LightSteelBlue4", RGB_(0x6e, 0x7b, 0x8b) }, 2890 { "LightYellow", RGB_(0xff, 0xff, 0xe0) }, 2891 { "LightYellow1", RGB_(0xff, 0xff, 0xe0) }, 2892 { "LightYellow2", RGB_(0xee, 0xee, 0xd1) }, 2893 { "LightYellow3", RGB_(0xcd, 0xcd, 0xb4) }, 2894 { "LightYellow4", RGB_(0x8b, 0x8b, 0x7a) }, 2895 { "Lime", RGB_(0x00, 0xff, 0x00) }, 2896 { "LimeGreen", RGB_(0x32, 0xcd, 0x32) }, 2897 { "Linen", RGB_(0xfa, 0xf0, 0xe6) }, 2898 { "Magenta", RGB_(0xff, 0x00, 0xff) }, 2899 { "Magenta1", RGB_(0xff, 0x0, 0xff) }, 2900 { "Magenta2", RGB_(0xee, 0x0, 0xee) }, 2901 { "Magenta3", RGB_(0xcd, 0x0, 0xcd) }, 2902 { "Magenta4", RGB_(0x8b, 0x0, 0x8b) }, 2903 { "Maroon", RGB_(0x80, 0x00, 0x00) }, 2904 { "Maroon1", RGB_(0xff, 0x34, 0xb3) }, 2905 { "Maroon2", RGB_(0xee, 0x30, 0xa7) }, 2906 { "Maroon3", RGB_(0xcd, 0x29, 0x90) }, 2907 { "Maroon4", RGB_(0x8b, 0x1c, 0x62) }, 2908 { "MediumAquamarine", RGB_(0x66, 0xcd, 0xaa) }, 2909 { "MediumBlue", RGB_(0x00, 0x00, 0xcd) }, 2910 { "MediumOrchid", RGB_(0xba, 0x55, 0xd3) }, 2911 { "MediumOrchid1", RGB_(0xe0, 0x66, 0xff) }, 2912 { "MediumOrchid2", RGB_(0xd1, 0x5f, 0xee) }, 2913 { "MediumOrchid3", RGB_(0xb4, 0x52, 0xcd) }, 2914 { "MediumOrchid4", RGB_(0x7a, 0x37, 0x8b) }, 2915 { "MediumPurple", RGB_(0x93, 0x70, 0xdb) }, 2916 { "MediumPurple1", RGB_(0xab, 0x82, 0xff) }, 2917 { "MediumPurple2", RGB_(0x9f, 0x79, 0xee) }, 2918 { "MediumPurple3", RGB_(0x89, 0x68, 0xcd) }, 2919 { "MediumPurple4", RGB_(0x5d, 0x47, 0x8b) }, 2920 { "MediumSeaGreen", RGB_(0x3c, 0xb3, 0x71) }, 2921 { "MediumSlateBlue", RGB_(0x7b, 0x68, 0xee) }, 2922 { "MediumSpringGreen", RGB_(0x00, 0xfa, 0x9a) }, 2923 { "MediumTurquoise", RGB_(0x48, 0xd1, 0xcc) }, 2924 { "MediumVioletRed", RGB_(0xc7, 0x15, 0x85) }, 2925 { "MidnightBlue", RGB_(0x19, 0x19, 0x70) }, 2926 { "MintCream", RGB_(0xf5, 0xff, 0xfa) }, 2927 { "MistyRose", RGB_(0xff, 0xe4, 0xe1) }, 2928 { "MistyRose1", RGB_(0xff, 0xe4, 0xe1) }, 2929 { "MistyRose2", RGB_(0xee, 0xd5, 0xd2) }, 2930 { "MistyRose3", RGB_(0xcd, 0xb7, 0xb5) }, 2931 { "MistyRose4", RGB_(0x8b, 0x7d, 0x7b) }, 2932 { "Moccasin", RGB_(0xff, 0xe4, 0xb5) }, 2933 { "NavajoWhite", RGB_(0xff, 0xde, 0xad) }, 2934 { "NavajoWhite1", RGB_(0xff, 0xde, 0xad) }, 2935 { "NavajoWhite2", RGB_(0xee, 0xcf, 0xa1) }, 2936 { "NavajoWhite3", RGB_(0xcd, 0xb3, 0x8b) }, 2937 { "NavajoWhite4", RGB_(0x8b, 0x79, 0x5e) }, 2938 { "Navy", RGB_(0x00, 0x00, 0x80) }, 2939 { "NavyBlue", RGB_(0x0, 0x0, 0x80) }, 2940 // Default Neovim palettes. 2941 // Dark/light palette is used for background in dark/light color scheme and 2942 // for foreground in light/dark color scheme. 2943 { "NvimDarkBlue", RGB_(0x00, 0x4c, 0x73) }, 2944 { "NvimDarkCyan", RGB_(0x00, 0x73, 0x73) }, 2945 { "NvimDarkGray1", RGB_(0x07, 0x08, 0x0d) }, 2946 { "NvimDarkGray2", RGB_(0x14, 0x16, 0x1b) }, 2947 { "NvimDarkGray3", RGB_(0x2c, 0x2e, 0x33) }, 2948 { "NvimDarkGray4", RGB_(0x4f, 0x52, 0x58) }, 2949 { "NvimDarkGreen", RGB_(0x00, 0x55, 0x23) }, 2950 { "NvimDarkGrey1", RGB_(0x07, 0x08, 0x0d) }, 2951 { "NvimDarkGrey2", RGB_(0x14, 0x16, 0x1b) }, 2952 { "NvimDarkGrey3", RGB_(0x2c, 0x2e, 0x33) }, 2953 { "NvimDarkGrey4", RGB_(0x4f, 0x52, 0x58) }, 2954 { "NvimDarkMagenta", RGB_(0x47, 0x00, 0x45) }, 2955 { "NvimDarkRed", RGB_(0x59, 0x00, 0x08) }, 2956 { "NvimDarkYellow", RGB_(0x6b, 0x53, 0x00) }, 2957 { "NvimLightBlue", RGB_(0xa6, 0xdb, 0xff) }, 2958 { "NvimLightCyan", RGB_(0x8c, 0xf8, 0xf7) }, 2959 { "NvimLightGray1", RGB_(0xee, 0xf1, 0xf8) }, 2960 { "NvimLightGray2", RGB_(0xe0, 0xe2, 0xea) }, 2961 { "NvimLightGray3", RGB_(0xc4, 0xc6, 0xcd) }, 2962 { "NvimLightGray4", RGB_(0x9b, 0x9e, 0xa4) }, 2963 { "NvimLightGreen", RGB_(0xb3, 0xf6, 0xc0) }, 2964 { "NvimLightGrey1", RGB_(0xee, 0xf1, 0xf8) }, 2965 { "NvimLightGrey2", RGB_(0xe0, 0xe2, 0xea) }, 2966 { "NvimLightGrey3", RGB_(0xc4, 0xc6, 0xcd) }, 2967 { "NvimLightGrey4", RGB_(0x9b, 0x9e, 0xa4) }, 2968 { "NvimLightMagenta", RGB_(0xff, 0xca, 0xff) }, 2969 { "NvimLightRed", RGB_(0xff, 0xc0, 0xb9) }, 2970 { "NvimLightYellow", RGB_(0xfc, 0xe0, 0x94) }, 2971 { "OldLace", RGB_(0xfd, 0xf5, 0xe6) }, 2972 { "Olive", RGB_(0x80, 0x80, 0x00) }, 2973 { "OliveDrab", RGB_(0x6b, 0x8e, 0x23) }, 2974 { "OliveDrab1", RGB_(0xc0, 0xff, 0x3e) }, 2975 { "OliveDrab2", RGB_(0xb3, 0xee, 0x3a) }, 2976 { "OliveDrab3", RGB_(0x9a, 0xcd, 0x32) }, 2977 { "OliveDrab4", RGB_(0x69, 0x8b, 0x22) }, 2978 { "Orange", RGB_(0xff, 0xa5, 0x00) }, 2979 { "Orange1", RGB_(0xff, 0xa5, 0x0) }, 2980 { "Orange2", RGB_(0xee, 0x9a, 0x0) }, 2981 { "Orange3", RGB_(0xcd, 0x85, 0x0) }, 2982 { "Orange4", RGB_(0x8b, 0x5a, 0x0) }, 2983 { "OrangeRed", RGB_(0xff, 0x45, 0x00) }, 2984 { "OrangeRed1", RGB_(0xff, 0x45, 0x0) }, 2985 { "OrangeRed2", RGB_(0xee, 0x40, 0x0) }, 2986 { "OrangeRed3", RGB_(0xcd, 0x37, 0x0) }, 2987 { "OrangeRed4", RGB_(0x8b, 0x25, 0x0) }, 2988 { "Orchid", RGB_(0xda, 0x70, 0xd6) }, 2989 { "Orchid1", RGB_(0xff, 0x83, 0xfa) }, 2990 { "Orchid2", RGB_(0xee, 0x7a, 0xe9) }, 2991 { "Orchid3", RGB_(0xcd, 0x69, 0xc9) }, 2992 { "Orchid4", RGB_(0x8b, 0x47, 0x89) }, 2993 { "PaleGoldenrod", RGB_(0xee, 0xe8, 0xaa) }, 2994 { "PaleGreen", RGB_(0x98, 0xfb, 0x98) }, 2995 { "PaleGreen1", RGB_(0x9a, 0xff, 0x9a) }, 2996 { "PaleGreen2", RGB_(0x90, 0xee, 0x90) }, 2997 { "PaleGreen3", RGB_(0x7c, 0xcd, 0x7c) }, 2998 { "PaleGreen4", RGB_(0x54, 0x8b, 0x54) }, 2999 { "PaleTurquoise", RGB_(0xaf, 0xee, 0xee) }, 3000 { "PaleTurquoise1", RGB_(0xbb, 0xff, 0xff) }, 3001 { "PaleTurquoise2", RGB_(0xae, 0xee, 0xee) }, 3002 { "PaleTurquoise3", RGB_(0x96, 0xcd, 0xcd) }, 3003 { "PaleTurquoise4", RGB_(0x66, 0x8b, 0x8b) }, 3004 { "PaleVioletRed", RGB_(0xdb, 0x70, 0x93) }, 3005 { "PaleVioletRed1", RGB_(0xff, 0x82, 0xab) }, 3006 { "PaleVioletRed2", RGB_(0xee, 0x79, 0x9f) }, 3007 { "PaleVioletRed3", RGB_(0xcd, 0x68, 0x89) }, 3008 { "PaleVioletRed4", RGB_(0x8b, 0x47, 0x5d) }, 3009 { "PapayaWhip", RGB_(0xff, 0xef, 0xd5) }, 3010 { "PeachPuff", RGB_(0xff, 0xda, 0xb9) }, 3011 { "PeachPuff1", RGB_(0xff, 0xda, 0xb9) }, 3012 { "PeachPuff2", RGB_(0xee, 0xcb, 0xad) }, 3013 { "PeachPuff3", RGB_(0xcd, 0xaf, 0x95) }, 3014 { "PeachPuff4", RGB_(0x8b, 0x77, 0x65) }, 3015 { "Peru", RGB_(0xcd, 0x85, 0x3f) }, 3016 { "Pink", RGB_(0xff, 0xc0, 0xcb) }, 3017 { "Pink1", RGB_(0xff, 0xb5, 0xc5) }, 3018 { "Pink2", RGB_(0xee, 0xa9, 0xb8) }, 3019 { "Pink3", RGB_(0xcd, 0x91, 0x9e) }, 3020 { "Pink4", RGB_(0x8b, 0x63, 0x6c) }, 3021 { "Plum", RGB_(0xdd, 0xa0, 0xdd) }, 3022 { "Plum1", RGB_(0xff, 0xbb, 0xff) }, 3023 { "Plum2", RGB_(0xee, 0xae, 0xee) }, 3024 { "Plum3", RGB_(0xcd, 0x96, 0xcd) }, 3025 { "Plum4", RGB_(0x8b, 0x66, 0x8b) }, 3026 { "PowderBlue", RGB_(0xb0, 0xe0, 0xe6) }, 3027 { "Purple", RGB_(0x80, 0x00, 0x80) }, 3028 { "Purple1", RGB_(0x9b, 0x30, 0xff) }, 3029 { "Purple2", RGB_(0x91, 0x2c, 0xee) }, 3030 { "Purple3", RGB_(0x7d, 0x26, 0xcd) }, 3031 { "Purple4", RGB_(0x55, 0x1a, 0x8b) }, 3032 { "RebeccaPurple", RGB_(0x66, 0x33, 0x99) }, 3033 { "Red", RGB_(0xff, 0x00, 0x00) }, 3034 { "Red1", RGB_(0xff, 0x0, 0x0) }, 3035 { "Red2", RGB_(0xee, 0x0, 0x0) }, 3036 { "Red3", RGB_(0xcd, 0x0, 0x0) }, 3037 { "Red4", RGB_(0x8b, 0x0, 0x0) }, 3038 { "RosyBrown", RGB_(0xbc, 0x8f, 0x8f) }, 3039 { "RosyBrown1", RGB_(0xff, 0xc1, 0xc1) }, 3040 { "RosyBrown2", RGB_(0xee, 0xb4, 0xb4) }, 3041 { "RosyBrown3", RGB_(0xcd, 0x9b, 0x9b) }, 3042 { "RosyBrown4", RGB_(0x8b, 0x69, 0x69) }, 3043 { "RoyalBlue", RGB_(0x41, 0x69, 0xe1) }, 3044 { "RoyalBlue1", RGB_(0x48, 0x76, 0xff) }, 3045 { "RoyalBlue2", RGB_(0x43, 0x6e, 0xee) }, 3046 { "RoyalBlue3", RGB_(0x3a, 0x5f, 0xcd) }, 3047 { "RoyalBlue4", RGB_(0x27, 0x40, 0x8b) }, 3048 { "SaddleBrown", RGB_(0x8b, 0x45, 0x13) }, 3049 { "Salmon", RGB_(0xfa, 0x80, 0x72) }, 3050 { "Salmon1", RGB_(0xff, 0x8c, 0x69) }, 3051 { "Salmon2", RGB_(0xee, 0x82, 0x62) }, 3052 { "Salmon3", RGB_(0xcd, 0x70, 0x54) }, 3053 { "Salmon4", RGB_(0x8b, 0x4c, 0x39) }, 3054 { "SandyBrown", RGB_(0xf4, 0xa4, 0x60) }, 3055 { "SeaGreen", RGB_(0x2e, 0x8b, 0x57) }, 3056 { "SeaGreen1", RGB_(0x54, 0xff, 0x9f) }, 3057 { "SeaGreen2", RGB_(0x4e, 0xee, 0x94) }, 3058 { "SeaGreen3", RGB_(0x43, 0xcd, 0x80) }, 3059 { "SeaGreen4", RGB_(0x2e, 0x8b, 0x57) }, 3060 { "SeaShell", RGB_(0xff, 0xf5, 0xee) }, 3061 { "Seashell1", RGB_(0xff, 0xf5, 0xee) }, 3062 { "Seashell2", RGB_(0xee, 0xe5, 0xde) }, 3063 { "Seashell3", RGB_(0xcd, 0xc5, 0xbf) }, 3064 { "Seashell4", RGB_(0x8b, 0x86, 0x82) }, 3065 { "Sienna", RGB_(0xa0, 0x52, 0x2d) }, 3066 { "Sienna1", RGB_(0xff, 0x82, 0x47) }, 3067 { "Sienna2", RGB_(0xee, 0x79, 0x42) }, 3068 { "Sienna3", RGB_(0xcd, 0x68, 0x39) }, 3069 { "Sienna4", RGB_(0x8b, 0x47, 0x26) }, 3070 { "Silver", RGB_(0xc0, 0xc0, 0xc0) }, 3071 { "SkyBlue", RGB_(0x87, 0xce, 0xeb) }, 3072 { "SkyBlue1", RGB_(0x87, 0xce, 0xff) }, 3073 { "SkyBlue2", RGB_(0x7e, 0xc0, 0xee) }, 3074 { "SkyBlue3", RGB_(0x6c, 0xa6, 0xcd) }, 3075 { "SkyBlue4", RGB_(0x4a, 0x70, 0x8b) }, 3076 { "SlateBlue", RGB_(0x6a, 0x5a, 0xcd) }, 3077 { "SlateBlue1", RGB_(0x83, 0x6f, 0xff) }, 3078 { "SlateBlue2", RGB_(0x7a, 0x67, 0xee) }, 3079 { "SlateBlue3", RGB_(0x69, 0x59, 0xcd) }, 3080 { "SlateBlue4", RGB_(0x47, 0x3c, 0x8b) }, 3081 { "SlateGray", RGB_(0x70, 0x80, 0x90) }, 3082 { "SlateGray1", RGB_(0xc6, 0xe2, 0xff) }, 3083 { "SlateGray2", RGB_(0xb9, 0xd3, 0xee) }, 3084 { "SlateGray3", RGB_(0x9f, 0xb6, 0xcd) }, 3085 { "SlateGray4", RGB_(0x6c, 0x7b, 0x8b) }, 3086 { "SlateGrey", RGB_(0x70, 0x80, 0x90) }, 3087 { "Snow", RGB_(0xff, 0xfa, 0xfa) }, 3088 { "Snow1", RGB_(0xff, 0xfa, 0xfa) }, 3089 { "Snow2", RGB_(0xee, 0xe9, 0xe9) }, 3090 { "Snow3", RGB_(0xcd, 0xc9, 0xc9) }, 3091 { "Snow4", RGB_(0x8b, 0x89, 0x89) }, 3092 { "SpringGreen", RGB_(0x00, 0xff, 0x7f) }, 3093 { "SpringGreen1", RGB_(0x0, 0xff, 0x7f) }, 3094 { "SpringGreen2", RGB_(0x0, 0xee, 0x76) }, 3095 { "SpringGreen3", RGB_(0x0, 0xcd, 0x66) }, 3096 { "SpringGreen4", RGB_(0x0, 0x8b, 0x45) }, 3097 { "SteelBlue", RGB_(0x46, 0x82, 0xb4) }, 3098 { "SteelBlue1", RGB_(0x63, 0xb8, 0xff) }, 3099 { "SteelBlue2", RGB_(0x5c, 0xac, 0xee) }, 3100 { "SteelBlue3", RGB_(0x4f, 0x94, 0xcd) }, 3101 { "SteelBlue4", RGB_(0x36, 0x64, 0x8b) }, 3102 { "Tan", RGB_(0xd2, 0xb4, 0x8c) }, 3103 { "Tan1", RGB_(0xff, 0xa5, 0x4f) }, 3104 { "Tan2", RGB_(0xee, 0x9a, 0x49) }, 3105 { "Tan3", RGB_(0xcd, 0x85, 0x3f) }, 3106 { "Tan4", RGB_(0x8b, 0x5a, 0x2b) }, 3107 { "Teal", RGB_(0x00, 0x80, 0x80) }, 3108 { "Thistle", RGB_(0xd8, 0xbf, 0xd8) }, 3109 { "Thistle1", RGB_(0xff, 0xe1, 0xff) }, 3110 { "Thistle2", RGB_(0xee, 0xd2, 0xee) }, 3111 { "Thistle3", RGB_(0xcd, 0xb5, 0xcd) }, 3112 { "Thistle4", RGB_(0x8b, 0x7b, 0x8b) }, 3113 { "Tomato", RGB_(0xff, 0x63, 0x47) }, 3114 { "Tomato1", RGB_(0xff, 0x63, 0x47) }, 3115 { "Tomato2", RGB_(0xee, 0x5c, 0x42) }, 3116 { "Tomato3", RGB_(0xcd, 0x4f, 0x39) }, 3117 { "Tomato4", RGB_(0x8b, 0x36, 0x26) }, 3118 { "Turquoise", RGB_(0x40, 0xe0, 0xd0) }, 3119 { "Turquoise1", RGB_(0x0, 0xf5, 0xff) }, 3120 { "Turquoise2", RGB_(0x0, 0xe5, 0xee) }, 3121 { "Turquoise3", RGB_(0x0, 0xc5, 0xcd) }, 3122 { "Turquoise4", RGB_(0x0, 0x86, 0x8b) }, 3123 { "Violet", RGB_(0xee, 0x82, 0xee) }, 3124 { "VioletRed", RGB_(0xd0, 0x20, 0x90) }, 3125 { "VioletRed1", RGB_(0xff, 0x3e, 0x96) }, 3126 { "VioletRed2", RGB_(0xee, 0x3a, 0x8c) }, 3127 { "VioletRed3", RGB_(0xcd, 0x32, 0x78) }, 3128 { "VioletRed4", RGB_(0x8b, 0x22, 0x52) }, 3129 { "WebGray", RGB_(0x80, 0x80, 0x80) }, 3130 { "WebGreen", RGB_(0x0, 0x80, 0x0) }, 3131 { "WebGrey", RGB_(0x80, 0x80, 0x80) }, 3132 { "WebMaroon", RGB_(0x80, 0x0, 0x0) }, 3133 { "WebPurple", RGB_(0x80, 0x0, 0x80) }, 3134 { "Wheat", RGB_(0xf5, 0xde, 0xb3) }, 3135 { "Wheat1", RGB_(0xff, 0xe7, 0xba) }, 3136 { "Wheat2", RGB_(0xee, 0xd8, 0xae) }, 3137 { "Wheat3", RGB_(0xcd, 0xba, 0x96) }, 3138 { "Wheat4", RGB_(0x8b, 0x7e, 0x66) }, 3139 { "White", RGB_(0xff, 0xff, 0xff) }, 3140 { "WhiteSmoke", RGB_(0xf5, 0xf5, 0xf5) }, 3141 { "X11Gray", RGB_(0xbe, 0xbe, 0xbe) }, 3142 { "X11Green", RGB_(0x0, 0xff, 0x0) }, 3143 { "X11Grey", RGB_(0xbe, 0xbe, 0xbe) }, 3144 { "X11Maroon", RGB_(0xb0, 0x30, 0x60) }, 3145 { "X11Purple", RGB_(0xa0, 0x20, 0xf0) }, 3146 { "Yellow", RGB_(0xff, 0xff, 0x00) }, 3147 { "Yellow1", RGB_(0xff, 0xff, 0x0) }, 3148 { "Yellow2", RGB_(0xee, 0xee, 0x0) }, 3149 { "Yellow3", RGB_(0xcd, 0xcd, 0x0) }, 3150 { "Yellow4", RGB_(0x8b, 0x8b, 0x0) }, 3151 { "YellowGreen", RGB_(0x9a, 0xcd, 0x32) }, 3152 { NULL, 0 }, 3153 }; 3154 3155 /// Translate to RgbValue if \p name is an hex value (e.g. #XXXXXX), 3156 /// else look into color_name_table to translate a color name to its 3157 /// hex value 3158 /// 3159 /// @param[in] name string value to convert to RGB 3160 /// @param[out] idx index in color table or special value 3161 /// return the hex value or -1 if could not find a correct value 3162 RgbValue name_to_color(const char *name, int *idx) 3163 { 3164 if (name[0] == '#' && isxdigit((uint8_t)name[1]) && isxdigit((uint8_t)name[2]) 3165 && isxdigit((uint8_t)name[3]) && isxdigit((uint8_t)name[4]) && isxdigit((uint8_t)name[5]) 3166 && isxdigit((uint8_t)name[6]) && name[7] == NUL) { 3167 // rgb hex string 3168 *idx = kColorIdxHex; 3169 return (RgbValue)strtol(name + 1, NULL, 16); 3170 } else if (!STRICMP(name, "bg") || !STRICMP(name, "background")) { 3171 *idx = kColorIdxBg; 3172 return normal_bg; 3173 } else if (!STRICMP(name, "fg") || !STRICMP(name, "foreground")) { 3174 *idx = kColorIdxFg; 3175 return normal_fg; 3176 } 3177 3178 int lo = 0; 3179 int hi = ARRAY_SIZE(color_name_table) - 1; // don't count NULL element 3180 while (lo < hi) { 3181 int m = (lo + hi) / 2; 3182 int cmp = STRICMP(name, color_name_table[m].name); 3183 if (cmp < 0) { 3184 hi = m; 3185 } else if (cmp > 0) { 3186 lo = m + 1; 3187 } else { // found match 3188 *idx = m; 3189 return color_name_table[m].color; 3190 } 3191 } 3192 3193 *idx = kColorIdxNone; 3194 return -1; 3195 } 3196 3197 const char *coloridx_to_name(int idx, int val, char hexbuf[8]) 3198 { 3199 if (idx >= 0) { 3200 return color_name_table[idx].name; 3201 } 3202 switch (idx) { 3203 case kColorIdxNone: 3204 return NULL; 3205 case kColorIdxFg: 3206 return "fg"; 3207 case kColorIdxBg: 3208 return "bg"; 3209 case kColorIdxHex: 3210 snprintf(hexbuf, 7 + 1, "#%06x", val); 3211 return hexbuf; 3212 default: 3213 abort(); 3214 } 3215 } 3216 3217 int name_to_ctermcolor(const char *name) 3218 { 3219 int i; 3220 int off = TOUPPER_ASC(*name); 3221 for (i = ARRAY_SIZE(color_names); --i >= 0;) { 3222 if (off == color_names[i][0] 3223 && STRICMP(name + 1, color_names[i] + 1) == 0) { 3224 break; 3225 } 3226 } 3227 if (i < 0) { 3228 return -1; 3229 } 3230 TriState bold = kNone; 3231 return lookup_color(i, false, &bold); 3232 }