retex-kpath 0.9.9

kpathsea-compatible file lookup for retex
Documentation
# retex

retex is a TeX engine written in Rust that can replace `lualatex`. It reads
the same LaTeX packages and fonts from an installed TeX Live tree and
produces the same PDF: on the documents we test, the pages are
pixel-identical to lualatex's at 300 dpi. It is faster, runs as many
passes as a document needs on its own, and reports errors in a form that
says what is wrong and how to fix it.

**Status:** release candidate for 1.0 (0.9.9). Large documents compile
correctly: articles and reports, Beamer presentations, TikZ and pgfplots,
amsmath and unicode-math, fontspec with OpenType and TrueType fonts,
microtype, hyperref, biblatex and BibTeX. Conformance with the test
suites of the LaTeX kernel, expl3 and pgf, counting the tests that
LuaTeX itself passes:

| suite | passes with retex | passes with LuaTeX |
|---|---|---|
| LaTeX kernel (latex2e) | 1016 of 1114 | 1108 |
| expl3 (latex3) | 255 of 257 | 255 |
| pgf/TikZ | 110 of 122 | 111 |

Most of the remaining LaTeX kernel differences are in latex-lab's tagged
PDF tests. retex targets TeX Live 2025 (LuaTeX 1.22); TeX Live 2026 is not
supported yet.

## Compared with lualatex

| | lualatex | retex |
|---|---|---|
| PDF output | the reference | pixel-identical pages; font subsets get other tags |
| `.log` file | LuaTeX's | the same |
| reruns for references, tables of contents, bibliographies | by hand, or with latexmk | automatic, with BibTeX or biber when needed |
| later passes | run the whole document again | resume after the preamble |
| terminal output | TeX's messages | errors and warnings with the source line, the cause and a fix; hints about common mistakes |
| auxiliary files | next to the document | in `.retex/<job>-<hash>/`; only the PDF is written next to the document |
| rebuild on change | external tools | `--watch` |
| SyncTeX | `-synctex=1` | the same, with the same records |
| command-line options | luatex's | the same set |

Measured on the same machine:

| document | lualatex | retex |
|---|---|---|
| 30-page project proposal (biblatex, TikZ, many packages), one pass | 19.7 s | 11.0 s |
| the same, full build from a clean directory | 67.9 s (lualatex, biber, lualatex ×2) | 44.4 s (`retex project.tex`) |
| one-page article ("Hello world"), one pass | 0.45 s | 0.08 s |

retex can also run under the name `luatex` or `lualatex`, or with
`--compat=lualatex`: it then behaves as LuaTeX for the tools that drive TeX
themselves (latexmk, l3build), with LuaTeX's terminal output and a single
pass.

## Building

```sh
cargo build --release
```

Requires Rust 1.93 or later and an installed TeX Live 2025 tree. retex reads
the LaTeX macro files and fonts from it, and the environment variables and
`texmf.cnf` settings that kpathsea and LuaTeX use (`TEXINPUTS`, `TEXFONTS`,
`openout_any`, `shell_escape`, …). It is tested on Linux.

## Usage

```sh
retex paper.tex
```

retex runs the passes the document needs and reports what went wrong, with
its location in the source:

```text
retex 0.9.9 · paper.tex
error: undefined command \textbff
  --> ./paper.tex:3:6
  |
3 | Some \textbff{bold} text.
  |      ^^^^^^^^
  │ help: did you mean \textbf or \textbar or \textsf?

warning: undefined reference `sec:result`
  --> ./paper.tex:4:27
  |
4 | See Section~\ref{sec:result}.
  |                           ^
  │ help: did you mean `sec:results`? (\label{sec:results} in ./paper.tex, line 3)

retex: wrote paper.pdf (1 page, 7 KB) in 0.21 s, 2 passes; 1 error, 1 warning (details in .retex/paper-1a2b3c4d/paper.log)
```

On a terminal, retex stops at an error as LuaTeX does, so that it can be
answered, and shows the pass and the pages done so far while it runs.
Without a terminal (in scripts and CI) it does not stop. After the
build it may print a few hints about the source, such as `$$ … $$`
display math or a `\label` placed before its `\caption`; `RETEX_HINTS=0`
turns them off.

Other options:

* `--no-aux-dir` keeps the auxiliary files next to the document, as do
  `-shell-escape`, `-output-directory` and `--compat=lualatex`.
* `retex -synctex=1 paper.tex` writes `paper.synctex.gz` next to the PDF
  for forward and inverse search in editors and viewers.
* `retex --watch paper.tex` stays running and rebuilds when a file the
  document uses changes, starting after the preamble.
* `retex --help` lists the options; every option of `luatex` is accepted.

## Clean-room provenance

retex is written from scratch and released under CC0. No code of another TeX
implementation (LuaTeX, pdfTeX, XeTeX, luaotfload, HarfBuzz, ...) has been
read, whatever its license. Behaviour is established from the output of
lualatex on our own test documents, from values returned by LuaTeX's
documented Lua API, and from published documentation and specifications. The
complete policy is in [CONTRIBUTING.md](CONTRIBUTING.md#provenance-and-licensing-clean-room-rule).

Three of Knuth's published programs and one change file are used as
references for the algorithms retex shares with them:

| file | what it is | used for |
|---|---|---|
| `tex.web` | *TeX: The Program*, D. E. Knuth | TeX82 semantics |
| `etex.ch` | the e-TeX change file to `tex.web`, P. Breitenlohner and the NTS team | e-TeX extensions |
| `mf.web` | *METAFONT: The Program*, D. E. Knuth | the random number generator LuaTeX shares with METAFONT |

Why they are permissible:

* **They are published works whose terms allow unrestricted copying.**
  `tex.web` and `mf.web` begin with: "Unlimited copying and redistribution
  of this file are permitted as long as this file is not modified.
  Modifications are permitted, but only if the resulting file is not named
  tex.web" (resp. `mf.web`). `etex.ch` authorizes copying as long as no
  changes are made to the copy. The two programs are also printed as
  volumes B and D of *Computers & Typesetting*. They are not under the GPL,
  MIT or Apache licenses: their terms govern copies of the files
  themselves.
* **retex neither copies nor modifies them.** They are read as
  documentation, the way a textbook is; retex's code is an independent
  Rust implementation, and none of the files is part of this repository
  (they are kept outside it, under the ignored `target/` directory, for
  reference).
* **They describe the reference behaviour.** For TeX82, e-TeX and the
  METAFONT random number generator, these programs *are* the
  specification: LuaTeX documents its behaviour as that of TeX and e-TeX,
  and its random numbers follow METAFONT's generator.

Sources, with the license text at the top of each file:

* `tex.web`: <https://ctan.org/tex-archive/systems/knuth/dist/tex/tex.web>
* `mf.web`: <https://ctan.org/tex-archive/systems/knuth/dist/mf/mf.web>
  (also on CTAN mirrors, e.g.
  <https://ctan.gonzaleztroyano.es/systems/knuth/dist/mf/mf.web>)
* `etex.ch`: <https://github.com/TeX-Live/texlive-source/blob/trunk/texk/web2c/etexdir/etex.ch>
  (TeX Live's source tree)

## Documentation

* [ROADMAP.md]ROADMAP.md: milestones and status
* [ARCHITECTURE.md]ARCHITECTURE.md: crate layout and design
* [CONTRIBUTING.md]CONTRIBUTING.md: engineering rules, provenance, testing
* [DEPENDENCIES.md]DEPENDENCIES.md: why each external crate is used

## License

CC0-1.0. See [LICENSE](LICENSE).