Using set syntax=lang we can override syntax highlighting of current buffer with lang.

Suppose we're editing a Bash script and some string variables are actually HTML code. How to force vim to use HTML syntax highlighting only for part of the code (or limited to only that variable)?

Consider the following bash script:

#!/usr/bin/env bash

a=$(curl "google.com")

b=$(printf "
    <!DOCTYPE html>
        <meta charset=\"UTF-8\">
        <meta name=\"viewport\"
            content=\"width=device-width, initial-scale=1.0\">
        <title>my title</title>
    </html>" \

c='#include "stdio.h"
void main() {
int var=10;
return 0;

I want part a to be highlighted as bash, part b as HTML, and part c and C code.

Is it possible to use some markers in vim DSL as indicators of highlighting portions? (like #start_of_cpp #end_of_cpp)

  • 1
    I think you'll want a plugin for this, for instance: github.com/vim-scripts/SyntaxRange (which is used by an Asciidoc plugin that I use...it enables appropriate syntax highlighting in an AD document's code blocks)
    – B Layer
    Jul 24 at 11:08
  • This describes what the plugin does under the covers: vim.fandom.com/wiki/…
    – B Layer
    Jul 24 at 11:12
  • 2
    I don't think you really need a plugin for this; I think :syntax include should be enough for this? Take a look at the default syntax file for Markdown for an example on how it highlights stuff inside code blocks in Python etc. I don't really have the time for a proper explanation/answer, but that should point you in the right direction to start with. Jul 24 at 14:22

In general :syntax include should be used.

Usually in the main syntax there should be "hooks" -- something that clearly defines begin and end of the foreign syntax block.

In your case it would be tricky to identify why part a should be bash while part b html.

For example in asciidoc(tor) syntax there is a clear definition of the foreign syntax:

curl "google.com"

<b>bold text</b>

So it is quite straightforward then to :syntax include whatever syntax into the source block depending on the "hints": bash, html or whatever.

unlet b:current_syntax
syntax include @srcBash syntax/bash.vim
syntax region srcBashHi start="^\[\%(source\)\?,\s*bash\%(,.*\)*\]\s*\n\z(--\+\)\s*$" end="^.*\n\zs\z1\s*$" keepend contains=@srcBash

unlet b:current_syntax
syntax include @srcHTML syntax/html.vim
syntax region srcHTMLHi start="^\[\%(source\)\?,\s*html\%(,.*\)*\]\s*\n\z(--\+\)\s*$" end="^.*\n\zs\z1\s*$" keepend contains=@srcHTML

Here is proof of concept for your slightly updated example (note I have added suffixes to the variables to "detect" what syntax to use there):

enter image description here

unlet b:current_syntax
syntax include @srcC syntax/c.vim
syntax region srcCHi start="\(^\k\+_c=\)'" end="'" contains=@srcC

unlet b:current_syntax
syntax include @srcHTML syntax/html.vim
syntax region srcHTMLHi start="\(^\k\+_html=\)\@<=$(" end=")$" contains=@srcHTML


There are examples in :help syn-include. There is also an extended example present in :help sh-embed for awk, which uses a recipe like this:

You may wish to embed languages into sh.  I'll give an example courtesy of
Lorance Stinson on how to do this with awk as an example. Put the following
file into $HOME/.vim/after/syntax/sh/awkembed.vim: >

    " AWK Embedding:
    " ==============
    " Shamelessly ripped from aspperl.vim by Aaron Hope.
    if exists("b:current_syntax")
      unlet b:current_syntax
    syn include @AWKScript syntax/awk.vim
    syn region AWKScriptCode matchgroup=AWKCommand start=+[=\\]\@<!'+ skip=+\\'+ end=+'+ contains=@AWKScript contained
    syn region AWKScriptEmbedded matchgroup=AWKCommand start=+\<awk\>+ skip=+\\$+ end=+[=\\]\@<!'+me=e-1 contains=@shIdList,@shExprList2 nextgroup=AWKScriptCode
    syn cluster shCommandSubList add=AWKScriptEmbedded
    hi def link AWKCommand Type
This code will then let the awk code in the single quotes: >
    awk '...awk code here...'
be highlighted using the awk highlighting syntax.  Clearly this may be
extended to other languages.

You can also use heredocs as delimiters (like <<SQL triggers sql highlighting until SQL), or (in the HTML case), use the <!DOCTYPE line and </html> line to define the region.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.