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 | |
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} |
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.py |
However, this doesn’t put pip
on our path.
$ which pip |
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 |
Since we have an easy way to discover the directory, we have an easy way to add it to our .whateverrc
:
$ echo 'export PATH="$(python -m site --user-base)/bin:$PATH"' >> .whateverrc |
You can also manually add it, which might be a good idea if you’re doing other PATH
manipulations.
pygments
With pip
installed, we can quickly install pygments
.
$ pip install --user pygments |
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-*' |
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 | |
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 |
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.tex |
With -shell-escape
, any external action is available (\write18 enabled
) and the document compiles.
$ pdflatex -interaction=nonstopmode -halt-on-error -shell-escape sample.tex |
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 | |
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 | { |
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 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | \documentclass{article} |
The default style is one of many available to minted
. You can check the styles available on your system via
$ pygmentize -L styles |
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 | |
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} |
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 | |
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} |
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 | |
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} |
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.