Jeromy Anglim's Blog: Psychology and Statistics

Monday, July 23, 2012

Beamer presentations using pandoc, markdown, LaTeX, and a makefile

This post discusses the creation of beamer presentations using a combination of markdown, pandoc, and LaTeX. This workflow offers the potential to reduce typing and increase readability of beamer presentation source code. Source code for an example presentation is provided containing markdown and LaTeX source code along with a makefile for building the beamer PDF.


I've used beamer quite a lot to prepare slides for both research and teaching purposes (e.g., this 2010 presentation on R Workflow). I've also written up a guide to getting started with beamer and a simple beamer template.

Nonetheless, for some time I've been concerned about the high ratio of markup to content in beamer presentations. I even asked a question on TeX.SE on strategies for dealing with this issue. I find that beamer markup is a burden. It interferes with content creation. Creating, editing, and re-arranging slides is more difficult than it needs to be. The high quantity of markup also interferes with readability.

Several ways of dealing with this.

  • Use LaTeX macros: I.e., to shorten common environments. However, this reduces readability if it is ad hoc.
  • Org Mode in Emacs. This sounds good, but I'm more experienced with Vim.
  • Code Snippets. Code snippets partially solve the typing issue, but they don't solve the readability issue.

In the end, I decided to explore the combination of pandoc, markdown, and LaTeX to create a beamer presentation. The reasons for this included that:

  • Markdown is a really intuitive markup format that is easy to read and easy to modify.
  • When pandoc converts markdown to LaTeX, any LaTeX is passed straight through. Thus, it is possible to obtain customisation beyond the basic options provided by markdown.

Existing resources on combining Beamer, markdown and pandoc

John MacFarlane, author of pandoc, has some relevant documentation on slide production Important points:

  • The basic compilation command is: pandoc -t beamer -o my_beamer.pdf
  • The post explains the slide separation rules.
  • You can have incremental lists by pre-pending dot points with the greater than symbol
  • Beamer Themes can be used via the -V option e.g., (-V theme:Warsaw)
  • It shows how the first few lines of the file pre-pended by % are incorporated into the title slide

Stephen Sinclair has a tutorial. Relevant points include:

  • Latex gets passed directly through
    • Equations can be passed directly through
    • Image size and placement can be controlled in detail with latex e.g., \centerline{\includegraphics[height=2in]{my_image.pdf}}
    • You can use bibtex for citations
  • He also mentions a number of other options for compiling the document involving templates, regular expressions, and so on.

My approach

My approach involved running a makefile which converted a markdown file into a tex file, which was then incorporated into another tex file and then converted into a pdf.

To use the approach you would need the following software:

  • LaTeX distribution with beamer package
  • pandoc
  • support for make: On Linux, make is installed by default; on Windows, you may need something like cygwin or Rtools.


