Фигурные скобки помечены как синтаксическая ошибка в Vim - PullRequest
1 голос
/ 02 апреля 2020

Я использую vim 8.1 и при написании кода C я замечаю, что все мои фигурные скобки используют красный фон с белым передним планом. После некоторых раскопок я нашел эту настройку в своей теме: call s:hi('Error', { 'fg': s:white, 'bg': s:red }) Я подтвердил, что это то, откуда исходит цвет, изменив цвет здесь.

Так как это отмечено как синтаксическая ошибка, и у меня есть syntax on в моем vimr c Я смущен, почему мои фигурные скобки отображаются как синтаксическая ошибка. Это происходит даже в очень простом коде, таком как:

int main(int argc, char **argv) 
{
    return 0;
}

Я запутался, почему это отображается как ошибка. Это происходит, если я ставлю открывающую фигурную скобку в конце основного определения или после него. Если я запускаю clist vim говорит мне, что ошибок нет. vimr c доступен для просмотра по адресу: https://pastebin.com/LukL8MBg

РЕДАКТ. 1: При дальнейшем копании проблема связана с используемой мной колортемой. Существует файл, который содержит это для синтаксиса:

syn keyword cDeclarationOverwrite var const type 
syn match cBraces       "[{}\[\]]"
syn match cParens       "[()]"
syn match cOpSymbols    "=\{1,2}\|!=\|<\|>\|>=\|<=\|++\|+=\|--\|-="
syn match cEndColons    "[,]"
syn match cLogicSymbols "\(&&\)\|\(||\)\|\(!\)"

РЕДАКТИРОВАТЬ 2: По рекомендации пользователя @filbranden я выполнил :scriptnames и увидеть следующее:

1: /usr/share/vim/vimrc
  2: ~/.vimrc
  3: ~/.vim/autoload/plug.vim
  4: /usr/share/vim/vim81/filetype.vim
  5: /usr/share/vim/vim81/ftplugin.vim
  6: /usr/share/vim/vim81/indent.vim
  7: /usr/share/vim/vim81/syntax/syntax.vim
  8: /usr/share/vim/vim81/syntax/synload.vim
  9: /usr/share/vim/vim81/syntax/syncolor.vim
 10: ~/.vim/plugins/purify/vim/colors/purify.vim
 11: ~/.vim/plugins/purify/vim/autoload/purify.vim
 12: /usr/share/vim/vim81/plugin/getscriptPlugin.vim
 13: /usr/share/vim/vim81/plugin/gzip.vim
 14: /usr/share/vim/vim81/plugin/logiPat.vim
 15: /usr/share/vim/vim81/plugin/manpager.vim
 16: /usr/share/vim/vim81/plugin/matchparen.vim
 17: /usr/share/vim/vim81/plugin/netrwPlugin.vim
 18: /usr/share/vim/vim81/plugin/rrhelper.vim
 19: /usr/share/vim/vim81/plugin/spellfile.vim
 20: /usr/share/vim/vim81/plugin/tarPlugin.vim
 21: /usr/share/vim/vim81/plugin/tohtml.vim
 22: /usr/share/vim/vim81/plugin/vimballPlugin.vim
 23: /usr/share/vim/vim81/plugin/zipPlugin.vim
 24: /usr/share/vim/vim81/autoload/dist/ft.vim
 25: /usr/share/vim/vim81/ftplugin/c.vim
 26: /usr/share/vim/vim81/indent/c.vim
 27: ~/.vim/plugins/purify/vim/syntax/c.vim
 28: /usr/share/vim/vim81/syntax/c.vim
Press ENTER or type command to continue

С виду из всего этого, c .vim из плагина очистки загружается до синтаксиса vim / c .vim, который загружается последним.

вывод :set rtp? показывает:

runtimepath=~/.vim,~/.vim/plugins/purify/vim,/usr/share/vim/vimfiles,/usr/share/vim/vim81,/usr/share/vim/vimfiles/after,~/.vim/after

Кто-нибудь может объяснить, почему это происходит?

1 Ответ

2 голосов
/ 04 апреля 2020

Так что мне кажется, что это ошибка в правилах синтаксиса, установленных плагином 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/. Локальное тестирование позволило решить проблему, о которой вы сообщали выше, без каких-либо серьезных проблем. (Запрос на извлечение был быстро объединен, поэтому автор, похоже, согласился с этой ошибкой.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...