Terminal Color Schemes (Part 2)
When the Alacritty configuration is changed, the changes immediately apply to all open instances. This has both positive and negative implications. On the positive side, it is pretty convenient for working on color schemes. I have long wanted to improve my Vim color scheme to get rid of some unfortunate color combinations, and Alacritty makes this easier. I want to better understand how Vim color schemes work, so I created a seemingly simple challenge: to determine exactly where a specific color on my screen is configured. This turned out to not be so simple!
There is a light green color that is used pretty prominently in my
current Vim color scheme but is not part of my Alacritty color
scheme. For example, the Haskell keyword module is
displayed in this color. I took a screenshot and used Gimp to determine that the color is
#87ffaf. My goal is to determine exactly how the string
module maps to the color #87ffaf.
First, I checked the haskell.vim syntax script. The
module keyword is assigned to the hsModule
syntax group.
syn keyword hsModule            moduleIn the same file, hsModule is linked to the
hsStructure syntax group.
hi def link hsModule                      hsStructureIn the same file, hsStructure is linked to the
Structure syntax group. As the group name indicates, it is
not specific to Haskell.
hi def link hsStructure                   StructureNext, I checked my Vim color scheme configuration. I am using the
default color scheme, as confirmed by typing
:colorscheme without arguments. The
default.vim color scheme script does not contain any color
configuration, so it was not very helpful. Searching online, I read that
the ron color scheme is the actual default with my
settings, and switching to the ron color scheme explicitly
indeed results in no color changes. The ron.vim color
scheme script contains color configuration, but it did not have any
configuration for the Structure syntax group.
After lots of searching (using find and
grep), I was eventually able to find the
syncolor.vim syntax script. This file defines the
highlighting defaults, and it is loaded by the syntax reset
command, which is executed by the color scheme scripts. The default
settings include many different colors, not just the terminal emulator
colors. This is probably a good way to configure the defaults because
some people may use terminals that are not configured well, but this is
the cause of the unfortunate color combinations that I want to get rid
of.
At this point, I realized that I will likely need to create my own
Vim color scheme, since even the default color scheme uses
colors that are not in my selected palette. Perhaps it is possible to
create a color scheme that uses only the terminal emulator color scheme.
Note that there is a termguicolors flag that looked like it
might be what I want, but I confirmed that other colors are used even
when that flag is set.
In the syncolor.vim syntax script,
Structure is linked to the Type syntax group.
Note that the SynLink command is defined earlier in the
script according to the current settings.
SynLink Structure TypeIn the same file, Type is given color settings!
SynColor Type   term=underline cterm=NONE ctermfg=LightGreen ctermbg=NONE gui=bold guifg=#60ff60 guibg=NONEThe foreground color in the terminal is set to
LightGreen. This looks promising, but I now need to find
how this identifier is mapped to the color code. Color names are defined
in the colors/lists/default.vim file, and string
lightgreen is associated with a different color than the
one that I see!
      \ 'lightgreen': '#90ee90',I also found the same setting in the src/highlight.c
file in the source repository.
            {(char_u *)"lightgreen",    RGB(0x90, 0xEE, 0x90)},None of the colors are set to #87ffaf. I tried
(case-insensitive) searching all of the Vim files (under
/usr/share/vim as well as the Vim source repository), and
the only hit is a 2html.vim syntax script that is sued to
“transform a file to HTML, using the current syntax highlighting”
according to the comments.
    \   121: "#87ffaf", 122: "#87ffd7", 123: "#87ffff", 124: "#af0000",The color is associated with number 121, and searching online
indicates that it is a standard color in the 256 color palette, named
PaleGreen1. In the colors/lists/default.vim
file, there is a different color associated with string
palegreen1!
      \ 'palegreen1': '#9aff9a',You can query the current highlight settings for a syntax group using
the highlight command. (I eventually realized that the
xxx is just placeholder text used to show the colors. That
is an odd choice of placeholder text! There is no need to search for it
on the internet…)
:highlight Type
Type           xxx term=underline ctermfg=121 gui=bold guifg=seagreenSo, the actual setting is 121, aka PaleGreen1, which is
indeed the color that I am looking for according to online references.
That does not match the configuration that I see in the
scripts, however! You can get a bit more information using the
verbose command.
:verbose highlight Type
Type           xxx term=underline ctermfg=121 gui=bold guifg=#60ff60
        Last set from /usr/share/vim/vim82/syntax/syncolor.vim line 40This is the line that I pasted above, setting the color to
LightGreen! Is the LightGreen identifier
mapped to 121 somewhere? Searching for the string 121, I
found it in the src/highlight.c file in the source
repository.
// for xterm with 256 colors...
static int color_numbers_256[28] = {0, 4, 2, 6,
                                 1, 5, 130, 3,
                                 248, 248, 7, 7,
                                 242, 242,
                                 12, 81, 10, 121,
                                 14, 159, 9, 224, 13,
                                 225, 11, 229, 15, -1};The 121 value is in index 17, which corresponds to the index of the
LightGreen color name in the same file.
static char *(color_names[28]) = {
            "Black", "DarkBlue", "DarkGreen", "DarkCyan",
            "DarkRed", "DarkMagenta", "Brown", "DarkYellow",
            "Gray", "Grey", "LightGray", "LightGrey",
            "DarkGray", "DarkGrey",
            "Blue", "LightBlue", "Green", "LightGreen",
            "Cyan", "LightCyan", "Red", "LightRed", "Magenta",
            "LightMagenta", "Yellow", "LightYellow", "White", "NONE"};The lookup_color function uses these two arrays to map
the string LightGreen to value 121. Perhaps that is a bug
in Vim, as LightGreen is assigned indexes 119 or 120
according to online references. The 121 value is interpreted by my
terminal emulator, which uses the correct color even though the colors
in Vim are incorrect. I finally understand why
module is displayed using that particular color.