LuaTeX / LuaJITTeX

LuaTeX is a TeX engine that extends pdfTeX and embeds the Lua scripting language. You can call Lua programs mid-typesetting and reach right into the material TeX has built — and it is this openness that makes it widely seen as the future of TeX. You invoke it as lualatex, and it handles Unicode and OpenType fonts natively.

What LuaTeX is

LuaTeX was developed by Taco Hoekwater, Hartmut Henkel, Hans Hagen and others. It grew out of the ConTeXt and Oriental TeX world, with the goal of an “open and configurable” TeX, built on pdfTeX while preserving downward compatibility. Because pdfTeX is its base, it outputs PDF directly and inherits the e-TeX extensions and most of pdfTeX’s typesetting machinery.

Much of the pdfTeX heritage is now reached through three interfacing primitives\pdfextension, \pdfvariable, and \pdffeedback — which take keywords and arguments so features can be extended without adapting the core engine. In day-to-day use LaTeX packages smooth over this difference, so you rarely write these primitives by hand.

The other pillar is an embedded Lua 5.3 interpreter. Write \directlua{...} inside your .tex file and the Lua code within runs on the spot. Input is UTF-8 natively. For fonts you select system or OpenType faces directly with fontspec, just as in XeTeX — but the loading is done by LuaTeX’s own Lua-based loader (luaotfload).

Embedding Lua in a document

\directlua{...} runs Lua code immediately. From Lua you call tex.print(...) and its output is fed back into TeX’s input stream and typeset as usual. Here is a minimal document you can compile with lualatex: it has Lua compute two to the tenth power and drop the result into the text.

document.tex
\documentclass{article}
\begin{document}
Two to the tenth power is
\directlua{tex.print(2^10)}.
\end{document}

Compiling this sets “Two to the tenth power is 1024.” A sibling command, \latelua{...}, instead runs when the page it sits on is shipped out. That suits work which must wait until page numbers and final coordinates are fixed — drawing onto the PDF or attaching annotations, for instance.

Because raw \directlua is finicky about braces and special characters, in practice the luacode package and its luacode environment let you write longer Lua code verbatim and safely.

Callbacks — hooking into the typesetting

LuaTeX’s real power is its callbacks. TeX builds your text out of nodes — characters, boxes, and glue (stretchable space) strung into linked lists — and by registering a callback you have your own Lua function invoked at each such juncture, free to inspect and rewrite that node list. In effect you reach safely into the engine’s internals.

Commonly used callbacks include the following. process_input_buffer fires each time TeX reads an input line, receiving a string and returning one. pre_linebreak_filter hands you the node list just before a paragraph is broken into lines, and post_linebreak_filter the list just after. ligaturing and kerning correspond to the ligature- and kerning-building stages.

CallbackWhen it fires
process_input_bufferAs each input line is read; for preprocessing
pre_linebreak_filterThe node list just before a paragraph is broken
post_linebreak_filterThe node list right after line breaking
ligaturing / kerningThe ligature- and kerning-building stages

You drive these operations through a set of tables visible from Lua. tex is the window onto TeX’s internal state (registers and dimensions), node creates, walks, and frees nodes, token deals with tokens (TeX’s smallest units of meaning), font with font data, and status with runtime information. Even advanced font machinery like luaotfload is written in Lua on top of these.

Fonts — selecting them with fontspec

As in XeTeX, loading the fontspec package in LuaTeX lets you name OpenType / TrueType fonts installed on your system directly. \setmainfont chooses the body font, with \setsansfont and \setmonofont for the sans-serif and monospaced faces.

document.tex
\documentclass{article}
\usepackage{fontspec}
\setmainfont{TeX Gyre Termes}
\begin{document}
This text is set in an OpenType font, with ligatures like ffi.
\end{document}

Behind the scenes luaotfload does the loading. It is an adaptation of ConTeXt’s font loader for Plain TeX and LaTeX, exposing OpenType features such as ligatures, oldstyle figures, and small capitals; it aims for compatibility with XeTeX and is maintained by the LaTeX team’s latex3 group.

MetaPost built in

LuaTeX has MPlib built in — the MetaPost drawing engine packaged as a library — so it can generate MetaPost figures in the very same process as the compile, without calling an external program. From LaTeX the luamplib package exposes this, letting you write MetaPost code directly inside an mplibcode environment.

Japanese — LuaTeX-ja

Japanese typesetting is handled by LuaTeX-ja (package luatexja). It reimplements, on the Lua side via callbacks, the Japanese-typesetting know-how that pTeX had — vertical writing, the inter-character spacing and punctuation handling driven by JFM (Japanese Font Metrics), and the spacing between Japanese and Western text. This opens a modern route to Japanese LaTeX distinct from pLaTeX/upLaTeX.

With luatexja-fontspec you can select Japanese fonts in fontspec’s style too. LuaTeX-ja requires LuaTeX 1.10.0 or later and a reasonably recent luaotfload. If upLaTeX on the pdfLaTeX side is the “mature standard,” then LuaLaTeX with LuaTeX-ja is the strong choice when starting fresh today.

LuaJITTeX and LuaMetaTeX

LuaJITTeX is a variant that links LuaJIT — a just-in-time compiler that turns code into machine code at runtime — instead of stock Lua. Lua runs faster, but LuaJIT remains pinned to the Lua 5.1 language level (mainline LuaTeX is at 5.3) and is less actively maintained. Outside special cases where Lua execution is extremely heavy, most users are well served by ordinary LuaTeX.

The other successor is LuaMetaTeX, a leaner reworking of LuaTeX — “lean and mean” — that underpins modern ConTeXt (LMTX / MkXL). It brings new math typesetting and many new primitives, adopts the Lua 5.4 line, and has shipped in TeX Live since 2023. The division of labor: LuaTeX for LaTeX work, LuaMetaTeX for the latest ConTeXt.

Trade-offs

XeTeX and LuaTeX both handle Unicode and OpenType, but they differ in character. Where XeTeX leans on the operating system’s text-layout machinery for convenience, LuaTeX is more flexible precisely because everything is controllable from Lua. The cost is that it has historically been somewhat slower than XeTeX (the gap has narrowed in recent years).

  • Unicode / OpenType first. UTF-8 input and fontspec are the norm.
  • Programmable. With Lua and callbacks you can step inside the typesetting itself.
  • Self-contained. MetaPost (MPlib) is built in, so figures need no external call.
  • Japanese-capable. LuaTeX-ja gives full Japanese typesetting, vertical writing and JFM included.
  • Forward-looking. The LaTeX team targets LuaTeX for new development.

On the whole, LuaLaTeX is becoming the default for new Unicode / OpenType workflows where programmability matters. The older division still holds: XeLaTeX if you simply want easy fonts, pdfLaTeX for quick mostly-English work. Which engine to pick is laid out on the “Choosing an engine” page.