No description
  • Rust 74.4%
  • Nix 21.8%
  • TeX 3.8%
Find a file
2026-05-17 10:58:56 +02:00
lanix feat(cli): add colour and logging checks 2026-05-13 23:05:46 +02:00
latex feat(example): add example to show features 2026-05-13 23:06:23 +02:00
nix chore(nix): rename package.nix to default.nix 2026-05-17 10:58:56 +02:00
.gitignore fix(latex): changed from expansion to ifx (renamed) 2026-05-10 18:30:18 +02:00
default.nix chore(nix): rename package.nix to default.nix 2026-05-17 10:58:56 +02:00
LICENSE Initial commit 2026-05-04 23:19:47 +02:00
README.md feat(readme): full readme 2026-05-13 23:51:06 +02:00

LaNiχ

A Nix-based blazingly-fast parametric LaTeχ compilation routine definition system written in Rust + nix.

LaNiχ takes advantage of Nix's configuration evaluation system to construct a sequence of latexmk invocations to compile multiple times a same document with multiple different variable values, as well as to pass variables defined in an actual programming language that has access to the outside world and interfaces easily with NixOS machines.

Quick start

Add a default.nix file at the root of your LaTeχ project:

{ pkgs ? import <nixpkgs> {}
, lanix ? pkgs.callPackage /path/to/lanix/nix/package.nix {}
}:

lanix.compile {
  src = ./.;
  config = {
    document = "./main.tex";

    latexmk = {
      output_mode = "pdf_lua";
      output_directory = "build";
      interaction = "non_stop_mode";
      bibtex = "when_needed";
    };

    variables = {
      title     = { type = "string";      value = "My Document"; };
      n_samples = { type = "list_int";    value = [ 100 500 1000 ]; };
      method    = { type = "list_string"; value = [ "euler" "rk4" ]; };
      tolerance = { type = "float";       value = 1.0e-6; };
    };
  };
}

See the [./latex/example.tex](example document) for examples on how variable passing works, and [./latex/default.nix](the nix configuration) for a complete example of configuration.

Variables

Variables are declared in the variables attribute set. Each entry has a type and a value which influences how they are passed to latexmk in the end.

For now, variable typing is not implemented in the Nix module, and no check is made on the variables. This will be changed in the future, but it needs dependent typing.

Supported variables are the following:

Type Nix value
int integer
float float
string string
bool true / false

The four types have variations built by \lambda x. \texttt{list\_}x. When a list [ a b c ] is passed to variable x, one compilation will be made for each of the possible values of x. When multiple lists are passed to multiple variables, the space of compilations is given by the product of the lists.

Inside the document, variables are accessed via the lanix package:

\usepackage{lanix}
\DefineVariable[int]{n_samples}{500}   % default used outside LaNiχ

We refer to the package's code for more details, the documentation is not yet written.

latexmk options

Most of latexmk direct options (namely except -pretex which is used by LaNiχ for variable passing) correspond to flags in the nix module. Defaults should match latexmk's defaults.

Output and engine

Option Type Default latexmk flag
output_mode enum pdf_lua see table below
output_directory string? -output-directory=<dir>
out2_directory string? -out2dir=<dir>
aux_directory string? -auxdir=<dir>
emulate_aux_dir enum default -emulate-aux-dir / -emulate-aux-dir-
change_to_dir bool? -cd / -cd-
jobname string? -jobname=<name>

output_mode values:

Value Flag Engine Output
pdf -pdf pdflatex PDF
pdf_dvi -pdfdvi latex DVI → PDF
pdf_ps -pdfps latex PS → PDF
pdf_lua -pdflua lualatex PDF
pdf_xe -pdfxe xelatex PDF
dvi -dvi latex DVI
dvi_lua -dvilua dvilualatex DVI
hnt -hnt hilatex HNT
xdv -xdv xelatex XDV
post_script -ps latex PostScript

Bibliography

Option Type Default latexmk flag
bibtex enum when_needed see table below
bibfudge enum off -bibfudge / -bibfudge-
makeindex_fudge enum off -indexfudge / -indexfudge-

