Так что мне кажется, что это ошибка в правилах синтаксиса, установленных плагином kyoz/purify
, в частности, в отношении упорядочения правил относительно правил из сред выполнения Vim.
Когда Менеджер плагинов добавил плагин, он добавит каталог этого плагина в 'runtimepath'
и добавит его до каталога времени выполнения Vim. Это сделано для того, чтобы плагины могли переопределять файлы, поставляемые во время выполнения Vim, имея возможность запускаться раньше.
В частности, это означает, что правила синтаксиса в плагине kyoz/purity
будут добавлены до тех из сред выполнения Vim, когда загружается файл типа C.
Теперь получается, что это вызывает конфликт в том, как правила взаимодействуют друг с другом.
Давайте, например, рассмотрим взаимодействие между cParen
(из среды выполнения Vim) и cParens
(из kyoz/purify
.) Для простоты предположим, что мы используем let g:c_no_curly_error = 1
, просто чтобы нам не нужно было обсуждать имея две end=
группы, но то же самое обоснование также применимо для случая, когда эта глобальная переменная не установлена.
При текущем порядке мы получаем cParens
от kyoz/purify
до cParen
из среды выполнения Vim :
" From kyoz/purify:
syn match cParens "[()]"
" From Vim runtime:
syn region cParen transparent start='(' end=')' contains=ALLBUT,...
Теперь первое, что касается правил синтаксиса, это то, что правило, которое приходит после , побеждает. Поэтому, когда Vim встречает (
, который может соответствовать обоим (либо cParens
, который соответствует либо, либо cParen
'start
, который точно соответствует (
), он выберет cParen
(из среды выполнения Vim), так как это произойдет позже.
Все в порядке ... Но тогда почему у нас есть проблема в )
?
Поскольку cParen
является "регионом", Vim сохранит собираюсь попытаться сопоставить end
часть этого. При этом он также попытается сопоставить группы в contains
. Но здесь contains
начинается с ALLBUT
, что означает, что он будет пытаться сопоставить каждую группу , за исключением из тех, что указаны в явном списке. Это означает, что также совпадет cParens
внутри этой группы.
Теперь, вот что вызывает проблему, потому что, если cParens
соответствует )
, то это означает, что )
не будет распознано как конец cParen
. Это на самом деле описано в :help :syn-keepend
:
По умолчанию содержащееся совпадение может скрыть совпадение для конечного шаблона. Это полезно для вложения. Например, регион, начинающийся с {
и заканчивающийся }
, может содержать другой регион. Встреченный }
затем завершит содержащуюся область, но не внешнюю область.
Если вы не хотите этого, аргумент keepend
также сделает сопоставление конечного шаблона внешней области. конец любой содержащийся элемент. Это делает невозможным вложение той же области, но позволяет отдельным элементам выделять части конечного шаблона, не пропуская при этом совпадение с конечным шаблоном.
Так что, если бы у нас было keepend
в правиле региона из среды выполнения Vim это фактически приведет к завершению правила cParen
, что не приведет к возникновению проблемы. Но поскольку это не так, наличие cParens
совпадения с )
означает, что cParen
будет выполняться до конца файла, что приведет к появлению ошибок в фигурных скобках (так как в C они не допускается в круглых скобках.)
Если бы у было было keepend
, ситуация была бы немного лучше, если бы cParen
увидел бы конец. Но это все равно не было бы идеально, поскольку kyov/purify
cParens
будет соответствовать только )
и не будет действительно соответствовать (
. (Вам нужно что-то вроде matchgroup
, чтобы также соответствовать разделителям, но это еще одна топика c.)
Так что это должно объяснить, почему это происходит.
Так что может что с этим делать?
Мне кажется, что здесь лучше было бы загрузить правила в обратном порядке.
" From Vim runtime:
syn region cParen transparent start='(' end=')' contains=ALLBUT,...
" From kyoz/purify:
syn match cParens "[()]"
Поскольку при наличии нескольких совпадений Vim будет использовать правило который приходит последний , он всегда будет вызывать cParens
только для (
, поэтому у нас нет проблемы с группой беглецов. )
будет соответствовать только cParens
(в этом случае это больше не конфликт с cParen
, так как это будет соответствовать только концу группы.)
Это сделает правила из kyov/purify
работает как положено.
Но у него есть побочный эффект! Что правило cParen
из сред выполнения Vim будет полностью скрыто этим плагином. (А также похожие правила, которые совпадают для одних и тех же символов, например, cBlock
.
. Это проблема? Может быть. Кажется, что большинство этих правил помечены transparent
(они не влияют на выделение непосредственно) и в основном используются для пометки ситуаций, таких как пометка несбалансированных или несоответствующих скобок, пометка их как Ошибка (аналогично тому, что вы видели, но для реальных проблем с синтаксисом.)
Если вы считаете, что вариант использования из kyov/purify
(то есть для раскрашивания фигурных скобок) предпочтительнее, чем тот, что во время выполнения Vim, тогда вам может пригодиться затенение правил во время выполнения Vim.
Это может быть достигнуто путем перемещения правил синтаксиса в в подкаталоге after/
. Менеджеры плагинов распознают каталог after/
в плагине и добавляют его после среды выполнения Vim. Это установленный механизм, позволяющий плагинам решать, хотят ли они свои правила. предшествовать тем из сред выполнения Vim (что является наиболее распространенным случаем) или приходить позже.
Поскольку я б Это ошибка в kyov/purify
, я открыл запрос на получение , который перемещает правила для C и C ++ в каталог after/
. Локальное тестирование позволило решить проблему, о которой вы сообщали выше, без каких-либо серьезных проблем. (Запрос на извлечение был быстро объединен, поэтому автор, похоже, согласился с этой ошибкой.)