How do I define a multi-line string in Vimscript without concatenation or escape sequences?
Answer
let {var} =<< {marker}
Explanation
Vim 8.1 introduced a heredoc syntax for Vimscript that lets you assign multi-line text to a variable using a delimiter marker — no \n concatenation or awkward escape sequences required. The result is a List of strings, one per line.
How it works
let template =<< END
hello world
foo bar
END
=<<is the heredoc operator- Everything between the marker lines (here
END) becomes a list item per line - The closing marker must appear at the very start of a line with no leading whitespace
- The marker name can be any word (e.g.,
EOF,TEXT,HEREDOC) - The resulting variable is a
List, sotemplate[0]is'hello world'
Example
Join and execute a multi-line Ex script without string concatenation:
let cmds =<< EOF
setlocal noexpandtab
setlocal tabstop=4
retab!
EOF
execute join(cmds, "\n")
Or pass JSON to a processing function without painful quoting:
let payload =<< JSON
{"name": "vim", "version": 9}
JSON
let data = json_decode(join(payload, ''))
echo data.name
Tips
- Use
=<< trim ENDto strip leading whitespace from each line (Vim 8.1.1744+), allowing indented heredocs in functions - In Neovim Lua, use a Lua string literal (
[[...]]) instead for the same effect - Vim9 script supports the same syntax
- Requires Vim 8.1+; check with
:echo has('patch-8.1.0051')