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:
- Enter the mode you want the snippets in. In this case I guess it is LaTeX-mode.
- Do M-x
yas/new-snippet
. - Enter a name for the snippet.
- You will now get a chance to edit the snippet. Mark everything by doing C-x h, then kill it by C-w.
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}
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:
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 \usepackage
s 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.