/ minted

# Syntax Highlighting in LaTeX with minted

This post serves as an introduction to minted, a pygments-based syntax highlighter for LaTeX. Adding pygments to LaTeX streamlines so many things. The post provides a few examples of things you can do with minted, details the installation process, and covers some basic security.

## Code

You can view the code related to this post under the post-01-overview tag.

## Overview

The easiest way to present code in LaTeX is to use the verbatim environment. It's quick, it preserves formatting, and it requires no set up. It's also very bland. Its ease of use comes at the cost of basically all the context clues well-formatted and styled code can provide.

The next step up (or rather many steps up) is the listings package. Out the box, it supports a broad range of languages. It's eminently configurable. You can define new languages yourself, add different keywords, and style to your heart's content. It's very good at being straightforward. Moving beyond its predefined scopes (or easily discoverable internet styles) is a challenge, though, because parsing and tokenizing code in LaTeX is just about as hard and ridiculous as it sounds.

minted has become a solid competitor. It uses the pygments project to parse and highlight. You've probably seen pygments in action already. It's a beast of an application that can do just about anything you want re: syntax highlighting. minted isn't quite as flexible, but it does have access to most of the pygments features. Recognizable styles, a massive library of lexers, and simple customization through Python make minted, by way of pygments, a veritable utility knife.

 sample.tex view source  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 \documentclass{article}% chktex-file 18\usepackage[ paperwidth=2.5in, paperheight=3in, total={2in,2.8in}]{geometry}\usepackage{listings}\usepackage{minted}\setlength{\parindent}{0pt}\begin{document}\begin{center}This is verbatim:\begin{verbatim}#!/bin/bashecho "Hello, world!"\end{verbatim}\hrule\vspace{6pt}This is vanilla {\ttfamily listings}:\begin{lstlisting}[language=Bash]#!/bin/bashecho "Hello, world!"\end{lstlisting}\hrule\vspace{6pt}This is vanilla {\ttfamily minted}:\begin{minted}{bash}#!/bin/bashecho "Hello, world!"\end{minted}\end{center}\end{document}

There's a bit more to the listings vs. minted debate. Essentially it boils down to where you want to customize. Personally, I feel like a general-purpose scripting language used in all areas of tech is a stronger contender than a typesetting system many of my peers have struggled to learn. I don't know, though (and if I'm wrong, I'd love to hear about it). At its core, TeX tokenizes everything. I'm just not sure that it can achieve the same level of regex wizardry that goes into some of the pygments code.

## Installing

minted requires a few things to get up and running.

### Python

You'll need Python to get started. Pygments needs >=2.6 or >=3.3, depending on your version of Python. You can lazily install both with any trouble. For example, via dnf,

 $sudo dnf install python{2,3} ### pip Next you'll need pip, a wonderful package manager for Python. It's ridiculously easy to install. Rather than install it globally (i.e. to /usr/bin), we're going to install it locally via the --user flag.  $ wget https://bootstrap.pypa.io/get-pip.py; python get-pip.py --user; rm get-pip.pyThis should be sufficient$wget https://bootstrap.pypa.io/get-pip.py; python2 get-pip.py --user; rm get-pip.pyThis will install for Python 2 explicitly$ wget https://bootstrap.pypa.io/get-pip.py; python3 get-pip.py --user; rm get-pip.pyThis will install for Python 3 explicitly

However, this doesn't put pip on our path.

 $which pip/usr/bin/which: no pip in () The --user flag installed pip to our user site packages. We can check the base directory, which should have the desired bin, via  $ python -m site --user-base~/.local

Since we have an easy way to discover the directory, we have an easy way to add it to our .whateverrc:

### TeX Dependencies

minted provides a list of its dependencies. If you've got access to something like tlmgr, it should be pretty easy to update them.

 keyval kvoptions fancyvrb fvextra upquote float ifthen calc ifplatform pdftexcmds etoolbox xstring xcolor lineno framed shellesc

