-
Notifications
You must be signed in to change notification settings - Fork 23
How to override a colorscheme?
To override some of the colors of an existing colorscheme, for example desert
, put the following into your vimrc
:
augroup desert_override
autocmd!
" I like green statements
autocmd ColorScheme desert hi Statement guifg=#5FD75F ctermfg=green
" I like transparent background for terminals
autocmd ColorScheme desert hi Normal ctermbg=NONE
" I like italic comments
autocmd ColorScheme desert hi Comment cterm=italic gui=italic
" etc ...
augroup END
colorscheme desert
Vim's screen is entirely made of text. Some of that text constitutes the chrome of the editor and the rest is dedicated to displaying the syntax highlighted content of files edited in the editor.
In order to style all those items, Vim uses something called "highlight groups", kind of like tags applied to some specific pieces of text. The whole mechanism is made of two parts: the part responsible for applying specific highlight groups to specific pieces of text and the part responsible for determining how those highlight groups look. The latter is the part we are focusing on in this guide.
The job of a highlight group is to determine how a given item will look in a given environment. In the somewhat maximalist example below:
highlight Visual guifg=#87afd7 guibg=#262626 gui=reverse ctermfg=110 ctermbg=235 cterm=reverse term=reverse
-
Visual
is the name of the highlight group, -
guifg
is the foreground color in GUI Vim, -
guibg
is the background color in GUI Vim, -
gui
is a comma-separated list of typographic attributes in GUI Vim, -
ctermfg
is the foreground color in color terminals, -
ctermbg
is the background color in color terminals, -
cterm
is the typographic attributes in color terminals, -
term
is the typographic attributes in monochrome terminals.
See :help highlight-gui
, :help highlight-ctermfg
, and :help highlight-term
.
But highlight groups don't have to be so extensive. The following line would be just as valid, if less portable:
highlight Visual gui=reverse
And, sometimes, all you want is for a given highlight group to look like another:
highlight link Terminal Normal
See :help :highlight-link
.
Colorschemes like desert
, distributed with Vim, or lucius
, available as a third-party plugin are essentially a way to put together a bunch of highlight
commands like the ones above into a convenient package. If you want to override some highlight groups, you will have to write your own highlight
commands.
Whether your favorite colorscheme came with Vim or not, you might find yourself in a situation where you would like to alter the style of some highlight groups… but without going through the trouble of editing the original colorscheme or creating your own. This is a two-steps process: identify the highlight groups you want to override, then override them.
As mentioned above, highlight groups can be applied to Vim's chrome or to syntax items, but, as they are handled by two separate mechanisms, we can't inspect them the same way. We will deal with syntax items first, and then with chrome items.
Vim provides a bunch of functions that can be used to identify highlight groups but they are a tad too low-level for everyday use. Here is a convenient higher-level wrapper:
command! Inspect echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
To use it…
- put the line above in your
vimrc
, write the file and quit Vim with:wq
, and start Vim again, - position the cursor on the piece of text you want to inspect,
- do
:Inspect<CR>
.
You should see a list of highlight groups being printed in the command-line:
['vimAugroup', 'vimAutoEventList', 'vimAutoEvent']
As mentioned above, highlight groups can be, and usually are, linked to other highlight groups. This helps keep colorschemes manageable by reducing the amount of highlight groups to style explicitly while also creating a bit of indirection. In the example above, you could choose to override vimAutoEvent
but that would only work for the vim
syntax and you would have to engage in a gigantic game of whack-a-mole to override other highlight groups with similar semantics. Follow along to find out how to narrow down your search.
In some cases, you might get an empty list:
[]
which means that there is no highlight group applied to the character under the cursor. Vim falls back to the Normal
highlight group in those cases so you should be targeting Normal
.
Chrome items can't be inspected interactively but they are all documented under :help highlight-groups
. All you have to do is search for the one you want in that section. If you think you have found the right one, the next section tells you how to inspect a highlight group.
You should further inspect any highlight group you may have found earlier with:
:hi NameOfHighlightGroup
which might print a few different things:
vimAugroup xxx cleared " case 1: this highlight group has no style attribute and no link
vimAutoEvent xxx links to Type " case 2: this highlight group is linked to another one
Type xxx term=bold ctermfg=14 guifg=#ffdf00 " case 3: this highlight group is defined explicitly
Syntax-level highlight groups are expected to be linked to a small number of generic highlight groups so it is rare to see the 3rd case on first try, but the 1st and second cases are pretty common. What to do next depends on the current case:
- Case 1, write down the name somewhere for the second step of the process.
- Case 2, repeat the process with
BazQuux
, and again until you get to either case 1 or case 3. - Case 3, write down the name somewhere for the second step of the process.
At that point, you should have identified the desired highlight group.
Now that you have identified the highlight group you want to override it is time to figure out how to apply that override at runtime.
Two principles first:
- the override has to be applied after the colorscheme is sourced,
- the override has to be applied every time the colorscheme is sourced.
Satisfying the first principle is easy enough, you put your own highlight
commands after the colorscheme
command in your vimrc
:
colorscheme desert
" I like green statements
hi Statement guifg=#5FD75F ctermfg=green
" I like transparent background for terminals
hi Normal ctermbg=NONE
" I like italic comments
hi Comment cterm=italic gui=italic
But what if you try a new colorscheme, and go back with :colorscheme desert
? Well, your override is lost. To satisfy the second principle, you can use a neat feature: when Vim sources a colorscheme, it emits the ColorScheme
event with the name of the new colorscheme as value. From there, it is easy to craft an autocommand that will apply the override every time the colorscheme is sourced:
augroup desert_override
autocmd!
autocmd ColorScheme desert hi Statement guifg=#5FD75F ctermfg=green
autocmd ColorScheme desert hi Normal ctermbg=NONE
autocmd ColorScheme desert hi Comment cterm=italic gui=italic
augroup END
Of course, this has to be put before any colorscheme
line to take effect:
augroup desert_override
autocmd!
autocmd ColorScheme desert hi Statement guifg=#5FD75F ctermfg=green
autocmd ColorScheme desert hi Normal ctermbg=NONE
autocmd ColorScheme desert hi Comment cterm=italic gui=italic
augroup END
colorscheme desert
And you can even use a wildcard to have your style override every colorscheme:
augroup highlight_override
autocmd!
autocmd ColorScheme * hi Statement guifg=#5FD75F ctermfg=green
autocmd ColorScheme * hi Normal ctermbg=NONE
autocmd ColorScheme * hi Comment cterm=italic gui=italic
augroup END
colorscheme desert
For all things concerning autocommands, see :help autocommands
. For all things concerning syntax highlighting, see :help syntax
.
You can see all the groups currently active with the following command: :runtime syntax/hitest.vim
, see :help hitest.vim
.