A Pandoc Workflow for Writing Letters in LaTeX

Pandoc is a wonderful tool for facilitating a plain text based workflow. I wanted to see if I could integrate Pandoc with my custom LaTeX letter template.

Pandoc generally lets LaTeX through unchanged, but it didn’t seem to like the \begin{letter}{addressee \\ etc. } construct.

The Pandoc solution to this sort of thing is to use a custom template in combination with the --variable=KEY:VALUE construct at the command line.

Custom template

Here’s a minimal custom template we’ll call minletter.latex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
\documentclass[11pt]{letter}

\address{John Q. Public \\ 1234 Main St. \\ Smalltown, CA 91234}
\signature{John Q. Public}

\begin{document}
$if(addressee)$
\begin{letter}{$addressee$}
$else$
\begin{letter}{\mbox{}\\\mbox{}}
$endif$

$body$

\closing{Sincerely,}
\end{letter}
\end{document}

Like all Pandoc custom templates this should be saved in ~/.pandoc/templates.

An example letter

Here’s a simple letter that we can pass to Pandoc. Name this letter-to-joe.md:

1
2
3
4
5
6
7
\opening{Dear Joe,}

How are you?  It's been a long time since we've been in touch. 
Sorry about that $50 I borrowed and never returned. 
Isn't it about time we patched things up?  
By the way, might you have a couple hundred bucks I can borrow? 
I promise to pay you back soon.

Processing the letter with Pandoc

We can then call Pandoc as follows:

1
pandoc letter-to-joe.md -o letter-to-joe.pdf --template minletter --variable=addressee:"Joe McShmoe \\ 9876 Mulberry Ln. \\ Salinas, CA 97654"

Can we improve on this?

The above example works, but it’s not self documenting. Six months from now if I want to write a follow-up letter to Joe (for another loan!) I’ll have to lookup his address again as well as remember the Pandoc command line options I used.

The solution I came up with is based on a a simple Python build system called Fabricate. Fabricate is a single file Python library that can be used to create build scripts for a wide variety of programming languages, command line tools, etc. To install Fabricate just make sure fabricate.py (see website) is somewhere in your PYTHONPATH.

A fabricate make file

Here’s a very simple Fabricate build script for our letter above. Name this letter-to-joe.mk:

1
2
3
4
5
6
7
8
9
10
11
12
from fabricate import *

input = "letter-to-joe.md"
output = "letter-to-joe.pdf"
addressee = r'Joe McShmoe \\ 9876 Mulberry Ln. \\ Salinas, CA 97654'

template = "minletter.latex"

run('pandoc', input,
	'-o', output, 
	'--template', template,
	'--variable=addressee:%s' % addressee)

You can now build the letter simply by typing the following from the command line:

1
python letter-to-joe.mk

Next time I need to write a letter to Joe (or anyone else for that matter) I can simply copy my build script to a new file (e.g. followup-to-joe.mk) and change the input, output, and addressee fields as appropriate.

Other ways to do this?

Have you come up with another, perhaps more elegant, solution? If so, I’d love to hear about it!