Ты рядом. Одна проблема состоит в том, что шаблоны start=
и end=
по умолчанию включены в регион. Синтаксис sed становится запутанным; то есть он уже интерпретирует sed
как команду s///
.
Это можно исправить с помощью :help :syn-pattern-offset
. Грубо говоря, вы позволяете (включая синтаксис) совпадению начинаться только после sed
(конец начала совпадения региона) + 1 пробела + начальная одинарная кавычка (давая ms=e+1
):
syntax region sedEmbed start=+\<sed\>+ms=e+3 end=+'+ contains=@sed
Но я бы предпочел изменить начальное регулярное выражение и включить начальную одинарную кавычку в совпадение, обработать произвольное количество пробелов между ними (TODO: также принимать аргументы sed, такие как -n
и -e
, если необходимо). Аналогично, конечное совпадение должно быть установлено до шаблона конечной области:
syntax region sedEmbed start="\<sed\s\+'"ms=e+1 end="'"me=s-1 contains=@sed
Теперь я могу выделить что-то вроде sed 's/foo/bar/g'
в обычном буфере.
Интеграция с базовым синтаксисом
Как вы упомянули, что вы видите "без эффекта" (вместо неправильной подсветки), я подозреваю, что вы на самом деле запускаете это расширение синтаксиса в буфере с существующим синтаксисом (вероятно, sh
). Это вызывает дополнительные проблемы, поскольку оригинальные синтаксические элементы затеняют вашу область наложения, так что она не совпадает.
Чтобы это исправить, вам нужно выяснить, какая исходная группа синтаксиса вызывает выделение. :syn list
показывает все активные группы, но это проще, когда вы устанавливаете SyntaxAttr.vim - Показывает синтаксическую подсветку атрибутов символа под курсором плагин. (Я поддерживаю расширенную вилку .)
Для меня работает следующее, но оно немного искажает оригинальный синтаксис оболочки:
setfiletype sh
if exists("b:current_syntax")
unlet b:current_syntax
endif
" Remove sh.vim syntax items that are "in the way".
syn clear kshStatement
syn clear bashStatement
syn clear shQuote
syn clear shSingleQuote
syntax include @sed syntax/sed.vim
syntax region sedEmbed start="\<sed\s\+'"ms=e+1 end="'"me=s-1 contains=@sed
Это документированное расширение обеспечивает практически идеальный план для встраивания других языков в синтаксис сценария оболочки, называя группы синтаксиса syntax/sh.vim
, которые необходимо включить и расширить. Чтобы адаптировать его к sed
, я внес следующие изменения:
- Еще нужно очистить
bashStatement
и kshStatement
, чтобы избежать совпадения ключевого слова с совпадением для добавленной области.
- Добавлена поддержка нескольких
sed
выражений (-e ... -e ...
) и продолжение строки.
- Восстановить правильное значение
b:current_syntax
.
syn clear kshStatement
syn clear bashStatement
let s:save_syntax = b:current_syntax
unlet b:current_syntax
syn include @shSedScript syntax/sed.vim
let b:current_syntax = s:save_syntax
unlet s:save_syntax
syn match shSedLineContinuation "\\\s*$" contained skipempty nextgroup=shSedExpression
syn match shSedExpression "\%(^\|\_s\+\)-\a*e\a*\_s\+" contained nextgroup=shSedScriptCode
syn region shSedScriptCode matchgroup=shSedCommand start=+[=\\]\@<!'+ skip=+\\'+ end=+'+ contains=@shSedScript contained skipwhite skipempty nextgroup=shSedLineContinuation,shSedExpression
syn region shSedScriptEmbedded matchgroup=shSedCommand start=+\<sed\>+ skip=+\\$+ end=+[=\\]\@<!'+me=e-1 contains=@shIdList,@shExprList2 nextgroup=shSedScriptCode
syn cluster shCommandSubList add=shSedScriptEmbedded
hi def link shSedCommand Type
hi def link shSedExpression shSetOption