tex_engine/doc.rs
1/*! This module contains additional documentation, use cases, etc.
2
3# Why is this so complicated?
4
5Unlike most programming languages, which broadly adhere to a conceptual split between
6*tokenization*, *parsing* and *interpreting* as separate, largely independent steps,
7TeX combines all of these into a single process -- meaning that tokenization and parsing
8are stateful processes that depend on the current state of the interpreter.
9For example, the existence of the `\catcode` command means that whether the string
10`\catcode` is a single token (i.e. a control sequence) or a sequence of 7 characters (or fewer)
11depends on the current category codes of the characters in the string, which can be changed at any time.
12Hence, without *interpreting* the document, and updating the state in the process, it is impossible
13to even *parse* the document correctly into an abstract syntax tree.
14
15Moreover, different engines treat the same document potentially very differently. For example,
16plain TeX processes a file as a stream of individual *bytes*, whereas XeTeX interprets the file
17as a stream of *Unicode codepoints*. While this may seem like a minor difference, it is a difference
18that carries through the entire codebase. Plain TeX treats *fonts* by loading a `.tfm` file,
19which provides metrics for up to at most 256 glyphs, whereas XeTeX uses system fonts with
20potentially thousands of glyphs. Plain TeX offers a mere 256 registers for integer values,
21dimensions, glue, etc., whereas e-TeX offers 32768 registers for each of these.
22Plain TeX implements dimensions as integers of "scaled points", with corresponding arithmetic
23operations and hence fixed-point precision, but an implementation taking advantage
24of floating-point arithmetic would be possible without changing any of the core mechanisms of
25macro expansion or (ultimately) producing nodes to be output. Having said that, the original
26TeX engine produces dvips output, which was changed by pdfTeX to produce pdf output, adding
27additional primitives for pdf-specific features.
28
29But apart of those differences, the core primitive commands, macro expansion etc. are the same
30for all engines.
31
32This crate therefore tries to abstract away as much of the differences between engines as possible,
33while still providing efficient implementations of the core algorithms and data structures.
34
35
36# Okay, okay, so, how do I use this?
37
38Well, it depends on what you want to do. In the simplest case, you want to use an already existing
39engine to process a `.tex` file. In the simplest (but probably not too realistic) case, a plain
40TeX engine without any of the extensions provided by e-TeX, pdfTeX, XeTeX, LuaTeX, etc., e.g.
41maybe you want to process David Carlisle's famous [xii.tex](https://github.com/davidcarlisle/dpctex/blob/main/xii/xii.tex).
42Then:
43```no_run
44use tex_engine::prelude::*;
45
46// instantiate a new plain TeX engine:
47let mut engine = PlainTeXEngine::default();
48// register the default primitive commands and process `plain.tex`:
49engine.initialize_plain_tex().unwrap();
50// the engine is now ready to process a document:
51engine.do_file_default("/path/to/your/xii.tex",|_,node| {
52 // do something with the nodes produced, e.g. print them to stdout:
53 println!("{}",node.display());Ok(())
54}).unwrap()
55```
56
57This will produce something along the lines of:
58```text
59<vbox:vbox>
60 <hbox:parline>
61 <hbox:parindent></hbox:parindent>On<space>the<space>§rst<space>day<space>of<space>Christmas
62 <space>my<space>true<space>love<space>gave<space>to<space>me
63 </hbox:parline>
64 <vskip:0.0pt plus 1.0pt>
65 <hbox:parline>
66 <hbox:parindent></hbox:parindent>a<space>partridge<space>in<space>a<space>pear<space>tree.
67 </hbox:parline>
68 <vskip:12.0pt plus 4.0pt minus 4.0pt>
69 <vskip:0.0pt plus 1.0pt>
70 ...
71```
72...representing the nodes produced by the engine, which can then be used to produce e.g. a `.dvi`
73or `.pdf`file.
74
75Now, chances are, if you have a `.tex` file, it will requite at least LaTeX (which is technically
76just a set of macros on top of plain TeX). You can load the LaTeX macros by calling
77```no_run
78# use tex_engine::prelude::*;
79# let mut engine = PlainTeXEngine::default();
80engine.initialize_etex_primitives(); // registers the plain TeX + e-TeX primitives
81engine.load_latex().unwrap(); // processes `latex.ltx`
82```
83...but this will throw an error, because LaTeX requires the primitives of one of several modern TeX engines,
84such as pdfTeX, XeTeX or LuaTeX.
85
86This crate implements (most of) the primitives of pdfTeX, when the `pdflatex` feature is enabled.
87Assuming the feature is enabled, you can load the pdfTeX primitives by calling
88```no_run
89# use tex_engine::prelude::*;
90use tex_engine::pdflatex::{PDFTeXEngine,PlainPDFTeXEngine};
91let mut engine = PlainPDFTeXEngine::default();
92// registers the plain TeX + e-TeX + pdfTeX primitives,
93// and processes `pdftexconfig.tex` and `latex.ltx`
94engine.initialize_pdflatex().unwrap();
95```
96This will (on `--release`) process `latex.ltx` in about 3.5 seconds on my machine.
97
98You can then process a `.tex` file by calling
99```no_run
100# use tex_engine::prelude::*;
101# use tex_engine::pdflatex::{PDFTeXEngine,PlainPDFTeXEngine};
102# let mut engine = PlainPDFTeXEngine::default();
103engine.do_file_pdf("/path/to/your/tex/file.tex",|e,node| {
104 // do something with the nodes produced, e.g. print them to stdout:
105 println!("{}",node.display());Ok(())
106}).unwrap()
107```
108
109# What else can I do?
110...todo
111
112*/