Подсветка синтаксиса в VIM: полное погружение

Разное > Консоль
VIM примечателен тем, как просто и гибко его можно настраивать. В этой статье я подробно опишу, как легко и просто можно создавать собственные правила подсветки синтаксиса на различных примерах.
Что особенно удобно — играться с подсветкой можно без каких либо дополнительных движений прямо во время редактирования вашего файла, сразу же наблюдая результат. Так что всем предлагаю открыть VIM и пробовать примеры, приведенные в моей статье.

Подсветка ключевых слов


Для начала рассмотрим простой пример: вы редактируете текст и для себя отсавляете в нем записи вида «todo — переписать это предложение что бы было легче читать». Давайте успростим себе чтение текста и будем подсвечивать. Для этого в командном режиме введите 
:syn keyword Keyword todo

Вуаля! Теперь мы в редакторе видимо что-то вроде:



Команда syn(syntax) с первым параметром keyword означает следующее: подсветить слово todo стилем Keyword. Цвет этого стиля зависит от вашей цветовой схемы. Можно перечислять сразу много ключевых слов:

:syn keyword Keyword todo rewrite done


Подсветка по регулярным выраженям


Для подсветки регулрярных выражений в виме используется следующая команда:
:syn match AnyHighlightStyle /herer-is-regexp/

