Ключевое слово в шаблоне области синтаксиса Vim

Я пытаюсь более или менее воспроизвести для Python подсветку синтаксиса if0 C-подобных файлов в Vim, где код, окруженный #if 0 и #endif, выделен серым цветом (выделен как Comment). Вместо директив препроцессора я хотел бы выделить серым цветом блоки кода Python, начинающиеся с if 0: или if False:.

Вдохновленный этим вопросом, я придумал со следующим кодом, который почти работает:

syn region pyIfFalse start=/^\(\s*\)if \%(0\+\|False\):\n\+\z(\1\s\+\)\S/ skip=/^\%(\z1\S\|^$\)/ end=/^\z1\@!.*/me=s-1
hi def link pyIfFalse Comment

Это приводит к следующему

 if 0: # grayed out (there is a space at the beginning)
   pass
if 0: # not grayed out
  pass

Если я заменю все if на ef (в примере и в шаблоне), оба блока будут выделены серым цветом, а это означает, что проблема должна быть с ключевым словом if.

Следуя этому вопросу, можно переопределить if как keyword contained, но тогда не будет выделен в обычном тексте, поэтому это не похоже на удовлетворительное решение.

Что меня очень удивило, так это то, что подсветка работает для первого блока, но не для второго, с той лишь разницей, что перед if стоит пробел.


person udscbt    schedule 19.06.2016    source источник
comment
В качестве продолжения было бы здорово иметь возможность обнаруживать if 1: ... else: ..., как это делается в настоящее время для C-подобных файлов, но я чувствую, что правила отступа Python сделают это намного сложнее.   -  person udscbt    schedule 20.06.2016


Ответы (1)


Ответ лежит в :help syn-priority.

  1. Когда несколько элементов Match или Region начинаются с одной и той же позиции, элемент, определенный последним, имеет приоритет.
  2. Ключевое слово имеет приоритет над элементами Match и Region.
  3. Элемент, который начинается в более ранней позиции, имеет приоритет над элементами, которые начинаются в более поздних позициях.

В третьей строке примера ключевое слово имеет приоритет над регионом (2.), но в первой строке приоритет имеет регион, поскольку он начался раньше (3.).

Обходной путь, из-за отсутствия лучшей альтернативы, состоит в том, чтобы понизить выделение if до совпадения, определенного перед регионом (1.).

syn clear pythonConditional
syn keyword pythonConditional elif else
syn match pythonIf /\<if\>/
syn region pyIfFalse start=/^\(\s*\)if \%(0\+\|False\):\n\+\z(\1\s\+\)\S/ skip=/^\%(\z1\S\|^$\)/ end=/^\z1\@!.*/me=s-1
hi def link pythonConditional  Conditional
hi def link pythonIf  Conditional
hi def link pyIfFalse Comment
person udscbt    schedule 20.06.2016