Current Articles | RSS Feed
In text editors like Vim, syntax highlighting is the feature that shows defined components in different colors depending on their functions in the file. Vim has code syntax highlighting already available for a huge array of programming languages, including PHP, Python, HTML, Ruby, JavaScript, and more, and most of them are installed by default in the $VIM/syntax/ directory, so in most cases you can just open up your source code files and see different parts appropriately color-coded. But what if you're using a little-known language that doesn't have a preinstalled syntax file? Or if you're working with a different type of file altogether and want to create syntax highlighting from scratch? This tutorial shows how easy and even fun it is to write your own syntax highlighting rules for Vim.
Before you start building your own syntax highlighting rules, it may help to look at an existing set of rules. There are two ways you can do this:
:syntax
An easy way to get the right setup for your new syntax file is to copy one of the existing files from $VIM/syntax/ and then delete most of its content, keeping only what you need and modifying it as you like. Alternatively, just create a file with the entries here. The example I'm going to use is for a todo list, with categories such as work, home, and personal. It might look a bit like this:
h: sort out drawers in spare roomw: draft Vim highlighting articlep: email jb@example.com
Create a todo.vim file and start it off like this:
" Vim syntax file" Language: Juliet's todo files" Maintainer: Juliet Kemp " Last Change: Sept 14, 2011" Version: 1if exists("b:current_syntax") finishendifsetlocal iskeyword+=:syn case ignore
"
if
The next line tells Vim that the keywords we'll use include the : character. Keywords match the iskeyword option (use the command :set isk ? to find out what it is currently set to), which should by default include digits, alphabetic characters, /, @, and _. If you have any other punctuation characters in your keywords, you'll need to set them up, as we do here.
:
iskeyword
:set isk ?
The following line tells Vim to ignore case when matching keywords. You can use case match instead if that's more suitable for your language or file type.
case match
Next, add a couple of actual rules:
syn match todoHome "^h: "syn match todoWork "^w: "syn match todoPersonal "^p: "
syn match
Next, we have to set the highlights that apply to each label:
highlight link todoHome Typehighlight link todoWork Stringhighlight link todoPersonal Statement
Finally, set the name of the current syntax file:
let b:current_syntax = "todo"
The next task is to make sure your syntax definitions get loaded the next time you open a todo list. The usual way Vim identifies files is by extension. We'll call any todo list files *.todo, and add this line to ~/.vimrc:
autocmd BufRead,BufNewFile *.todo set filetype=todo
syntax on
:syntax on
Currently, only the initial labels are highlighted. To highlight a whole line, you need to use a region match instead. Try replacing your syn match lines with these:
syn region todoHome start=/^h: / end=//syn region todoWork start=/^w: / end=// syn region todoPersonal start=/^p: / end=//
$
You can set up syntax highlighting such that certain matches get "priority." For example, these lines look for email addresses (as defined by the regular expression in quotes – and this pattern is imperfect, so don't rely on it for anything vital) and set their color:
syn match todoEmail "[a-zA-Z0-9._-]\+@[a-zA-Z0-9./-]\+"highlight link todoEmail Identifier
todoHome
syn region
syn region todoHome start=/^h: / end=// contains=todoEmail
contains
keepend
syn region todoHome start=/^h: / end=// contains=todoEmail keepend
To take this a bit further, you can also use the contained keyword to limit matches to occur only within certain sections. For example, if you wanted to highlight email addresses only within a labeled line, and not if you'd just made a note at the bottom of the file, you could use this syntax:
contained
syn match todoEmail contained "[a-zA-Z0-9._-]\+@[a-zA-Z0-9./-]\+"
contains todoEmail
syn region todoHome start=/^h: / end=// syn region todoWork start=/^h: / end=// contains=todoEmail
You might want to highlight todo items you've completed. You can add a "done" setting for when you add "x" at the start of lines:
syn region todoDone start=/^x[hwp]: / end=//highlight link todoDone Underlined
Ignore
Underlined
All of the above is fine if what you're defining is single, specific matches. But if you're writing syntax for a whole language, you might want an easier way to do it. This is where syn keyword comes in. Suppose you were writing a syntax file for Perl, and you want to group various sorts of blocks together:
syn keyword
syn keyword groupBlockLabels if while for
highlight link
And, of course, it's possible to get a lot more complicated. For instance, you can use the nextgroup option to specify that a certain sort of match should always appear after a certain keyword. After the groupBlockLabels element above, you might want to define a code block, beginning and ending with curly braces, and then specify that this type of block should always occur after a groupBlockLabels element:
nextgroup
groupBlockLabels
syn region codeBlock start=/{/ end=/}/ syn keyword groupBlockLabels if while for nextgroup=codeBlock
One of the best ways to get to grips with syntax highlighting in Vim is to experiment. For more information to support your experimentation, check out the Vim documentation chapter on writing syntax files. In particular, check out the matchgroup and transparent options for more complicated setups. Happy highlighting – and feel free to share your best syntax highlighting tips and tricks in the comments section below!
matchgroup
transparent
Allowed tags: <a> link, <b> bold, <i> italics