If you don't (e.g. modern RHEL derivatives, I think), you'll have to get creative. This is the easiest route:

 $sudo dnf install 'texlive-*'...Install >5779 PackagesTotal download size: >2.4 GInstalled size: >3.8 GIs this ok [y/N]: If, like me, you're running an SSD on a budget, the easiest isn't very convenient. Maybe you just don't feel like warehousing all of TeX Live to snag 16 dependencies. If you're not going to install everything, you need to figure out what you have to install. dnf/yum makes this somewhat trivial. If you're stuck with dpkg/dpkg-query, the discovery will be much more involved (but also I think you can run tlmgr so there's that).  install-texlive-dependencies view source  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #!/bin/bash# Pulled from https://github.com/gpoore/minted/blob/master/source/minted.pdfDEPENDENCIES=( keyval kvoptions fancyvrb fvextra upquote float ifthen calc ifplatform pdftexcmds etoolbox xstring xcolor lineno framed shellesc)PACKAGES=()# Loop over all the dependenciesfor dependency in "${DEPENDENCIES[@]}"; do # Check dnf for the parent package and trim its output PACKAGES+=($( dnf provides "tex($dependency.sty)" \ | awk -F':' '/^texlive/{ gsub("-[0-9]+$", "",$1); print $1 }' ))done# Remove duplicatesPACKAGES=($(echo "${PACKAGES[@]}" | tr ' ' '\n' | sort -u))# Install dependenciessudo dnf install "${PACKAGES[@]}"

### minted

