Vim HereDoc Highlighting

Issue

I want to get syntax highlighting inside of a bash heredoc. In addition, I want bash variable dereference and command substitution highlighting in the heredoc.

Using these instructions as a starting point, I was able to add variable dereferencing by examining sh.vim. I imagine you could accomplish command substitution in a similar fashion.

let s:bcs = b:current_syntax

unlet b:current_syntax
syntax include @YAML syntax/yaml.vim

syntax region hereDocYAML matchgroup=Statement start=/<<-\?\s*\z(YML\)/ end=/^\s*\z1/ contains=@YAML,hereDocDeref,hereDocDerefSimple

syn match  hereDocDerefSimple  "\$\%(\h\w*\|\d\)"
syn region hereDocDeref  matchgroup=PreProc start="\${" end="}"  contains=@shDerefList,shDerefVarArray

hi def link hereDocDeref PreProc
hi def link hereDocDerefSimple PreProc

My problem is, this doesn’t appear to work in any sort of block (if, function, for, etc.). For example:

highlighting example

The only thing I know is that this is not an indentation problem. Changing indentation has no effect, and using indentation outside of a block works properly.

Solution

The contains on the definition of shIf appears to limit the possible highlights to whatever items are in shIfList group.

Adding your item to the group as follows will give you highlighting withing that region:

syn cluster shIfList add=hereDocYAML

The same principle holds for all other blocks. For example:

syn cluster shFunctionList add=hereDocYAML
syn cluster shLoopList     add=hereDocYAML

It should be noted that the approach you’ve outlined is not generally useful. First of all, it requires that the included syntax file use groups for their contains definitions.

In addition, it works for YAML because bash dereference syntax and YAML syntax do not conflict. For more complicated syntaxes like sed or awk, you will have conflicts, and the rules to resolve those conflicts will likely require a new syntax entirely.

Answered By – Tim Pote

Answer Checked By – Robin (AngularFixing Admin)

Leave a Reply

Your email address will not be published.