bibtex values:

Value Flag Behaviour
when_needed -bibtex Run when a .bbl is required
never -bibtex- Never run BibTeX
conditional -bibtex-cond Run only when the .bib file exists
conditional_keep_bbl -bibtex-cond1 As above; keep .bbl on cleanup

Engine overrides

Option Type Default latexmk flag
latex_program string? -latex=<prog>
pdflatex_program string? -pdflatex=<prog>
lualatex_program string? -pdflualatex=<prog>
xelatex_program string? -pdfxelatex=<prog>
dvilualatex_program string? -dvilualatex=<prog>
latex_options [string] [] -latexoption=<opt> × n

Interaction and verbosity

Option Type Default latexmk flag
interaction enum non_stop_mode -interaction=<mode>
verbosity enum normal (none) / -silent / -verbose
log_file_warnings bool? -logfilewarninglist / -logfilewarninglist-
warnings_as_errors bool false -Werror
show_time bool? -time / -time-
show_rules bool? -rules / -rules-
show_commands bool false -commands
rc_report bool? -rc-report / -rc-report-
dir_report enum? -dir-report / -dir-report- / -dir-report-only

interaction values: non_stop_mode, batch_mode, scroll_mode, error_stop_mode.

Dependency tracking

Option Type Default latexmk flag
show_deps_m bool false -M
show_dependents bool? -dependents / -dependents-
deps_escape enum? -deps-escape=<kind>
deps_output string? -deps-out=<file>
deps_file string? -MF <file>
deps_phony_targets bool false -MP

deps_escape values: nmake, none, unix.

File operations

Option Type Default latexmk flag
clean enum? -c / -C / -CF
force bool? -f / -f-
go_mode enum normal (none) / -g / -gg / -gt
use_make bool? -use-make / -use-make-
recorder bool? -recorder / -recorder-
norc bool false -norc
std_tex_cmds bool false -stdtexcmds
rc_file string? -r <file>
exec_perl [string] [] -e <code> × n

clean values:

Value Flag Removes
light -c Aux/log files; keeps dvi/ps/pdf
full -C All generated files including dvi/ps/pdf
reset_db -CF Resets the latexmk database, then proceeds

Preview and viewer

Option Type Default latexmk flag
preview enum? -pv / -pvc
new_viewer bool? -new-viewer / -new-viewer-
view enum? -view=<target>
pvc_timeout bool? -pvctimeout / -pvctimeout-
pvc_timeout_mins uint? -pvctimeoutmins=<n>

preview values: once (-pv), continuous (-pvc).

Printing

Option Type Default latexmk flag
print bool false -p
print_target enum? -print=<target>

print_target values: dvi, ps, pdf.

TeX engine pass-throughs

Option Type Default latexmk flag
shell_escape enum default (none) / -shell-escape / -no-shell-escape / -shell-restricted
landscape bool? -l / -l-
synctex enum off (none) / -synctex=1 / -synctex=-1 / -synctex=<n>
halt_on_error bool false -halt-on-error
draftmode bool false -draftmode
file_line_error bool? -file-line-error / -no-file-line-error
mswin_backslash bool? -MSWinBackSlash / -MSWinBackSlash-
dvi_filter string? -dF <filter>
ps_filter string? -pF <filter>
extra_flags [string] [] verbatim, always last

synctex values: off, uncompressed (-synctex=1), compressed (-synctex=-1). For any other integer pass { custom = <n>; }.

Code documentation

The Rust codebase is documented with rustdoc conventions. The LaTeχ package currently only has comments near the functions for the user to read, but the package is quite short. The Nix codebase sucks and is poorly documented, except for the module options which all should have a description and a type.

AI Usage declaration

AI was used in the project to format documentation to nicer markdown, in the README and in the rust code, because git forges can't be bothered to render LaTeχ documents and I'm not writing markdown tables myself. They were built based on docstrings wrote by hand and most were checked. The code comments and the text of the README are handmade.