Let’s Learn LaTex: Part 7

Let’s talk about embedding code snippets in your LaTex documents. All of us here are programmers (except for those who aren’t) so this is a natural thing we might want to do. Despite being built by programmers for programmers, LaTex doesn’t really have a code mode. Knuth spent around a lot of time on making sure that Tex is the best tool around for typesetting math equations, which was probably a good choice. After all, math is the universal language of science and formulas are the “meat” of any serious research paper. This goes double for Computer Science papers which should be liberally sprinkled with it. Snippets of code are “implementation details” and thus of little importance in the grand scheme of things.

Still, embedding code in documents is something we may want to do. The traditional method is using the verbatim environment which respect white space and creates a nice, preformated, mono-spaced code blocks. For example, lets take the following snippet:

\noindent Here is a code snippet in Python:

\begin{verbatim}
# Hello world
def Hello():
    foo = 10
    print "Hello World!"
\end{verbatim}

Upon compiling, it will look like this:

Verbatim Environment

Verbatim Environment

While this is not terribly impressive, it is good enough for most research papers. That said, if you are using LaTex for writing manuals, homeworks or school papers you might want your code blocks to be a little bit more flashy. Perhaps they could include line numbers, and some color. How do you do that?

With a package of course. There are a number of different packages that offer this kind of functionality, but my favorite is probably the one named lstlistings. It is not the most powerful or flexible one, but it does not have any dependencies (except maybe the color package), does not rely on external tools and it is easy to use.

You include it in your preamble like this:

\usepackage{listings}
\usepackage{color}

Then you put your code snippet inside the lstlisting environment instead of verbatim:

\noindent Here is a code snippet in Python:

\begin{lstlisting}
# Hello world
def Hello():
    foo = 10
	print "Hello World!"
\end{lstlisting}

The result is rather unimpressive:

Listings Package

Listings package without any configuration.

Yes, it does actually look worse than the verbatim environment, but that’s only because we have never configured it. You see, the lstlistings package is old school, and like many LaTex packages it adheres to the fuck reasonable defaults philosophy. The idea behind this attitude is simple: the user should know what they are doing, or else go die in a fire. Yes, I know – it’s charming. But what are you gonna do? Go back to using Microsoft Word? I didn’t think so.

Configuring our code environment is actually not a major pain in the ass. You basically need to include a short lstset block somewhere in the preamble. It can be as brief or as detailed as you want. I typically go with something like this:

\lstset{ %
	language=python,
	numbers=left,
	frame=single,
	showstringspaces=true,
        basicstyle=\ttfamily,
       	keywordstyle=\color{blue}\ttfamily\textbf,
	identifierstyle=\color{magenta}\ttfamily,
	stringstyle=\color{red}\ttfamily,
	commentstyle=\color{cyan}\ttfamily\textit
}

The above will set the default language for all the code blocks in the document to be python (don’t worry, this can be overriden), toggles on line numbers, puts a border (frame) around the code and sets up some basic font and color formatting. You should remember commands like \textbf from Part 2. The color related commands are provided by the color package.

The resulting code block will look like this:

Listings Package

Listings package with config.

The lstlistings package makes up for having no useful defaults by being very configurable. You can control just about any aspect of the way your code is displayed. You not only have control over fonts and colors, but you can mess around with the line numbers, visual indicators for whitespace characters, and change which words are treated as keywords. Here is a nearly complete list of config options you may find useful:

\lstset{ %
  language=python,                 % the language of the code
  basicstyle=\ttfamily,        	   % style for all of the code
  keywordstyle=\color{blue},       % keyword style
  identifierstyle=\color{magenta}, % style for variables and identifiers
  commentstyle=\color{green},      % comment style
  stringstyle=\color{mymauve},     % style for string literals

  tabsize=2,                       % sets default tabsize (in spaces)
  backgroundcolor=\color{white},   % requires the color package
  frame=single,                    % put a border around the code

  numbers=left,                    % line numbers (none, left, right)
  numberstyle=\tiny\color{red},    % the style that is used for line numbers
  numbersep=5pt,                   % how far the line-numbers are from the code 
  
  showspaces=false,                % visibly indicate spaces everywhere
  showstringspaces=false,          % visibly indicate spaces within strings only
  showtabs=false,                  % visibly indicate tabs within strings
  
  breaklines=true,                 % toggle automated line wrapping
  breakatwhitespace=false,         % if wrapping is on, enable to break on whitespace only

  deletekeywords={...},            % exclude keywords from chosen language
  morekeywords={*,...},            % add words to be treated as keywords
      
  captionpos=b                     % sets the caption-position (bottom)
}

The package supports a good number of languages out of the box. All the popular ones are represented, alongside some rather obscure ones (like Motorola assembler). Here is a table of languages ripped straight out of the manual:

Supported Languages

Supported Languages. Dialects are listed in parentheses with defaults underlined. If there is no default, dialect must be specified.

Dialects are listed in parentheses, with the defaults being underlined. As you probably noticed, not all languages that have dialects include a default (because fuck defaults, remember?). For those languages you must specify one in the declaration. The method of doing it is rather awkward:

\lstset{
	language={[x86masm]Assembler}
}

It doesn’t look pretty, but it works.

I mentioned before that you can override the language setting. You can also skip it from the preamble declaration, but putting it there is usually a good idea. In most documents you will be posting snippets in the same language over and over again, so this saves you typing. If you want to use a different language, or you did not specify one in preamble, you will need to include it as an optional argument when you open the lstlisting environment like this:

\begin{lstlisting}[language=ruby]
	puts "Hello World!"
\end{lstlisting}

You can also override any of the other options this way. Just list them after the language declaration.

If you are super lazy, and can’t be bothered to copy and paste a code snippet into your paper, you can include it using the \lstinputlisting command. It has one mandatory argument which is the file name:

\lstinputlisting[language=python, firstline=7, lastline=18]{filename.py}

You can specify any regular \lstset settings as optiononal arguments. The firstline and lastline arguments can be used to import only a part of the file. If you skip them, the entire file will be embedded.

Let’s Learn LaTex
<< Prev Next >>
This entry was posted in Uncategorized. Bookmark the permalink.



2 Responses to Let’s Learn LaTex: Part 7

  1. Another newer package to typeset code in LaTeX is minted, based on the Python library Pygments. I find it better-looking.

    Reply  |  Quote
  2. Luke Maciak UNITED STATES Google Chrome Terminalist says:

    Ah, it does seem nicer. My concern was that not everyone who uses LaTex might have Python installed. Like non-CS science folks for example. There is a good chance people using it to typeset Bio/Chem/Phys or pure Math papers might have Python on board, but I felt more comfortable with a pure Tex solution.

    Reply  |  Quote

Leave a Reply

Your email address will not be published. Required fields are marked *