Working with templates

Snippet managers

A flexible and powerful way of working with templates is to use a snippet manager. In Replace the `$$ ... $$` macro with the `\[ ... \]` macros? - Prefer the way LaTeX lays it out, but `$` are faster to write you find a simple explanation of how a snippet manager works. What you do is simply to store each template as a separate snippet and use the power of the snippet manager to modify it on expansion.

YASnippet

Here is an example with YASnippet, a snippet manager for Emacs. The following steps are how to create a simple article template:

  1. Enter the mode you want the snippets in. In this case I guess it is LaTeX-mode.
  2. Do M-x yas/new-snippet.
  3. Enter a name for the snippet.
  4. You will now get a chance to edit the snippet. Mark everything by doing C-x h, then kill it by C-w.
  5. You will now have an empty snippet. Paste the following into it and make sure the snippet ends after \end{document} and not on a new line:

    # -*- mode: snippet -*-
    # name: article
    # key: arttemp
    # --
    \documentclass{article}
    
    \usepackage[${1:english}]{babel}
    
    \title{${2:Title}}
    \author{${3:Author}}
    
    \begin{document}
    
    \maketitle
    
    $0
    
    \end{document}
    
  6. Do C-c C-c to save and load the snippet.

Now you can use the snippet in LaTeX-mode by writing arttemp and then pressing Tab. Note how $1, $2, $3 and $0 defines tab stops and that the three first has default values which can be overridden. Here is an animation that shows how the snippet works:

Animation of the snippet above

Obviously the snippet in the example is a very simple snippet. One snippet I use as a template for articles is 172 lines long. It contains \usepackages for the packages I commonly use, package configuration and macro definitions for macros I commonly use. For more information on how to write snippets see the documentation.

With YASnippet your snippets are stored as files. The manual describes how you can organize snippets. I keep my snippets in ~/.emacs.d/mysnippets and load them by the following in my .emacs:

(setq yas/root-directory "~/.emacs.d/mysnippets"); Develop and keep personal snippets under ~/emacs.d/mysnippets
(yas/load-directory yas/root-directory); Load the snippets

By syncing ~/.emacs.d/mysnippets between computers I get the same snippets on all of them.


You can set up simple templating system with lua.

Sample template sample.tpl:

---
title = "Sample document",
extra_packages = "cmap",
encoding="utf8",
class = "article"
---
\documentclass{${class}}
\usepackage[${encoding}]{inputenc}
\usepackage{${extra_packages}}
\title{${title}}
\begin{document}
\maketitle
${content}
\end{document}

In header delimited with --- strings, default variables are set. They are then included in the code with ${variable_name}. You can overide the variables in the document:

---
title = "Hello world",
extra_packages="lipsum"
---
\section{First one}

\lipsum[1-4]

Now the script luatextemplating.lua

kpse.set_program_name("luatex")
-- Helper functions
-- interp: simple templating
-- usage: print( "${name} is ${value}" % {name = "foo", value = "bar"} )
function interp(s, tab)
  return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
end
getmetatable("").__mod = interp

-- Parse page variables
function table.unserialize(s)
        local getTableFromString = loadstring('return '..s)
        local t = assert(getTableFromString())
        if type(t) ~= 'table' then return end
        return t
end

function string:split(pat)
  pat = pat or '%s+'
  local st, g = 1, self:gmatch("()("..pat..")")
  local function getter(segs, seps, sep, cap1, ...)
    st = sep and seps + #sep
    return self:sub(segs, (seps or 0) - 1), cap1 or sep, ...
  end
  return function() if st then return getter(st, g()) end end
end
-- 
function parseInputFile(filename)
  local f=io.open(filename)
  local s = f:read("*a")
  f:close()
  return parseInput(s)
end
function parseInput(s)
  local start = s:find("---") + 3
  local header_end= s:find("---",start)
  local header= s:sub(start,header_end-1)
  local content= s:sub(header_end+3)
  return table.unserialize("{"..header.."}"),content
end

-- Execution

local arg_message=[[
luatextemplating - generate TeX files from simple templates
usage: 
  luatextemplating templatefile inputfile
result is printed to the stdout
]]


if #arg < 2 then
  texio.write_nl(arg_message)
  return 0
end

local main_header, template = parseInputFile(arg[1])
local file_header, content= parseInputFile(arg[2])

for k, v in pairs(file_header) do
  main_header[k]=v
end

main_header["content"]=content
print(template % main_header)

After running texlua luatextemplating.lua path/to/templates/sample.tpl sample.tex you get this document at the standard output

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{lipsum}
\title{Hello world}
\begin{document}
\maketitle

\section{First one}

\lipsum[1-4]

\end{document}

One way to enable template is to use the facilities provided in the different IDEs.

For example: In TexMaker, you want to keep the templates all in a single folder structure separate from your working folders. Then you use the file-new for existing file option to get the template. Then save it into the working folder. I have my students develop and keep individual project templates this way.

Additionally the IDE TexnicCenter has a similar feature, except you are required to carefully follow the directions in the manual to get the template feature to work. The most important direction is that a new directory must be created in the structure for your template files. (edit: The template feature in TexnicCenter prevents you from accidentally changing a template when you save as.)

I would expect that other IDE have similar features provided.