Home | Notes
LaTeX/Beamer Code Review

I recently needed to put together a set of slides to review some code I wrote for work. A slide deck is not how I would normally or preferrably present my code, but the request was for slides so that's what I set out to make. For me, a presentation is always an opportunity for deeper exploration of LaTeX and Beamer, so these code review slides presented an interesting opportunity.

Going into this project, I had a few goals:

  1. Include my program source code directly into my slides.

These code review slides are supposed to cover hundreds of lines of code, so I don't want to be manually copying all that code in my slides. Instead, it'd be great if I could use LaTeX to automatically pull in, say, lines 121-160 from src/file.c into a particular slide.

  1. Have my slides accurately reflect the git branch and latest commit hash of the code I'm discussing

If I'm including code directly in from source files, I want to make sure I'm including lines from the correct version of the files I'm presenting. It would be great if, as part of the build process for the slides, I could automatically pull in the current git branch and latest commit hash and display that clearly in the slides for later reference and present confirmation that I'm reading the right files.

I found a great and broadly applicable solution goal #2, but I'm going to put my code for tracking git version in a different note. Hopefully I'll remember to come back and link to it here!

Including Source Code

Fortunately there exists an easy way to include source code - or any text in an external file - in a LaTeX document - the listings package! I found this package via an old post on texblog.org. It is very easy to get startd with - just place a

\usepackage{listings}
\usepackage{listings}

at the top of your LaTeX file, and include lines from other files with:

\lstinputlisting{path/to/file.txt}
\lstinputlisting{path/to/file.txt}

This is pretty handy but I just want to include excerpts, not entire files.

Including File Excerpts

A StackExchange answer from user egreg showed me a way to include just a few lines from a file:

\lstinputlisting[firstline=300,lastline=500]{file.cc}
\lstinputlisting[firstline=300,lastline=500]{file.cc}

The listings package also supports a linerange method of including multiple chunks of a file in a single excerpt, as shown in this StackExchange answer:

\lstinputlisting[linerange={1-4,7-9}]{file.cc}
\lstinputlisting[linerange={1-4,7-9}]{file.cc}

For now, I'm going to stick with the firstline,lastline method because it works better with line numbering. I can definitely see myself using the linerange version in a situation where line numbers aren't as important though.

Correct Line Numbers

Giving just the firstline and lastline arguments to \lstinputlisting gave a code listing where the line numbers did not match the source file. For example, the command

\lstinputlisting[firstline=61,lastline=69]{../Terrain2STL/src/STLWriter.c}
\lstinputlisting[firstline=61,lastline=69]{../Terrain2STL/src/STLWriter.c}

gave me an output of

Screenshot from 2021-02-24 21-40-06.png

even though that void startSTLfile... line is actually line 61 in the source file. Passing the additional firstnumber argument to \lstinputlisting as described in this post let me choose the correct starting line number. An updated command

\lstinputlisting[firstline=61,lastline=69,firstnumber=61]{../Terrain2STL/src/STLWriter.c}
\lstinputlisting[firstline=61,lastline=69,firstnumber=61]{../Terrain2STL/src/STLWriter.c}

gives

Screenshot from 2021-02-24 21-40-18.png

Splitting Long Excerpts

The final issue I encounted was that really long code excerpts would run off the end of the page and not be visible to the reader. This turned out be an easy fix, at least for slides in beamer. The solution proposed by this StackExchange post is to simply change the \begin{frame} line at the start of a long slide to \begin{frame}[allowframebreaks]. With this modification, a slide with a long code excerpt (or any long text for that matter) will auto-expend in subsequent slides with the same title. Very convenient!

Final Macro

I eventually settled on the following macro for all my code excerpting needs:[1]

\newcommand{\excerpt}[3] {
  \small{\texttt{\detokenize{#1}}:}
  \lstinputlisting[firstline=#2, lastline=#3, firstnumber=#2]{#1}}
\newcommand{\excerpt}[3] {
  \small{\texttt{\detokenize{#1}}:}
  \lstinputlisting[firstline=#2, lastline=#3, firstnumber=#2]{#1}}

It can then used as:

\excerpt{../Terrain2STL/src/STLWriter.c}{61}{69}
\excerpt{../Terrain2STL/src/STLWriter.c}{61}{69}

Where the arguments are 1) path to excerpt source file, 2) first source line to include in excerpt, 3) last source line to include in excerpt.

That command producesa code listing in a LaTeX document that looks like this:

Screenshot from 2021-02-24 21-32-12.png

The following snippet should also be included before the \begin{document} line to setup the listings package correctly:

\usepackage{listings}

% lstset adapted from https://tex.stackexchange.com/questions/147512/latex-a-single-code-listing-over-multiple-pages
\lstset{ %
basicstyle=\tiny\ttfamily,       % the size of the fonts that are used for the code
numbers=left,           % where to put the line-numbers
numberstyle=\tiny,  % the size of the fonts that are used for the line-numbers
stepnumber=1,           % the step between two line-numbers. If it is 1 each line will be numbered
numbersep=5pt,          % how far the line-numbers are from the code
backgroundcolor=\color{white},  % choose the background color. You must add \usepackage{color}
showspaces=false,           % show spaces adding particular underscores
showstringspaces=false,     % underline spaces within strings
showtabs=false,         % show tabs within strings adding particular underscores
frame=single,           % adds a frame around the code
tabsize=2,              % sets default tabsize to 2 spaces
captionpos=b,           % sets the caption-position to bottom
breaklines=true,            % sets automatic line breaking
breakatwhitespace=false,        % sets if automatic breaks should only happen at whitespace
escapeinside={\%*}{*)},      % if you want to add a comment within your code
float=H
}
\usepackage{listings}

% lstset adapted from https://tex.stackexchange.com/questions/147512/latex-a-single-code-listing-over-multiple-pages
\lstset{ %
basicstyle=\tiny\ttfamily,       % the size of the fonts that are used for the code
numbers=left,           % where to put the line-numbers
numberstyle=\tiny,  % the size of the fonts that are used for the line-numbers
stepnumber=1,           % the step between two line-numbers. If it is 1 each line will be numbered
numbersep=5pt,          % how far the line-numbers are from the code
backgroundcolor=\color{white},  % choose the background color. You must add \usepackage{color}
showspaces=false,           % show spaces adding particular underscores
showstringspaces=false,     % underline spaces within strings
showtabs=false,         % show tabs within strings adding particular underscores
frame=single,           % adds a frame around the code
tabsize=2,              % sets default tabsize to 2 spaces
captionpos=b,           % sets the caption-position to bottom
breaklines=true,            % sets automatic line breaking
breakatwhitespace=false,        % sets if automatic breaks should only happen at whitespace
escapeinside={\%*}{*)},      % if you want to add a comment within your code
float=H
}

Final Results

To see all these variations of code excerpting, check out a set of demo slides and the LaTeX source file below. I'd recommend downloading both to see the different commands, including my final \excerpt macro, render code snippets!

pres1.tex

pres1.pdf


  1. The \detokenize{} macro is there to make sure TeX doesn't try to process the source file name - I ran into issues where special characters like underscores would mess up the display of the source file name. detokenize fixed that ↩︎