Sunday, December 18, 2011

Re: sh (bash) syntax for here-document strings: embedding other languages

On 2011-12-18 10:15, Timothy Madden wrote:
> The \z1 notation does not work for me no matter how much I try ...
> Only the first lines get highlighted (the lines matched by the start
> pattern in syn region ... start=+start_script...+ Other than those
> initial lines, I just get the original highlight from shHereDoc.

I think you want to use a syn-region, you may want a matchgroup=shRedir
to use the normal highlighting for the start and end patterns.


> sh_php_heredoc xxx match
> /\%(<<-\?\s*\("\|'\)\(\S\+\)\1\s*\%(.*\|\\\n\s*\)\n\)\@<=\%(.*\n\)\{-,4}\%(\%(.*\s\+\)\?vim\?\|.*\S\+\s\+ex\):\s*\%(\%(\a\+\%(=[^\n\
> s:]*\)\?:\)*\%(ft\|filetype\)=php\%(:\a\+\%(=[^\n\s:]*\)\?\)*\s*\|set\?\s\+\%(\a\+\%(=[^\n\s:]*\)\?\s\+\)*\%(ft\|filetype\)=php\%(\s\+\a\+\%(=[^\n\s:]*\)\?\)
> *\s*:.*\)$\_.\{0,}\%(^\t*\2$\)\@=/ contained keepend excludenl
> contains=@PHP containedin=shHereDoc
>
> Still, at run-time, the end expression \2, which should be the delimiter
> without the quotes, (\S\+, does not match the delimiter at the end of
> the here-document.
>
> Even if I try to get a shorter RE, still the backreferenced expesssion
> is not matched properly:
> \%(<<-\?\s*\("\|'\)\(\w\+\)\1\s*\%(.*\|\\\n\s*\)\n\)\@<=\_.\{0,}\%(^\t*\2$\)\@=
> \%(<<-\?\s*\("\|'\)\(\w\+\)\1\s*\%(.*\|\\\n\s*\)\n\)\@<=\_.\{0,}\%(^\t*\2$\)\@=

Yikes, start with something even simpler than that until you get it
working and then build it up from there. I wouldn't even try to script
it yet. I have the following (and only the following) in my
~/.vim/after/sh.vim

unlet b:current_syntax
syn include @phpSyntax syntax/php.vim
syn region shPhp matchgroup=shRedir contains=@phpSyntax
\ start=+<<\z(.*\)\ze\n.*vim: ft=php+ end=+\z1+

And it highlights the following sh/php fragment correctly.

php <<EOF
<?php # vim: ft=php ?>
<?php echo "hi there"; ?>
EOF


> Is it possible vim has a bug with regular expressions ?

From :help \@<=

The part of the pattern after "\@<=" and "\@<!" are checked for a
match first, thus things like "\1" don't work to reference \(\) inside
the preceding atom. It does work the other way around:

No comments: