VIM syntax highlighting: full immersion
Yes, there was already an article about it in Habr , but the topic was considered very superficially in it, and I will try to understand this in detail. We will cover from the simplest examples, including html highlighting enhancements for highlighting habra marking tags, to creating highlighting for full-fledged programming languages, with "context-sensitive" syntax highlighting.
What is especially convenient - you can play with backlight without any additional movements right while editing your file, immediately observing the result. So I suggest everyone open VIM and try the examples in my article.
Keyword Highlighting
To begin with, consider a simple example: you edit the text and for yourself leave notes in it like “todo - rewrite this sentence so that it would be easier to read”. Let's simplify our reading of the text and highlight the word todo. To do this, in command mode, enter
:synkeywordKeywordtodoVoila! Now we are in the editor, apparently something like:

The syn (syntax) command with the first keyword parameter means the following: highlight the word todo with the Keyword style. The color of this style depends on your color scheme. You can list many keywords at once:
:synkeywordKeywordtodorewritedoneRegular Expression Highlighting
The following command is used to highlight regular expressions in a wim:
:syn match AnyHighlightStyle /herer-is-regexp/The main thing to remember is that the syntax of Wim's regular expressions is significantly different from Perl-like regular expressions (which many are used to):
| Perl-like | Vim |
| oneOrMany + | oneOrMany \ + |
| (group) | \ (group \) |
| (optional) | \ (optional \) \ = |
| (notSoManyTimes) {2, 4} | \ (notSoManyTimes \) \ {2, 4} |
| something (? = lookAhead) | something \ (lookAhead \) \ @ = |
| something (?! shouldNotBeThere) | something \ (shouldNotBeThere \) \ @! |
| (? <= lookBackward) something | \ (lookBackword \) \ @ <= ssomething |
As a first example, consider the highlighting of numbers:
:syn match Float /\d\+\(\.\d\)\=/
Now let's look at an example more complicated - let's highlight the function calls. A function call is defined as follows: an identifier followed by an opening bracket (but you don’t need to highlight the bracket itself. To do this, use the look-ahead construction \ ze, which requires an atom to the right, but does not include it in the result of matching (thus, the parenthesis will not be highlighted with the color of the function):
:syn match Function /\w\+\((\)\@=/
Or let's highlight the constructor call: new SomeClassName. To do this, it will use a construction similar to \ ze, only scanning “backward”: \ zs
:syn match Function /\(new\s\+\)\@<=\w\+/Highlighting regions
Highlighting regions exists in order to simplify the highlighting of blocks with certain opening and closing constructions, for example: comments, lines, tags in html, etc. The syntax for setting regions is as follows:
:syn region SomeHighlightStyle start=/start-regexp/ end=/end-regexp/ skip=/regexp-to-skip-and-not-treat-as-an-end-regexp/Consider use on reamers. First, highlight C-style multi-line comments:
:syn region Comment start=/\/\*/end=/\*\//Now let's look at an example a little more complicated: let's highlight the line in the limited by double quotes:
:syn region String start=/"/end=/"/However, there is a flaw in such a construction - we cannot include the character itself in the string. Let's fix this flaw and make the escaped quotes not be considered the end of the string. It is for this that the skip parameter is created, which “swallows” the expression without giving it away checking at the end of the region:
:syn region String start=/"/ skip=/\\"/end=/"/
Now it works as it should.
"Folding" (folding) of regions
Vim allows you to “collapse” blocks (for example, long comments or blocks of code). To do this, the command: syn has an optional fold parameter. So if you want to let the user collapse comments, just add fold to the end of the syn command:
:syn region Comment start=/\/\*/end=/\*\// foldYou just need to make sure that the information from syntax highlighting is used for “folding”:
set foldmethod=syntaxIn order to describe the folding of the contents of {} brackets in the code, but at the same time leave the code highlighting inside (which by default will “eat”: syn region), you can use the transparent parameter at: syn region:
:syn region CodeBlock start=/{/end=/}/ transparent foldIn this case, the command will not change the appearance of the block inside {}, but will make it possible to collapse it.
Highlight Styles
The second argument to the command: syn - the style to be marked up can be any line. And in a good way, in order to separate “structure” and “presentation”, in: syn indicate “structural names” with the language prefix, for example:
:syn keyword pascalKeyword beginendvarprocedurefunction
:syn keyword pascalBuiltinFunction WriteLn ReadLn Assign
And then they compare these styles with the styles described in VIM color schemes using the hi (hilight) command:
:hi link pascalKeyword Keyword
:hi link pascalBuiltinFunction Keyword
Nested blocks
Now let's look at the following example: we want to highlight our keywords in the comments: TODO, NOTE, which are often left by programmers. To do this, VIM has two parameters contained and contains in the construct: syn. contained means that the highlighting rule is not applied “in the global” region. And contains = Style1, Style2 means that inside the rule it is worth looking for rules that describe the style of Style1 and Style2. Let's see how it looks:
:syn keyword CommentKeyword TODO NOTE contained
:syn region Comment start=/\/\*/end=/\*\// contains CommentKeyword
:hi link CommentKeyword Keyword
Thus, outside TODO and NOTE comments will not be highlighted, and only they will be highlighted in the comments.
You can “contain” not only keywords, but also any highlighting rules. For example, you can select escapable characters in a string: \ n, \ t, \ r, \ b:
:syn region String start=/"/ skip=/\\"/end=/"/ contains=EscapeSymbol
:syn match EscapeSymbol /\\[ntrb"]/ contained
:highlight link EscapeSymbol Keyword

Practical example: Habrateg highlighting in .html files
If you write habraposts in VIM in .html files, then, unfortunately, hub-specific tags like habracut, hh will not be highlighted. Correct this misunderstanding. To do this, we climb into the html: .vim / syntax / html.vim highlighting file and find out that the tag name highlighting style is called htmlTagName, so by entering the command:
:syn keyword htmlTagName habracut source hh video slideshow
Backlight by extension
Each time, enter commands to highlight all designs, of course, no one requires. All commands need to be issued in a file (for example) my.vim in the directory (required) .vim / syntax / Now for your files like my this script will be automatically applied. And so that the type is automatically affixed depending on the extension, you need to add the line in .vimrc:
au BufRead,BufNewFile *.my set filetype=myBufRead and BufNewFile mean to apply the rule both for opened existing and for created new files.
By the way, if suddenly you did not know this command, it can also be used to automatically highlight files with non-standard extensions: for example, if you store a database dump in .dump files, then the line
au BufRead,BufNewFile *.dumpset filetype=sqlAutomatically when you open it will color you it as a sql file.
Whole example
Now let's look at a simple example as a whole: let's colorize a subset of the javascript language:
"В javascript строчки бывают в одинарных и двойных кавычках, и экранировать
if exists("b:current_syntax")
finish
endif
"В javascript строчки бывают в одинарных и двойных кавычках, и экранировать соответсвенно надо разные символы
syn region jsString start=/"/ skip=/\\"/ end=/"/ contains=jsEscapeSymbol,jsDoubleQuoteEscape
syn region jsString start=/'/ skip=/\\'/ end=/'/ contains=jsEscapeSymbol,jsSingleQuoteEscape
syn match jsEscapeSymbol /\\[ntrb]/ contained
syn match jsSingleQuoteEscape /\\'/ contained
syn match jsDoubleQuoteEscape /\\"/ contained
syn match jsFunction /\w\+\((\)\@=/
syn match jsFunction /\(new\s\+\)\@<=\w\+/
"многострочный коментарий /* *
syn region jsComment start=/\/\*/ end=/\*\//
"однострочный коментарий //
syn region jsComment start=/\/\// end=/$/
syn keyword jsKeyword ifelsewhilenewfor throw catch function
hi link jsKeyword Keyword
hi link jsString String
hi link jsEscapeSymbol jsEscape
hi link jsDoubleQuoteEscape jsEscape
hi link jsSingleQuoteEscape jsEscape
hi link jsEscape Keyword
hi link jsComment Comment
hi link jsFunction Function"помечаем, что правила для языка javascript уже загружены
let b:current_syntax="javascript"
Well, lastly
If the language for which you are highlighting is not case sensitive - use the command
syn case ignoreat the beginning of the backlight description. When editing the backlight, I want to constantly see the result. To do this, open the coloring text in another buffer and when you want to update the result simply enter: e or: syn off | syn on
UPD: Thanks to Goder for a lot of comments about errors in the article :)