Подсветка Vim Markdown (элементы списка и конфликты блоков кода)
Вопрос
Я решил узнать больше о vim и его подсветке синтаксиса.Используя примеры других, я создаю свой собственный файл синтаксиса для Markdown.Я видел mkd.vim и у него тоже есть эта проблема.Моя проблема заключается между элементами списка и подсветкой блока кода.
Кодовый блок определение:
- первая строка пуста
- вторая строка начинается как минимум с 4 пробелов или 1 табуляции
- блок заканчивается пустой строкой
Пример:
Regular text
this is code, monospaced and left untouched by markdown
another line of code
Regular Text
Мой синтаксис Vim для блока кода:
syn match mkdCodeBlock /\(\s\{4,}\|\t\{1,}\).*\n/ contained nextgroup=mkdCodeBlock
hi link mkdCodeBlock comment
Упорядочить элемент списка определение:
- первая строка пуста
- вторая строка начинается с [-+*], за которым следует пробел
- список заканчивается пустой строкой, а затем обычной строкой (не списком)
- между позициями можно добавить любое количество пустых строк
- подсписок указывается с помощью отступа (4 пробела или 1 табуляция)
- строка обычного текста после включения элемента списка как продолжение этого элемента списка
Пример:
Regular text
- item 1
- sub item 1
- sub item 2
- item 2
this is part of item 2
so is this
- item 3, still in the same list
- sub item 1
- sub item 2
Regular text, list ends above
Мой синтаксис Vim для определения элемента списка упорядочения (я выделяю только [-+*]
):
syn region mkdListItem start=/\s*[-*+]\s\+/ matchgroup=pdcListText end=".*" contained nextgroup=mkdListItem,mkdListSkipNL contains=@Spell skipnl
syn match mkdListSkipNL /\s*\n/ contained nextgroup=mkdListItem,mkdListSkipNL skipnl
hi link mkdListItem operator
Я не могу заставить подсветку работать с двумя последними правилами для списка и с блоком кода.
Это пример, который нарушает мою подсветку синтаксиса:
Regular text
- Item 1
- Item 2
part of item 2
- these 2 line should be highlighted as a list item
- but they are highlighted as a code block
В настоящее время я не могу понять, как заставить выделение работать так, как я хочу.
Забыл добавить «глобальное» синтаксическое правило, используемое в обоих правилах, перечисленных ниже.Это делается для того, чтобы они начинались с пустой строки.
syn match mkdBlankLine /^\s*\n/ nextgroup=mkdCodeBlock,mkdListItem transparent
Еще одно примечание:Я должен был быть более ясным.В моем файле синтаксиса правила списка появляются перед правилами блоковых цитат.
Решение
Просто убедитесь, что определение mkdListItem находится после определения mkdCodeBlock, например:
syn match mkdCodeBlock /\(\s\{4,}\|\t\{1,}\).*\n/ contained nextgroup=mkdCodeBlock
hi link mkdCodeBlock comment
syn region mkdListItem start=/\s*[-*+]\s\+/ matchgroup=pdcListText end=".*" contained nextgroup=mkdListItem,mkdListSkipNL contains=@Spell skipnl
syn match mkdListSkipNL /\s*\n/ contained nextgroup=mkdListItem,mkdListSkipNL skipnl
hi link mkdListItem operator
syn match mkdBlankLine /^\s*\n/ nextgroup=mkdCodeBlock,mkdListItem transparent
В документации Vim говорится: :help :syn-define
:
«В случае, если более одного элемента совпадает с той же позицией, тот, который был определен в прошлом победах.Таким образом, вы можете переопределить ранее определенные элементы синтаксиса, используя элемент, который соответствует тому же тексту.Но ключевое слово всегда идет перед совпадением или регионом.И ключевое слово с соответствующим корпусом всегда идет перед ключевым словом с игнорированием случая ».
Другие советы
hcs42 был прав.Я помню, как читал этот раздел сейчас, но забыл о нем, пока hcs24 не напомнил мне об этом.
Вот мой обновленный синтаксис (несколько других настроек), который работает:
""""""""""""""""""""""""""""""""""""""" " Code Blocks: " Indent with at least 4 space or 1 tab " This rule must appear for mkdListItem, or highlighting gets messed up syn match mkdCodeBlock /\(\s\{4,}\|\t\{1,}\).*\n/ contained nextgroup=mkdCodeBlock """"""""""""""""""""""""""""""""""""""" " Lists: " These first two rules need to be first or the highlighting will be " incorrect " Continue a list on the current line or next line syn match mkdListCont /\s*[^-+*].*/ contained nextgroup=mkdListCont,mkdListItem,mkdListSkipNL contains=@Spell skipnl transparent " Skip empty lines syn match mkdListSkipNL /\s*\n/ contained nextgroup=mkdListItem,mkdListSkipNL " Unorder list syn match mkdListItem /\s*[-*+]\s\+/ contained nextgroup=mkdListSkipNL,mkdListCont skipnl
Тао Чжин, возможно, это охватывает ваши варианты использования, но не охватывает синтаксис Markdown.В Markdown элемент списка мог содержать блок кода.Вы можете взглянуть на мое решение здесь
ТЛ;ДР;проблема в том, что vim не позволяет вам сказать что-то вроде: блок, имеющий тот же отступ, что и его контейнер + 4 пробела.Единственное решение, которое я нашел, — это сгенерировать правила для каждого типа блоков, которые могут содержаться в элементах списка для каждого уровня отступа (на самом деле я поддерживаю 42 уровня отступов, но это произвольное число).
Итак, у меня есть markdownCodeBlockInListItemAtLevel1, который должен содержаться в markdownListItemAtLevel1 и иметь не менее 8 начальных пробелов, а затем markdownCodeBlockInListItemAtLevel2, который должен содержаться в markdownListItemAtLevel2, который должен содержаться в markdownListItemAtLevel1, ant должен иметь не менее 10 ведущих пробелов и т. д.
Я знаю, что прошло несколько лет, но, возможно, кто-то сочтет этот ответ полезным, поскольку весь синтаксис, основанный на отступах, страдает от одной и той же проблемы.