Главное что нужно помнить, что синтаксис вимовских регулярных выражений существенно отличается от Perl-like регулярных выражений (которым многие привыкли): 
Perl-like VIM
oneOrMany+ oneOrMany\+
(group) \(group\)
(optional) \(optional\)\=
(notSoManyTimes){2, 4} \(notSoManyTimes\)\{2, 4}
something(?=lookAhead) something\(lookAhead\)\@=
something(?!shouldNotBeThere) something\(shouldNotBeThere\)\@!
(?\(lookBackword\)\@


В качестве первого примера рассмотрим подсветку чисел:

:syn match Float /\d\+\(\.\d\)\=/



Теперь рассмотрим пример посложнее — давайте подсветим вызовы функций, которы определяются следующим образом: идентификатор, за которым следует открывающаяся скобка (, но саму скобку подсвечивать не надо. Для этого воспольземся look-ahead конструкцией \ze, которая требует наличия атома справа, однако не включает его в результат сопоставления (таким образом круглая скобка не будет подсвечена цветом функции):

:syn match Function /\w\+\((\)\@=/



Или давайте подсветим вызов конструктора: new SomeClassName. Для этого воспользуется конструкцией, схожей с \ze, только сканирующая «назад»:\zs 

:syn match Function /\(new\s\+\)\@\w\+/


Подсветка регионов


Подсветка регионов существует для того, чтобы упростить подсветку блоков имеющих определенные открывающие и закрывающие конструкции, например: комментарии, строки, теги в html и т.д. Синтаксис задания регионов следующий:
:syn region SomeHighlightStyle start=/start-regexp/ end=/end-regexp/ skip=/regexp-to-skip-and-not-treat-as-an-end-regexp/


Рассмотрим его на пример. Для начала подсветим C-style многострочные комментарии:

:syn region Comment start=/\/\*/ end=/\*\//

Тпереь рассмотрим пример чуть посложнее: давайте подсветим строку в ограниченную двойным кавычками:

:syn region String start=/"/ end=/"/

Однако в такой конструкции есть недостаток — мы не можем включить в строку сам символ ". Давайте исправим этот недостаток и сделаем так, чтобы заэкранированные ковычки не считались концом строки. Именно дя этого и создан параметр skip, которы «проглатывает» выражение, не отдавая его проверке на конец региона:

 :syn region String start=/"/ skip=/\\"/ end=/"/ 



Теперь работает как надо.

«Складывание» (folding) регионов


Vim позволяет «сворачивать» блоки (например длинные комментарии или блоки кода). Для этого у команды :syn есть опциональый параметр fold. Так что если вы хотите позволить пользователю сворачивать комментарии, то просто добавте fold в конец команды syn:

:syn region Comment start=/\/\*/ end=/\*\// fold

Нужно только убедиться, что для «складывания» используется информация от подсветки синтаксиса:

set foldmethod=syntax

Для того, чтобы описать сворачивание содержимое {} скобок в коде, но при этом оставить подсветку кода внутри (которую по умолчанию «съест» :syn region), можно воспользоваться параметром transparent у :syn region:

:syn region CodeBlock start=/{/ end=/}/ transparent fold

В этом случаи это правило не изменит внешний вид блока между {}, но даст возможность его сворачивать.

Стили подсветки


Второй аргумент команды :syn — стиль, которым надо разметить, может быть любой строчкой. И по-хорошему, для того чтобы разделить «структуру» и «представление», в :syn в качестве стилей указывают «структурные названия» с префиксом язык, например:

:syn keyword pascalKeyword begin end var procedure function 
:syn keyword pascalBuiltinFunction WriteLn ReadLn Assign

А потом сопоставляют эти стили с стилями, описываемым в цветовых схемах VIM при помощи команды hi (hilight):

 :hi link pascalKeyword Keyword :hi link pascalBuiltinFunction Keyword 


Вложенные блоки


Теперь давайте рассмотрим следующий пример: мы хотим в комментариях выделять свои ключевые слова: TODO, NOTE, которые часто оставляются программистами. Для этого в VIM есть два параметра contained и contains у конструкци :syn. contained означает что правило подсветки не применяется «в глобальном» регионе. А contains=Style1,Style2 означает, что внутри правила стоит искать правила, описывющие стиль Style1 и Style2. Посмотрим к это выглядит:

:syn keyword CommentKeyword TODO NOTE contained 
:syn region Comment start=/\/\*/ end=/\*\// contains CommentKeyword 
:hi link CommentKeyword Keyword 

Таким образом вне комметариев TODO и NOTE подсвечиваться не будут, а в комментариях будут подсвечиваться только они. 

«Содержать» можно не только ключевые слова, но и любые правила подсветки. Например можно выделить в строке экранируемые символы: \n, \t, \r, \b:

 
:syn region String start=/"/ skip=/\\"/ end=/"/ contains=EscapeSymbol 
:syn match EscapeSymbol /\\[ntrb"]/ contained :highlight link EscapeSymbol Keyword 



Практичный пример: подсветка хабратэгов в .html файлах


Если писать хабрапосты в VIM в .html файлах, то, к сожалению, хабраспецифичные типа habracut подсвеичваться не будут. Исправим это недоразумение. Для этого залезаем в файл подсветки html: .vim/syntax/html.vim и выясняем, что стиль подсветки имен тэгов называется htmlTagName, так что введя команду:

:syn keyword htmlTagName habracut source hh video slideshow



Подсветка по расширению


Каждый раз вводить команды для подсветки всех конструкций, безусловно некто требует. Все команды нужно оформить в файле (например) my.vim в директории (обязательно) .vim/syntax/ Теперь для файлов типа my будет автоматически применяться этот ваш скрипт. А что бы тип автоматически проставлялся в зависимости от расширения, необходимо в .vimrc добавить строкчу:

au BufRead,BufNewFile *.my set filetype=my

BufRead и BufNewFile означают применить правило как для открываемых существующих, так и для создаваемых новых файлов.

Кстати, если вдруг вы не знали эту команду, ее можно использовать и для автоматической подсветки файлов с нестандартными расширением: например если вы храните дамп базы данных в файлах .dump, то строчка 


Автоматически при открытии раскрасит вам его как sql файл.

Пример целиком


Теперь рассмотрим простенький пример целиком: давайте раскарасим некотрое подмножество язык javascript:

"В 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\+\)\@

Комментарии
]]> ipv6 ready Kiev LUGLinux4MeНостальгияЛичный сайт skeletora ]]>