Convoluted dependency resolution aside, minted itself is a breeze to install (like pygments; we've already done all the hard work).

 $sudo dnf install texlive-minted ## -shell-escape Because minted relies on an external application (pygments) to highlight, it can't just run in a tiny, neatly contained environment. TeX essentially exposes streams but, by default, access to the operating system is locked down. -shell-escape neatly sidesteps those restrictions, but it doesn't come without risk. Just like anything else, it's probably not a great idea to provide shell access until you understand what's going on. Don't download random things off the internet and execute them blindly. Don't run in superuser mode all the time. You know, basic stuff. This is what happens when you try to run minted without -shell-escape. Notice at the beginning that external actions are limited (restricted \write18 enabled). The document will not compile (even without -halt-on-error).  $ pdflatex -interaction=nonstopmode -halt-on-error sample.texThis is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016) (preloaded format=pdflatex) restricted \write18 enabled.entering extended mode(./sample.texLaTeX2e <2016/03/31>...Package ifplatform Warning: shell escape is disabled, so I can only detect \ifwindows....! Package minted Error: You must invoke LaTeX with the -shell-escape flag.See the minted package documentation for explanation.Type H for immediate help. ...l.9! ==> Fatal error occurred, no output PDF file produced!Transcript written on sample.log.

With -shell-escape, any external action is available (\write18 enabled) and the document compiles.

 $pdflatex -interaction=nonstopmode -halt-on-error -shell-escape sample.texThis is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016) (preloaded format=pdflatex) \write18 enabled.entering extended mode(./sample.texLaTeX2e <2016/03/31>...Output written on sample.pdf (1 page, 48380 bytes).Transcript written on sample.log. Chances are you're not actually building from the CLI every time. You've probably got an editor with some build commands stored. Don't add -shell-escape to all of your build profiles. It's a pain to toggle custom builds off and on, but having to rebuild your system after an attack is worse. Look for something like User Builds, Custom Commands, or the like. For example, in TeXstudio, you can add custom builds via Configure TeXstudio > Builds > User Commands. In Texmaker, the same menu is available via User > User Commands > Edit User Commands. Similarly, in Sublime via the LaTeXTools package, you can add custom builds to your project file (or anywhere else, for that matter).  posts-latex-minted.sublime-project view source  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 { "folders": [ { "path": "." } ], "build_systems": [ { "name": "Escalated pdflatex", "target": "make_pdf", "selector": "text.tex.latex", "builder": "script", "script_commands": [ [ "pdflatex", "-synctex=1", "-interaction=nonstopmode", "-shell-escape", "$file_base_name" ] ] } ]}

## Useful features

You've already seen how simple it is to add code to a tex file. minted also makes it easy to include external source code without worrying about getting it to play well with your editor. The \inputminted macro lets you load any file while specifying the lexer.

 input.tex view source  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \documentclass{article}\usepackage[ paperwidth=6in, paperheight=4in, total={5.5in,3.9in}]{geometry}\usepackage{minted}\setlength{\parindent}{0pt}\begin{document}\begin{center}\inputminted{bash}{../convert-pdf-to-png}\end{center}\end{document}

The default style is one of many available to minted. You can check the styles available on your system via

 $pygmentize -L stylesPygments version 2.2.0, (c) 2006-2017 by Georg Brandl.Styles:~~~~~~~* default: The default style (inspired by Emacs 22).* emacs: The default style (inspired by Emacs 22).* friendly: A modern style based on the VIM pyte theme.* colorful: A colorful style, inspired by CodeRay.* autumn: A colorful style, inspired by the terminal highlighting style.* murphy: Murphy's style from CodeRay.* manni: A colorful style, inspired by the terminal highlighting style.* monokai: This style mimics the Monokai color scheme.* perldoc: Style similar to the style used in the perldoc code blocks.* pastie: Style similar to the pastie default style.* borland: Style similar to the style used in the borland IDEs.* trac: Port of the default trac highlighter design.* native: Pygments version of the "native" vim theme.* fruity: Pygments version of the "native" vim theme.* bw:* vim: Styles somewhat like vim 7.0* vs:* tango: The Crunchy default Style inspired from the color palette from the Tango Icon Theme Guidelines.* rrt: Minimalistic "rrt" theme, based on Zap and Emacs defaults.* xcode: Style similar to the Xcode default colouring theme.* igor: Pygments version of the official colors for Igor Pro procedures.* paraiso-light:* paraiso-dark:* lovelace: The style used in Lovelace interactive learning environment. Tries to avoid the "angry fruit salad" effect with desaturated and dim colours.* algol:* algol_nu:* arduino: The Arduino® language style. This style is designed to highlight the Arduino source code, so exepect the best results with it.* rainbow_dash: A bright and colorful syntax highlighting theme.* abap: You can preview any of the styles by visiting the pygments demo and trying out a highlighter. Once pygments has parsed the code, you'll be able to change the style at whim. The default styles alone add a tremendous amount of utility to minted. There are many other settings that may be tweaked. Sharing style changes is an easy way to underscore minted's versatility.  style.tex view source  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 \documentclass{article}% chktex-file 18\usepackage[ paperwidth=2.5in, paperheight=3in, total={2in,2.8in}]{geometry}\usepackage{minted}\usepackage{xcolor}\setlength{\parindent}{0pt}\definecolor{monokaibg}{HTML}{272822}\definecolor{friendlybg}{HTML}{f0f0f0}\begin{document}\begin{center}This is the {\ttfamily monokai} style.\begin{minted}[ style=monokai, bgcolor=monokaibg]{bash}#!/bin/bashecho "Hello, world!"\end{minted}\hrule\vspace{6pt}This is the {\ttfamily colorful} style.\begin{minted}[ style=colorful,]{bash}#!/bin/bashecho "Hello, world!"\end{minted}\hrule\vspace{6pt}This is the {\ttfamily friendly} style.\begin{minted}[ style=friendly, bgcolor=friendlybg]{bash}#!/bin/bashecho "Hello, world!"\end{minted}\end{center}\end{document} If you want to use the same style throughout your document, minted makes that simple too. The \newminted macro defines a configuration for a specific language, e.g. python. It can then be used as an environment in place of minted by appending code to the end, e.g. pythoncode.  newminted.tex view source  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 \documentclass{article}% chktex-file 16% chktex-file 18% chktex-file 36\usepackage[ paperwidth=2.5in, paperheight=3in, total={2in,2.8in}]{geometry}\usepackage{minted}\usepackage{xcolor}\setlength{\parindent}{0pt}\setlength{\parskip}{0pt}\definecolor{monokaibg}{HTML}{272822}\definecolor{monokaifg}{rgb}{0.97,0.97,0.95}\newminted{bash}{ style=monokai, bgcolor=monokaibg}\BeforeBeginEnvironment{bashcode}{\color{monokaifg}}\AfterEndEnvironment{bashcode}{\color{black}}\begin{document}\begin{center}\begin{bashcode}#!/bin/bashecho "Hello, world!"\end{bashcode}\hrule\begin{minted}{bash}#!/bin/bashecho "Hello, world!"\end{minted}\hrule\begin{bashcode}#!/bin/bashFOO=($(find . -type f))# Nothing's perfectecho "\${FOO[@]}"\end{bashcode}\end{center}\end{document}

You can use the same logic with \inputminted via \newmintedfile. Rather than defining a new environment, \newmintedfile creates a new macro. It has an optional name parameter to make things easier (otherwise the macro is called \<language>file).

 newmintedfile.tex view source  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 \documentclass{article}\usepackage[ paperwidth=6in, paperheight=4in, total={5.5in,3.9in}]{geometry}\usepackage{minted}\usepackage{xcolor}\setlength{\parindent}{0pt}\definecolor{mannibg}{HTML}{f0f3f3}\newmintedfile[bashcode]{bash}{ style=manni, bgcolor=mannibg}\begin{document}\begin{center}\bashcode{../convert-pdf-to-png}\end{center}\end{document}

## What's Next

Sometime very soon I hope to look explore minted in combination with some other tools to build on its features. I've got some examples in use right now but I need to break them out and annotate them.

#### CJ Harries

I did a thing once. Change "blog." to "cj@" and you've got my email. All these opinions are mine and might not be shared by clients or employers.