When vim is used to write python codes, some keywords in the comments are highlighting with different colors. And the keywords can be found in /usr/share/vim/vim80/syntax/python.vim
, where there is a line:
syn keyword pythonTodo FIXME NOTE NOTES TODO XXX contained
so the words FIXME
, NOTE
, NOTES
, TODO
, XXX
in the comments will be highlighted.
Now I want to add more words in it, such as adding DEBUG
, WARNING
but I don't have sudo so I can not directly edit this file. Is there anyway to solve it? What if I want to specify the color for different words? For example, red for DEBUG
, yellow for WARNING
.
Syntax highlighting is a two-steps process where each step is handled by separate scripts.
Now, Vim uses two "runtime directories":
/usr/share/vim/vimXX/
for you, which you shouldn't touch, sudo
or not,$HOME/.vim/
for you, where all your customization is supposed to take place.Both directories have the same structure so the idea is that you can put your custom stuff there and, as long as it respects the default structure, it will be picked up by Vim automatically.
In this case, your job is to write your own syntax script at $HOME/.vim/syntax/python.vim
, with the following content:
syn keyword pythonTodo DEBUG WARNING contained
which would give you something like that in a new Vim session:
But then comes your second requirement:
What if I want to specify the color for different words? For example, red for
DEBUG
, yellow forWARNING
.
The syntax script doesn't care about colors, only about syntax. It is the color scheme that handles colors but it depends on the hard work of the syntax script. If DEBUG
and WARNING
are both pythonTodo
, then they will both be highlighted the same way.
This is a bit more complex, but not by much. Let's do it step-by-step.
Define a different highlight group, say pythonTodoAlt
, only for WARNING
:
syn keyword pythonTodo DEBUG contained
syn keyword pythonTodoAlt WARNING contained
Do you see that contained
at the end? It means that the highlight group is to be found in other highlight groups that explicitly "contain" it. In this case, pythonTodo
is supposed to be "contained" in pythonComment
, which is defined on the line above in the built-in syntax script:
syn match pythonComment "#.*$" contains=pythonTodo,@Spell
As-is, only pythonTodo
is listed and simply adding the following to your custom syntax script won't work because it will be overridden by the built-in one:
syn match pythonComment "#.*$" contains=pythonTodoAlt,pythonTodo,@Spell
Bummer.
The solution is to add the containedin
attribute to pythonTodoAlt
:
syn keyword pythonTodoAlt WARNING containedin=pythonComment contained
But you are not done yet, because there is no highlighting defined for pythonTodoAlt
:
Syntax scripts tend to define lots and lots of highlight groups but it would be ludicrous to expect every color scheme to handle every highlight group, present and future, explicitly. That's why syntax script authors link their fancy groups, like pythonTodo
, to a small set of "default" groups, like Todo
. In the built-in syntax script, this is done like so:
hi def link pythonTodo Todo
Now, this is the time to decide what to do next.
One possibility is to link pythonTodoAlt
to a different default group, which would be the most "correct" move, but which one? Is there a default highlight group other than Todo
that looks the way you want with the current color scheme? Here is an example where I link pythonTodoAlt
to Constant
because that's the first one that came to mind:
hi def link pythonTodoAlt Constant
Meh.
The other possibility is to directly define the looks of pythonTodoAlt
at the color scheme level. If you don't want or can't edit your color scheme, this is how you do it (see this gist):
" in $MYVIMRC, before defining your color scheme
augroup MyColors
autocmd!
autocmd ColorScheme * highlight pythonTodoAlt cterm=reverse ctermbg=NONE ctermfg=204 gui=reverse guibg=NONE guifg=#ff5f87
augroup END