I edited my original question and title to broaden its scope to any syntax - with SQL used as just an example. You can adapt the examples and the answer to other languages.
By adding suitable highlighting rules, one can make vim highlight multiple languages within the same file. This comes particularly handy for shell scripts, in which each new language block is embedded inside a heredoc. For instance, the above picture shows SQL within four shell heredocs. SQL is displayed mono-color inside EOF
delimited heredocs, in which default highlighting rules apply, By contrast, SQL is displayed multi-color inside SQLDOC
delimited heredocs, in which new highlighting rules were added specific to SQL syntax elements. We can see an issue, however: the last SQLDOC
heredoc is incorrectly highlighted mono-color. How can I fix this and make that block display multi-color SQL highlights?
To reproduce this issue:
Close vim and copy the highlighting file to ~/.vim/after/syntax/sh/heredoc-embed.vim (file contents below).
Start
vim ./vim-heredoc-syntax-issue.sh
(file contents below).
We are often instructed to start vim with -u NONE
to make sure that plugins don't get in the way of reproducing an issue. In this case I can't tell you so. If I use -u NONE
syntax highlighting will not load at all. And I'm unable to find a sequence of vim commands that enables syntax highlighting from -u NONE
to my issue. I tried! but failed. So please start your vim as I explained above and hopefully you'll reproduce this issue. To make sure that it occurs in a reasonably pristine vim configuration, I took the above screenshot in a virtual machine, in which I booted a fresh copy of my Linux distribution, installed vim from the package manager, copied the "heredoc-embed.vim" file, and ran vim.
heredoc-embed.vim
" This VIML code sets SQL syntax highlighting for heredoc content blocks
" marked by word <LANGUAGE>DOWN, i.e. SQLDOC.
" source https://subvisual.co/blog/posts/87-smarter-heredoc-syntax-in-vim/ {{{1
let s:bcs = b:current_syntax
" this unlet instruction is needed before we load each new syntax
unlet b:current_syntax
syntax include @SQL syntax/sql.vim
let b:current_syntax = s:bcs
syntax region hereDocDashSQL matchgroup=Statement start=+<<\s*[-'\\]\?\z(SQLDOC\)+ end=+^\s*\z1+ contains=@SQL
if exists("b:current_syntax")
unlet b:current_syntax
endif
vim-heredoc-syntax-issue.sh
# colorscheme evening
: << EOF
SELECT * FROM table;
EOF
: << SQLDOC
SELECT * FROM table;
SQLDOC
foo() {
: << EOF
SELECT * FROM table;
EOF
: << SQLDOC
SELECT * FROM table;
SQLDOC
}
Similar questions I found on SE:
I'd rather fix mine because the regular expressions are simpler.
Maybe Dr Chip can tell me?
My formula but for Perl heredoc.