Ваша основная проблема заключается в том, что Подсветка синтаксического выделения происходит построчно, поэтому любое регулярное выражение, которое должно совпадать в нескольких строках, не будет ничего совпадать, потому что никогда не получает достаточно ввода.Чтобы выполнить такой тип соответствия, вам нужно использовать context stack
для отслеживания состояния построчно.
Синтаксическая документация содержит больше информации по теме, но, по сути, идея заключается в том, что вы временно заменяете (push
на стек контекста) новый набор правил синтаксиса для конкретной ситуации., который принимает подсветку синтаксиса до тех пор, пока не будет pop
для удаления этих правил и возврата к тому, что происходило раньше.
Возможно, это лучше всего продемонстрировать на примере модификации синтаксиса в вашем вопросе:
%YAML 1.2
---
name: Metamath
file_extensions: mm
scope: source.mm
contexts:
main:
- match: \$\(
scope: punctuation.definition.comment.begin
push:
- meta_scope: comment
- match: \$\)
scope: punctuation.definition.comment.end
pop: true
Здесь единственное правило в контексте main
(где начинается сопоставление всех синтаксисов) заинтересовано только в сопоставлении последовательности \$\(
, поэтому любой текст, кроме этого, будет проигнорирован и в конечном итоге будет простымtext.
Когда $(
совпадает, происходит пара вещей.Сначала ему присваивается область действия punctuation.definition.comment.begin
, чтобы пометить его как последовательность начала комментария.Во-вторых, он помещает анонимный контекст в стек контекста с правилами, которые предполагают, что они находятся внутри комментария.
Пока этот контекст активен в стеке, применяются только те правила match
, которые применяются втот контекст, который соответствует \$\)
и ничего больше.Любой текст, который не является этим токеном, игнорируется, но когда этот токен просматривается, ему присваивается область, которая помечает его как конец комментария, а затем pop
удаляет этот анонимный контекст из стека, чтобы вернуться ккакими были правила до того, как комментарий был запущен (которые здесь соответствуют только другим комментариям)
* * * * * * * * * * * * * * * * * * * * * * meta_scope
говорит, что, хотя этот контекст находится на вершине стека, весь текст должен иметь область действия comment
в дополнение к любой другой области, которую он может иметь.Это относится также к тексту, который вызвал этот контекст ($(
), а также к тексту, который вызывает выталкивание контекста ($)
).
В результате все начинаетсяв $(
и заканчивая $)
, включая эти токены, помечается как comment
, в то время как начальному и конечному токенам также назначается область действия, которая указывает, что они являются начальными комментариями (не обязательно, но, тем не менее, в хорошей форме).
Вы также можете использовать специально названные элементы context
вместо анонимного контекста, как показано здесь;как правило, это лучшее решение для случаев, когда правила могут понадобиться более чем в одном месте, или если существует только много правил для сопоставления.
%YAML 1.2
---
name: Metamath
file_extensions: mm
scope: source.mm
contexts:
main:
- match: \$\(
scope: punctuation.definition.comment.begin
push: comment_rules
comment_rules:
- meta_scope: comment
- match: \@\w*
scope: keyword.other
- match: \$\)
scope: punctuation.definition.comment.end
pop: true
Этот пример в основном идентичен первому, нотеперь контекст comment_rules
специально назван и используется по имени.Существует дополнительная запись, которая соответствует любому слову, которое начинается с @
и выделяет его по-разному, но только внутри комментариев.
Делая этотаким образом, вы можете иметь несколько ситуаций, в которых правила комментариев применяются без необходимости дублировать вещи (хотя это по общему признанию придумано в этом примере).
Когда в контексте несколько правил, как в этом примере, этоможет быть немного чище;для чего-то вроде вашего исходного примера, возможно, анонимный контекст немного легче читать и делает вещи немного яснее и более самодостаточными.