The makefile was as follows:

    pandoc --slide-level 2 -t beamer -o talk.tex
    pdflatex main.tex
    pdflatex main.tex
    -xdg-open main.pdf
  • pandoc converted into a beamer latex file talk.tex
  • --slide-level 2 meant that level 1 markdown headings (i.e., lines preceded with a single hash: # Section name) represented section headings used in the presentation, and level 2 headings (i.e., lines preceded with two hashes ## Slide Title) represented new slides and their title.
  • The line -xdg-open main.pdf opens the resulting pdf file on Linux, but xdg-open could be replaced by the name of pdf viewer (e.g., on a different operating system).

Preamble LaTeX file: main.tex

I had a main LaTeX file (main.tex) as follows:

\setbeamertemplate{navigation symbols}{}

% more preamble...




  • The file is completely in latex and includes the preamble the document environment, some opening slides with particular features, and the input command which reads in the file talk.tex.
  • talk.tex is generated by pandoc from and contains all the individual content slides.
  • I prefer to exclude navigation symbols.
  • Naturally, usetheme could be altered to some other theme (see the beamer theme matrix), such as default.

Body markdown slide file: contained all the individual markdown slides.

For example a basic slide might look as follows:

* Some point to make
    * Another point
    * Another point
* Some point to make
    * Another point
    * Another point
  • The first line adds a section title. This is not part of the slide, but can be used to generate table of contents, and in slide navigation.
  • The second line starts a new slide with the content to the right of the double hash constituting the slide title.
  • And then subsequent lines generate a two-level list represented in LaTeX using the itemize environment.

In general, markdown is converted by pandoc into sensible beamer content. See the actual markdown file and resulting tex file talk.tex. However, pandoc passes any LaTeX through as is, and this is sometimes required.

For incorporating images, I found the default markdown image command led to an excessively large image. Thus, I used LaTeX for images. I'd like to think that there is a way of making default images work well, but I didn't work it out. Thus, instead, I used commands like the following:

  • I often had to tweak the image width to get it the right size.
  • I also read about some other options, which I discuss here.

Obviously there are many reasons that you might want to fall back to LaTeX. In my talk, I tried to keep things simple, so the main instances were:

  • Images as shown above
  • Small text for footnotes often with a url inside: e.g., \tiny{some text and a link: \url{}}
  • Large text at the end of the talk: e.g., \begin{center} \LARGE{Questions?} \end{center}


Overall, there were pros and cons to the approach I adopted.

  • By incorporating markdown and pandoc, there was an extra layer of complexity to think about to ensure that the conversion process had the desired effect. Error messages were sometimes more difficult to diagnose.
  • There were a lot of situations where you might want to have more control over slide content than what you get by default with Markdown.
  • There is an argument to suggest that slide creation is best in a WYSIWIG environment where you can manually tweak image positioning and layout.

Nonetheless, I really liked how easy it was to create, edit, and read dot points, nested dot points, frames, sections, and basic formatting, and in general it was relatively easy to incorporate LaTeX when required. I also like the idea of where possible using open plain-text file formats to take advantage of easier programmability, version control, incorporating into a powerful text editor, simpler conversion, and so on.

Other aspects

The following are a few other aspects that might interest some readers, particularly Vim users.

Syntax highlighting of markdown+LaTeX in Vim

There is a Vim plugin for pandoc that provides many features including syntax highlighting for documents that combine multiple markups including markdown and LaTeX. I found it best to install the latest version available on github:

Code folding of markdown-Beamer

I also have the following script in my .vimrc file. The great thing about it is that it allows code folding if you use hash style markdown headings. It is setup to only fold on headings 1 and 2. This corresponds to sections and slides in my pandoc setting for beamer markdown documents. To increase the level, change it to MarkdownLevel(3), etc.

function! MarkdownLevel(maxlevel)
    if a:maxlevel >= 1 && getline(v:lnum) =~ '^# .*$'
        return ">1"
    if a:maxlevel >= 2 && getline(v:lnum) =~ '^## .*$'
        return ">2"
    if a:maxlevel >= 3 && getline(v:lnum) =~ '^### .*$'
        return ">3"
    if a:maxlevel >= 4 && getline(v:lnum) =~ '^#### .*$'
        return ">4"
    if a:maxlevel >= 5 && getline(v:lnum) =~ '^##### .*$'
        return ">5"
    if a:maxlevel >= 6 && getline(v:lnum) =~ '^###### .*$'
        return ">6"
    return "=" 

au BufEnter *.md  setlocal foldexpr=MarkdownLevel(2)  
au BufEnter *.md  setlocal foldmethod=expr     
au BufEnter *.md  setlocal autoindent

Then the following Vim commands in normal model make folding, navigation, and getting a sense of structure really easy:

  • zx show current line and necessary headings; close other headings
  • zc close heading
  • zj and zk to move down and up headings

Showing backticks and single quotes properly in code

I often need to show code, and backticks and single quotes weren't showing properly. The following code in my LaTeX preamble drawn from this TeX.SE question solved the problem:

% enables straight single quote
\let \@sverbatim \@verbatim
\def \@verbatim {\@sverbatim \verbatimplus}
{\catcode`'=13 \gdef \verbatimplus{\catcode`'=13 \chardef '=13 }} 

% enables backticks in verbatim
\xdef\@verbatim{\unexpanded\expandafter{\@verbatim}\chardef\noexpand`=18 }