Vim Recipes Typing Using Templates

Using Templates

Problem

You create documents containing boilerplate text and would like to avoid typing it.

For instance, you write HTML documents and don't want to type the standard preamble every time.

Solution

Use templates and associate them with a file extension. When a new file is created with an extension for which a template is available, the template contents will be inserted.

You must first create a skeleton document, e.g.:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3.org/MarkUp/SCHEMA/xhtml11.xsd"
    xml:lang="en">
    <head>            
      <title>Document Title</title>
    </head>
    <body></body>
</html>

Save this document in your Vim directory with the corresponding file extension, e.g. ~/.vim/skel/tmpl.html. (You may also want to make this file read only so you don't modify it by mistake).

Add the following to your .vimrc:

autocmd! BufNewFile * silent! 0r ~/.vim/skel/tmpl.%:e

Now, every time you open a new file Vim checks ~/.vim/skel/ for a file whose name starts with tmpl. and ends with the extension of the file you're creating. It then reads the template file into your new file's buffer.

For example, if you added the template above then invoked Vim with vim page.html, the XHTML above would be inserted into the page.html file automatically.

Discussion

Once you have created a document from a template you have to insert text at various predefined positions. For instance, for the XHTML template, you have to change the contents of <title>…</title>, then start typing between the <body>…</body> tags. Navigating between these points in the document, which are the same every time you use the template, is cumbersome.

The traditional solution is to use placeholders. This involves including some notation in the template file that indicates where your input is required, then providing a method to jump between them.

Here's the previous template with placeholders added:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3.org/MarkUp/SCHEMA/xhtml11.xsd"
    xml:lang="en">
    <head>            
      <title>%TITLE%</title>
    </head>
    <body>%BODY%</body>
</html>

The placeholder notation is arbitrary, but let's stick with %VARIABLE% for the sake of example. Now we need a way to jump between them, and <Ctrl>-p (menmonic: placeholder) seems reasonable. While we're at it, we'll define a function (LoadTemplate()) to replace the autocmd line we added earlier. Add the following to your vimrc:

function! LoadTemplate()
  silent! 0r ~/.vim/skel/tmpl.%:e
  " Highlight %VAR% placeholders with the Todo colour group
  syn match Todo "%\u\+%" containedIn=ALL
endfunction
autocmd! BufNewFile * call LoadTemplate()
"Jump between %VAR% placeholders in Normal mode with
" <Ctrl-p>
nnoremap <c-p> /%\u.\{-1,}%<cr>c/%/e<cr>
"Jump between %VAR% placeholders in Insert mode with
" <Ctrl-p>
inoremap <c-p> <ESC>/%\u.\{-1,}%<cr>c/%/e<cr>

If we create a new HTML file now this is what we see:

See below for ways to automatically jump to the placeholders and for inserting smaller code fragments by using snippets.