Combining Lua and LaTeX

1. Introduction

This page introduces you to LuaLaTeX, a version of LaTeX with Lua built in. This is a replacement to the standard pdfLaTeX that you have probably already been using, and like pdfLaTeX will write pdf files directly, but has a built in Lua interpretor that allows you to combine programming with typesetting to do things that were difficult or impossible before.

I only introduce the basic ideas here and give some examples. As always, if you want detailed and precise control you will need to read the documentation. Any recent version of LuaLaTeX will work. This is available in all the standard LaTeX installations, including MikTeX for MS-Windows.

2. Getting started

To make these examples work all you need to do is to replace "pdfLaTeX" with "LuaLaTeX" in your work chain. Indeed, LuaLaTeX is expected to be the official replacement for pdfLaTeX shortly, so this switch is recommended anyway, even if you don't plan to use Lua directly.

On a standard MikTeX installation under MS-Windows (e.g. on university computers) follow the following instructions.

1. Open TeXworks and make a new document

On university computers, press the MS-Windows start button and then type "TeXworks" (the case of the letters seems to be important) and click the application that comes up.

Note: if you want to install TeXworks on your own MS-Windows computer it is part of MikTeX which is available at https://miktex.org/

2. Ensure that TeXworks is set to process using LuaLaTeX.

Set this in the top left of the TeXworks window. In other systems (mac, linux...) the most important thing is that you are using "LuaLaTeX" or "lualatex" and not one of the other versions of LaTeX.

3. Enter a test document.

A suggestion is to use

\documentclass[a4paper]{article}

\usepackage{luacode}

\begin{document}

A random number:
\begin{luacode}
tex.sprint(math.random())
\end{luacode}

\end{document}

4. Save your document as usual and then process with Typeset -> Typeset. Your LaTeX document will be compiled and you should see the PDF output.

In this case the document involves calling Lua to make a random number between 0 and 1 (using the math.random() function) and then "printing" it to LaTeX (the tex.sprint(...) command). In other words the output of Lua will be incoporated in your document.

I don't know why, but I found that on university computers the first typesetting operation often hangs. I found that Typeset -> abort Typesetting and then restarting works. Strange...

3. Some gotchas!

There are some difficulties, not least that when it goes wrong the error messages you get can be very difficult or impossible to understand. For beginners, or even not-so beginners the main recommendation is to use packages and type stuff very carefully to look just like the ones here (which do work). Only change a few things as an expermiment or if you know for sure it will work, and keep testing your code regularly.

The general process is,

The problem is that each of these stages involve significant amounts of processing that can be a bit obscure.

For example LuaLaTeX also has a \directlua{...} command, for the first of these, but using \directlua can mangle the text badly. The \begin{luacode}...\end{luacode} avoids most of this mangling, and is recommended. For those that need it, the luacode package is documented at http://mirrors.ibiblio.org/CTAN/macros/luatex/latex/luacode/luacode.pdf

Unfortunately, the \begin{luacode}...\end{luacode} has some limitations. Chief of these is that it can't be used in commands and the \end{luacode} has to be on a line all by itself. When these limitations are too much, \luaexec may be used (with care).

Secondly, Lua itself requires its text in a particular form which might not be obvious. Note the double backslash in

\begin{luacode}
tex.sprint("$\\sin x$")
\end{luacode}

This is needed because the backslash is used in Lua to print special characters. So for example, print("He said, \"Hello!\"") is how you'd get Lua to print "He said, "Hello!"". You need to double up backslashes too in the same way, e.g. print("\\sin x") to get Lua to print "\sin x".

Finally, LaTeX must process the results from Lua. This is normally the easiest part to understand but LaTeX can behave oddly. This is why tex.sprint(...) is recommended over the alternative tex.print(...) that you will see mentioned elsewhere: the sprint version seems to have fewer traps and works in a way that is closer to what is expected.

If you really need it, lualatex itself is documented here https://mirror.hmc.edu/ctan/info/luatex/lualatex-doc/lualatex-doc.pdf but this is quite a difficult read... You will certainly find other documents on-line.

4. Three examples

This section has three examples that show you how you can use Lua to get LuaLaTeX to do things that would be difficult or impossible in LaTeX alone. In each case, make a new folder for the example, download the files into that folder and look at them carefully in TeXworks, notepad++ or your favourite editor, and then run LuaLaTeX on the ".tex" file.

A trig table

Latex has some facilities for handling numbers, but no good facility to handle floating point numbers. We can use Lua's "math" library to calculate values in our document. Here is LuaLaTeX being used to print a table of sine and cosine values. trigtable.tex. Download it and process it (it contains explanations of how it works). Then modify it and check you understand what is happening.

(Note the use of the "strut" command to make an invisible bar of a particular height to get vertical alignment right in the table, and the LaTeX command \verb and exvironment verbatim to print source code to the document.)

Using Lua to do calculations with crossreferences

LaTeX's method of handling cross references is one of its strengths: it takes the work away from author to enable the author to concentrate on what actually matters - the text - rather than the basic work of keeping track of theorem numbers etc. Occasionally this cross reference data can be used in different ways to calculate numbers in the text. This might be possible in ordinary LaTeX but these calculations are easy in Lua. The example on combinations.tex gives the idea. Load it and experiment with it, and see how simple modifications of the text can lead to different numbers calcuated in Lua. In other words, this is a case where information is passed from LaTeX to Lua prior to Lua doing its calculations.

(In this case, data is contained in LaTeX's "counters" and passed to Lua that way.)

Using Lua as a sophisticated macro processor

Another major strength of LaTeX is its mechanism to define and handle simple macros to reduce input and ensure consistency of style. Most macros are typically substitution of various pieces of text into a template or pattern. (It is possible to make a LaTeX macro do more than this but difficult.) When the requirements of the macro are partticularly complicated, you can use Lua to calculated the macro expansion that you need.

This example also shows how you can define your Lua code is a separate "main" file with a number of functions, loaded using Lua's dofile, and then simply call the functions when needed. (This approach is recommended: it completely avoids the worst layer on mangling that was talked about before, since Lua reads text directly from a file rather than via LaTeX.) Download the two files needed to the same directory and process the .tex file: luamacros.tex and myluamacros.lua .