VIM is notable for how simple and flexible it can be customized. In this article I will describe in detail how easy and simple it is to create your own rules for syntax highlighting with various examples.
Yes, on Habré about this was already a
article , but in it the topic was considered very superficially, and I will try to understand this in detail. They will cover from the simplest examples, including html backlight enhancements for highlighting habra-tagging tags, to creating highlighting for full-fledged programming languages, with context-sensitive syntax highlighting.
What is especially convenient - you can play with the backlight without any additional movements right while editing your file, immediately watching the result. So I suggest everyone to open VIM and try the examples given in my article.
Keyword highlighting
To begin with, let's look at a simple example: you edit the text and leave for yourself notes like “todo - rewrite this sentence, which would be easier to read.” Let's simplify reading the text and we will highlight the word todo. To do this in command mode, enter
:syn keyword Keyword todo
Voila! 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:
:syn keyword Keyword todo rewrite done
Highlighting by regular expressions
To highlight regular expressions in the Vime, use the following command:
:syn match AnyHighlightStyle /herer-is-regexp/
The main thing to remember is that the syntax of WIM regular expressions differs significantly from Perl-like regular expressions (which many people 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 highlighting numbers:
:syn match Float /\d\+\(\.\d\)\=/

Now consider the example more complicated - let's highlight the function calls. A function call is defined as follows: an identifier followed by an opening bracket (but the bracket itself should not be highlighted. To do this, use the look-ahead construction with \ ze, which requires an atom to the right but does not include it in the matching result (thus the parenthesis will not be highlighted in the function color):
:syn match Function /\w\+\((\)\@=/

Or let's highlight the constructor call: new SomeClassName. To do this, use the construction similar to \ ze, only scanning "back": \ zs
:syn match Function /\(new\s\+\)\@<=\w\+/
Highlighting the regions
Highlighting regions exists 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 remakes. First, highlight the C-style multi-line comments:
:syn region Comment start=/\/\*/ end=/\*\//
Now let's look at an example a bit more complicated: let's highlight the string with a double quotation mark:
:syn region String start=/"/ end=/"/
However, there is a flaw in this design - we cannot include the character itself in the string. ”Let's correct this flaw and make sure that the screened quotes are not considered the end of the string. It is this that created the skip parameter, which“ swallows ”the expression without giving it check for the end of the region:
:syn region String start=/"/ skip=/\\"/ end=/"/

Now it works as it should.
"Folding" (folding) regions
Vim allows you to "collapse" blocks (for example, long comments or blocks of code). For this, the command: syn has the optional parameter fold. So if you want to allow the user to fold comments, simply add fold to the end of the syn command:
:syn region Comment start=/\/\*/ end=/\*\// fold
You just need to make sure that the information from syntax highlighting is used for “folding”:
set foldmethod=syntax
In order to describe the folding {} of the brackets in the code, but at the same time leave the code highlighting inside (which by default “eat”: syn region), you can use the transparent parameter at: syn region:
:syn region CodeBlock start=/{/ end=/}/ transparent fold
In this case, the command will not change the appearance of the block inside {}, but will enable it to collapse.
Backlight styles
The second argument of the command: syn - the style that you want to mark up, can be any line. And in a good way, in order to separate "structure" and "presentation", in: syn the "structural names" with the prefix language indicate the styles, for example:
:syn keyword pascalKeyword begin end var procedure function :syn keyword pascalBuiltinFunction WriteLn ReadLn Assign
And then they match these styles with the styles described in VIM color schemes with the help of the hi (hilight) command:
:hi link pascalKeyword Keyword :hi link pascalBuiltinFunction Keyword
Nested blocks
Now let's consider the following example: we want to highlight our keywords in the comments: TODO, NOTE, which are often left by programmers. For this, VIM has two parameters contained and contains for the structure: syn. contained means that the highlight rule does not apply "in the global" region. And contains = Style1, Style2 means that inside the rule you should look for rules that describe the Style1 and Style2 style. Let's see how it looks like:
:syn keyword CommentKeyword TODO NOTE contained :syn region Comment start=/\/\*/ end=/\*\// contains CommentKeyword :hi link CommentKeyword Keyword
Thus, TODO and NOTE will not be highlighted outside the comments, and only they will be highlighted in the comments.
You can "contain" not only keywords, but also any rules for highlighting. For example, you can select escaped 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: highlighting of habrateg in .html files
If you write habraposts in VIM in .html files, then, unfortunately, habracut-specific tags like habracut, hh will not be highlighted. Correct this misunderstanding. To do this, we climb into the html backlight file: .vim / syntax / html.vim and find out that the tagname highlighting style is called htmlTagName, so typing the command:
:syn keyword htmlTagName habracut source hh video slideshow

Highlighting by extension
Each time to introduce commands to highlight all designs, of course, no one requires. All commands need to be placed in the file (for example) my.vim in the directory (required) .vim / syntax / Now this file will be automatically applied to my files. And in order for the type to be automatically added depending on the extension, it is necessary to add a line to .vimrc:
au BufRead,BufNewFile *.my set filetype=my
BufRead and BufNewFile mean to apply the rule for opening existing and for creating new files.
By the way, if suddenly you didn’t know this command, you can also use it 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 *.dump set filetype=sql
Automatically when you open it will color you as an sql file.
Example entirely
Now let's look at a simple example in its entirety: let's color a certain 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 if else while new for 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"
And lastly
If the language for which you are highlighting is not important register - use the command
syn case ignore
at the beginning of the description of the backlight.
When editing the backlight, you want to constantly see the result. To do this, open the coloring text in another buffer and when you want to update the result just enter: e or: syn off | syn on
UPD: Thanks to
Goder for a large number of comments about errors in the article :)