Recently I spent much longer than expected generating data about library holdings for an insurance spreadsheet needed by CURIE. We don’t have to do it often, and this was the first time I’d had to figure out the numbers they want about total books on the shelf (by LCC class letter) and years of print journal holdings (by subject groupings based on LCC). Cleaning the messy bibliographic metadata—all bibliographic metadata is messy—took a number of steps, and naturally I did it with R in Org, documenting everything in a reproducible way so that next time it will just take me an afternoon, not days and days.
Interesting fact: the Scott Library has about 250,000 years of print journals on the shelves.
So that others can see what data cleaning and munging was done, I exported the Org file to LaTeX and then turned it into a PDF. I included the R source code and wanted to make that look nice, not just plain verbatim text. This got me looking at the LaTeX package minted for the first time. Here I document how I now have things set up.
In my Emacs config I set up a function to turn minted
on or off. Originally I added minted
to the default list of packages in every LaTeX export and defined that every source code listing should be formatted with minted
, like so:
(add-to-list 'org-latex-packages-alist '("" "minted" nil))
(setq org-latex-src-block-backend 'minted)
About the first line, a lot of documentation says the variable to set is org-latex-listings
but as of Org 9.6 that is obsolete. As to the second, with that back end variable set, every block will be inside \begin{minted}
and \end{minted}
instead of \begin{verbatim}
and \end{verbatim}
.
But when minted
is one of the included packages it’s always necessary to run pdflatex -shell-escape
to compile the PDF, even if there are no source blocks. I can’t be having that.
Instead, I use this function (based on a tip from Xah Lee) to toggle those settings on or off. When I’m working on a file that I want to export using minted
, I run M-x wtd/org-toggle-minted
to turn things on. When I’m done, I run it again to turn things off.
(defun wtd/org-toggle-minted ()
"Toggle whether or not Org should use minted for LaTeX."
(interactive)
(if (get 'wtd-org-minted-on-or-off 'state)
(progn
(setq org-latex-packages-alist (delete '("" "minted" nil) org-latex-packages-alist))
(setq org-latex-src-block-backend 'verbatim)
(put 'wtd-org-minted-on-or-off 'state nil)
(message "Minted is off")
)
(progn
(add-to-list 'org-latex-packages-alist '("" "minted" nil))
(setq org-latex-src-block-backend 'minted)
(put 'wtd-org-minted-on-or-off 'state t)
(message "Minted is on; use pdflatex -shell-escape -interaction=nonstopmode")
)
)
)
(My arrangement of parentheses probably offends many people, but I don’t do much Lisp and I find it helpful here.)
Now, minted
has all sorts of options. They can be set in an association list that will be passed to every source block, like so.
(setq org-latex-minted-options
'(("frame" "leftline")
))
However, this seems inelegant to me. It puts the same text on every code block, over and over, and I would rather specify the options once in LaTeX. Also, I don’t think I’ll want the same look on everything I do; I want to be able to control document-specific options right in the Org file. Therefore I prefer to define options with \setminted{}
in a latex_header
at the top of the Org file.
Here’s an example. The file starts with minted
settings (I don’t need usepackage
because it’s already done, thanks to the above). This says that I want to use one of the Solarized colour schemes (see the listing of Pygments styles) and put a line on the left of every block. For R code, I want line numbers.
#+latex_header: \setminted{style=solarized-light,frame=leftline}
#+latex_header: \setminted[r]{linenos=true}
Here’s an R block. I throw in an option for this block specifically, to change the frame setting so there’s a line around the whole block.
#+attr_latex: :options frame=single
#+begin_src R
library(purrr)
fruits <- c("apple", "pear", "grape", "blueberry")
map(fruits, \(f) nchar(f))
#+end_src
(I know that nchar(fruits)
is the proper way, but I was using purrr seriously for the first time in the CURIE work and thought what the hell.)
In my Emacs (where I use the dark Solarized theme), this looks like so:
When turned into a PDF, I get:
That looks good!
It’s in a box because I overrode the frame
setting, it has line numbers because I set that for R, and it uses the Solarized light theme because that is the document setting.
Next, here’s a Ruby block.
#+attr_latex: :options style=default,fontsize=\footnotesize
#+begin_src ruby
fruits = %w[apple pear grape blueberry]
fruits.each do |f|
puts f.length
end
#+end_src
In my Emacs:
In the PDF:
That also looks good!
It has the left line by the document setting, but the style is overridden in just this block to be the Pygments default
, and for fun the font size is a bit smaller.
To make all this work I need Pygments installed, because that’s how minted
does the formatting. That’s a simple external requirement (well, as simple as Python packages are; I use them so rarely I always get confused by whether I should use pip
or pip3
and if it needs to be run as root, but the error messages are helpful and I get it right soon enough). But because it’s external, pdflatex
needs to be run specially to allow an outside call:
pdflatex -shell-escape filename.tex
Or better yet this, to plough through problems:
pdflatex -shell-escape -interaction=nonstopmode filename.tex
I could configure Org to handle that but I’d rather do it by hand when needed and I know it’s safe.
Lastly, to show off the LaTeX fragment previews in Org, here’s some math almost plain (some of the raw LaTeX is prettified in the buffer) and then previewed. This is Org showing me in Emacs what the PDF output will look like.
I’m happy to have found one more way for Org and LaTeX to work together to make more beautiful documents.
UPDATE (22 November 2023): I rewrote this to use the toggle function instead of accidentally leaving the minted
settings permanently on.