Vim: нужна помощь в создании пользовательской подсветки синтаксиса

Вот что я получил до сих пор:

syntax match cfg_Comment '#.*$' contains=cfg_DocTag
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

highlight default link cfg_Comment Comment
highlight default link cfg_DocTag  SpecialComment

Отлично работает для чего-то вроде:

##
#   @brief The maximum.
#    @type number
# @default 1

Что я хочу сделать дальше, так это выделить следующее слово после @type с группой Type. Поэтому я сделал следующее:

syntax match cfg_Comment '#.*$' contains=cfg_DocTag,cfg_DocField_type
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

syntax match cfg_DocTag_type   '@type' containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite
syntax match cfg_DocField_type '\a\+' contained

highlight default link cfg_Comment       Comment
highlight default link cfg_DocTag        SpecialComment
highlight default link cfg_DocField_type Type

Есть 2 проблемы с этим:

  1. Теперь @type не выделен, и я понял это, потому что, очевидно, я не указал для него группу, но я ожидал, что он как бы унаследует цвет от своего родительского контейнера cfg_DocTag.
  2. Конечно, теперь все в комментариях имеет цвет Type, а не только слово после @type, и я снова получаю это, потому что я указал, что cfg_Comment является контейнером cfg_DocField_type.

Я знаю, откуда берутся проблемы, но я не знаю, как элегантно их решить и написать как можно меньше шаблонного кода.

Наконец, может кто-нибудь сказать мне, почему

syntax match cfg_DocTag_type '@type' containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite

а также

syntax keyword cfg_DocTag_type @type containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite

не одинаковы? т.е. в первом случае как я описал выше: @type уже не подсвечивается так как группа не указана, а это ожидаемо. Но во втором случае оно подсвечивается, хотя группа не указана, что неожиданно, поэтому создается впечатление, что как ключевое слово оно вообще не подходит. И это легко доказать с помощью простейшего теста:

  1. Подсветка работ:

    syntax match Test '@type'
    
    highlight default link Test Keyword
    
  2. Выделение не работает:

    syntax keyword Test @type
    
    highlight default link Test Keyword
    

Обновлять


После ответа Инго предлагаемое решение действительно работает. Однако мне интересно, почему этого нет?

syntax match cfg_Comment '#.*$' contains=cfg_DocTag
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

syntax match cfg_DocTag_type   '@type' transparent containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite
syntax match cfg_DocField_type '\a\+' contained

highlight default link cfg_Comment       Comment
highlight default link cfg_DocTag        SpecialComment
highlight default link cfg_DocField_type Type

Этот был бы идеальным, если бы он работал. Это освобождает нас от дублирования совпадения комментариев и обеспечивает естественное наследование. Кстати, пропуск @ перед type ничего не меняет, то есть эффект наследования остается неизменным. Но почему cfg_DocField_type не выделено? Есть идеи?


person Alexander Shukaev    schedule 25.10.2013    source источник
comment
Извините за мой нубский вопрос, но не могли бы вы объяснить, что именно вы сделали? Просто положить все в vimrc?   -  person EverythingRightPlace    schedule 26.10.2013
comment
@bashophil: Конечно нет! Если вы расширите какую-то стандартную подсветку синтаксиса, которая уже есть в Vim, скажем, для cpp, тогда вы поместите свой собственный cpp.vim в .vim/after/syntax. Если вы пишете что-то новое с нуля или хотите полностью переопределить стандартное, поставляемое с Vim, скажем, cpp, тогда вам нужно поставить .vim/syntax.   -  person Alexander Shukaev    schedule 26.10.2013


Ответы (1)


Ты уже совсем близко. Ваше сдерживание cfg_DocTag_type в cfg_DocTag не работает, потому что они оба будут совпадать в одной и той же позиции. Если убрать начальный @ из первого, это будет исправлено, но nextgroup=cfg_DocField_type по-прежнему не будет совпадать, потому что, по-видимому, конец совпадения для cfg_DocTag (после тега) заставляет Vim не применять nextgroup.

Что я сделал, так это поместил cfg_DocTag_type на тот же уровень, что и cfg_DocTag, то есть не содержался в последнем. Из минусов только дублирование предматчевого #\s*\zs.

syntax match cfg_Comment '#.*$' contains=cfg_DocTag,cfg_DocTag_type
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

syntax match cfg_DocTag_type   '#\s*\zs@type' nextgroup=cfg_DocField_type skipwhite
syntax match cfg_DocField_type '\a\+' contained

highlight default link cfg_Comment       Comment
highlight default link cfg_DocTag        SpecialComment
highlight default link cfg_DocTag_type   cfg_DocTag
highlight default link cfg_DocField_type Type

Относительно 1.: Он не содержится; только если вы опустите @. Затем добавление transparent даст вам эффект наследования.

Насчет "наконец": я подозреваю, что @ не является частью 'iskeyword' (это не по умолчанию), но он должен быть для :syn keyword.

Подсказка: разработка синтаксического скрипта упрощается, если вы устанавливаете SyntaxAttr.vim — Показать атрибуты подсветки синтаксиса. символа под курсором плагин.

person Ingo Karkat    schedule 25.10.2013
comment
Спасибо, Инго, как обычно - качественный ответ! Пожалуйста, взгляните на мое обновление, так как у меня есть еще один вопрос. - person Alexander Shukaev; 26.10.2013
comment
Как я уже сказал, если вы расширяете соответствие для cfg_DocTag, чтобы включить (некоторые из) DocField_type (например, ` '#\s*\zs[\\@]\l\+\s\w', only then it matches. The nextgroup` не применяется, когда конец совпадения родителя.Однако я не могу найти подтверждающее заявление в справке. - person Ingo Karkat; 26.10.2013