Hey everybody, it’s your favorite tech-savvy psychopath with another informative tutorial for you to enjoy. This time I’m going to show you the system I use for adding my own custom syntax highlighting to Vim, using the scripting language informally known as Vimscript. I say “the system I use” rather than “how to do XYZ” because in all honesty I don’t know half of the syntax constructs used by Vimscript for creating syntax highlighting and colorschemes. Basically all I know is how to add keywords to Vim’s syntax highlighting repertoire and how to modify colorscheme files so they use the colors I want (on a side note, syntax files and colorschemes are technically two different kinds of scripts).
Since I never got around to learning advanced metacharacters in Vimscript, I can’t really write a full tutorial on the subject, though I’m sure several good ones exist. Instead, I’m going to show you the system I personally use, which is a subset of Vim’s syntax highlighting capabilities combined with some key bindings and auxiliary scripts that I use.
First let’s look at how to create a basic syntax file in Vimscript. There are basically two levels to a syntax file: linking patterns and keywords to syntax classes specific to the given language, and linking the language-specific classes to universal classes. The language-specific classes take the form of
Element is the name of a syntactic element (which could be a universal class) and
lang is the codename for the language, specifically the value of the environment variable
b:current_syntax corresponding to the current window. There are seven universal classes:
Special. To find out what language code corresponds to the language you’re using, type
:let b:current_syntax. To get an exhaustive, color-coded list showing what patterns and keywords are mapped to what classes, type
This is all rather abstract at the moment. Hopefully a couple screenshots of the output of
:syntax will make it clearer.
Notice how there are three columns – first the syntax class, then the color assigned to that syntax class, then a description of what that syntax class does (matches a pattern or links to something else). Also notice the long list of keywords that are mapped to the
cFunction class. By default Vim doesn’t even highlight C functions. These are rules that I added through the use of Vimscript syntax files.
There are two basic commands used in a syntax file:
syntax is used to link keywords and patterns to language-specific classes while
highlight is used to link language-specific classes with universal classes. As an illustration, here is the syntax file I use for libc:
1 " Syntax highlighting for libc constructs 2 3 syntax keyword cFunction abort 4 syntax keyword cFunction abs 5 syntax keyword cFunction acos 6 syntax keyword cFunction acosh 7 syntax keyword cFunction alarm 8 syntax keyword cFunction asctime 9 syntax keyword cFunction asin 10 syntax keyword cFunction asinh 11 syntax keyword cFunction atan 12 syntax keyword cFunction atanh 13 syntax keyword cFunction atexit 14 syntax keyword cFunction atof 15 syntax keyword cFunction atoi 16 syntax keyword cFunction atol 17 syntax keyword cFunction brk 18 syntax keyword cFunction calloc 19 syntax keyword cFunction ceil 20 syntax keyword cFunction cfgetispeed 21 syntax keyword cFunction cfgetospeed 22 syntax keyword cFunction cfsetispeed 23 syntax keyword cFunction cfsetospeed 24 syntax keyword cFunction chdir 25 syntax keyword cFunction chmod 26 syntax keyword cFunction chown 27 syntax keyword cFunction chroot 28 syntax keyword cFunction clearerr 29 syntax keyword cFunction clock 30 syntax keyword cFunction close 31 syntax keyword cFunction closedir 32 syntax keyword cFunction cos ... 302 303 syntax keyword cConstant O_RDONLY 304 syntax keyword cConstant O_WRONLY 305 syntax keyword cConstant O_RDWR 306 syntax keyword cConstant O_CREAT 307 syntax keyword cConstant O_EXCL 308 syntax keyword cConstant O_NOCTTY 309 syntax keyword cConstant O_TRUNC 310 syntax keyword cConstant O_APPEND 311 syntax keyword cConstant O_NONBLOCK 312 syntax keyword cConstant O_NDELAY 313 syntax keyword cConstant O_SYNC 314 syntax keyword cConstant O_FSYNG 315 syntax keyword cConstant O_ASYNC 316 syntax keyword cConstant O_LARGEFILE 317 syntax keyword cConstant O_ACCMODE 318 syntax keyword cConstant S_ISDIR 319 syntax keyword cConstant S_ISCHR 320 syntax keyword cConstant S_ISBLK 321 syntax keyword cConstant S_ISREG 322 syntax keyword cConstant S_ISFIFO 323 syntax keyword cConstant S_ISLNK 324 syntax keyword cConstant S_IRUSR 325 syntax keyword cConstant S_IWUSR 326 syntax keyword cConstant S_IXUSR 327 syntax keyword cConstant S_IRGRP 328 syntax keyword cConstant S_IWGRP 329 syntax keyword cConstant S_IXGRP 330 syntax keyword cConstant S_IROTH 331 syntax keyword cConstant S_IWOTH 332 syntax keyword cConstant S_IXOTH ... 445 446 syntax keyword cType dev_t 447 syntax keyword cType gid_t 448 syntax keyword cType ino_t 449 syntax keyword cType mode_t 450 syntax keyword cType nlink_t 451 syntax keyword cType pid_t 452 syntax keyword cType pthread_attr_t 453 syntax keyword cType pthread_t 454 syntax keyword cType speed_t 455 syntax keyword cType uid_t 456 syntax keyword cType key_t 457 458 highlight link cFunction Function
Notice how the code at the top designates certain keywords as belonging to the
cFunction class, and the line at the bottom links the
cFunction class to the universal class
Function. This last part need only be done for classes that aren’t yet linked. There’s no need to do it for the
The idea of these syntax files is that you will have a separate one for each language you’re coding in. And that’s exactly what I’ve done with my system. If I find the default syntax file for a language lacking in any way, I add my own syntax rules via an auxiliary file storied in my .vim directory. I then write another Vimscript file to multiplex these files together, which I will now show here. This script is very easy to understand, even if you don’t know Vimscript. All it does is look at the value of
b:current_syntax and decide which auxiliary syntax script to run based on that value. I have several versions of this script, depending on whether I’m using Vim from the DOS prompt, Cygwin, my Arch Linux Live CD, or my Ubuntu VM. The version you see here is what I use in Cygwin.
1 " Add custom syntax highlighting 2 3 if b:current_syntax == 'c' || b:current_syntax == 'cpp' 4 so /cygdrive/c/Users/Public/.vim/libc.vim 5 so /cygdrive/c/Users/Public/.vim/Xlib.vim 6 elseif b:current_syntax == 'bash' || b:current_syntax == 'sh' 7 so /cygdrive/c/Users/Public/.vim/bash.vim 8 elseif b:current_syntax == 'basic' 9 so /cygdrive/c/Users/Public/.vim/qbasic.vim 10 endif 11
Currently I only have scripts for C, Unix shell, and QBASIC, because those were the only languages where I found important keywords missing from the the default syntax files.
Of course, ideally, this script should be run automatically, with as little user intervention as possible. The ideal case would be to put an
so command for it in the _vimrc file so that it runs every time I start up. Unfortunately, I found that when I did this I ended up getting weird errors and not being able to use syntax highlighting at all. I still haven’t figured out why these errors occurred. But in any case, I used the next best alternative – using Vim’s keybinding feature to bind a key that I never use to that script. I added this line to my _vimrc file:
nmap + :so ~/.vim/syntax.vim<CR>
Now whenever I type the plus key in normal mode in Vim, my custom syntax highlighting rules are activated, based on what language I’m currently using. And therein lies my entire system. See you next time and happy hacking!