with apologies

`just` LaTeX it!

Richard Mortier · January 18, 2025 · #tech

I have recently become a fan of just as a replacement for the venerable make. I find that nowadays I rarely need the built-in dependency rules that make provides. Perhaps more radically, I also rarely need to write my own as the prevelance of format-specific build tools such as cargo, uv, latexmk and the like mean I don’t need to write my own either.

Recently, while writing references and then helping out get submissions for Rossfest consistently formatted and building cleanly, I found myself extending my various just targets for LaTeX. So I thought I’d document them here.

I always begin my Justfile with the apparently idiomatic “just show me the targets and associated help text” target:

_default:
    @just --list

This seems considerably easier – and more powerful – than the equivalent hack I used to use in a Makefile!

.DEFAULT: help

.PHONY: help
help:
	@echo "Targets are:"
	@grep -E '^(^## |[^.#][ a-zA-Z0-9-]+:.*#)' Makefile \
	| sed -E 's/:[[:print:]]+#/:/;s/^([^#])/-- \1/'

Next setup up some useful variables: the command we’ll use (latex) plus sources (texs) and targets (pdfs), and droppings that might be produced but not cleaned up by latexmk -[cC]:

latex := "latexmk -pdf"

texs := `echo [0-9][0-9]-*.tex`
pdfs := replace(texs, '.tex', '.pdf')
droppings := "$f.nav $f.snm $f.bbl"

Now to actually building and cleaning things; first, individual targets:

# build a PDF
pdf tgt:
    {{latex}} {{file_stem(tgt)}}.tex

# clean generated files
clean tgt:
    {{latex}} -C {{file_stem(tgt)}}.tex
    for f in {{file_stem(tgt)}}; do rm -f {{droppings}} ; done

(Yes, ok, so it seems a bit silly to have to wrap a for loop around simp[ly to propagate a variable from the Justfile into the shell. But no matter.)

Next, all available targets:

# build all PDFs
pdfs:
    for f in {{texs}}; do just pdf $f ; done

# clean all PDFs
clean-pdfs:
    for f in {{pdfs}}; do just clean $f ; done

Finally, watch a target, rebuilding on save – it may be helpful to avoid automatically saving the source while in a state in which it will not successfully build:

# watch a file, rebuilding when saved
watch tgt:
    while inotifywait -e close_write {{tgt}}* ; do just pdf {{tgt}} ; done