Format Equations in roff with GNU eqn

Typing a quadratic formula into a man page or a roff document looks impossible until you meet eqn, which turns plain-text maths into proper notation. You will turn a small roff document containing mathematical notation into terminal, PostScript or MathML output with GNU eqn. The examples use groff 1.23.0 from the Ubuntu groff-base package. Allow about 15 minutes for a first working document. No root privileges are needed.

1. Know which program does what

eqn is a preprocessor. It reads roff, translates the material between .EQ and .EN, and writes roff to standard output. It does not normally produce a finished page by itself.

Confirm the version before relying on a feature. It also makes a bug report reproducible:

eqn --version
groff --version
dpkg-query -W -f='\${Package} \${Version}\n' groff-base

Checkpoint: on the machine used for these examples, the result begins with GNU eqn (groff) version 1.23.0 and the package is groff-base 1.23.0-3build2. Your output may differ.

2. Write a displayed equation

Put the equation between lines beginning with .EQ and .EN. Spaces and newlines separate tokens. They do not become visible spacing in the result.

.EQ
F = m a
.EN

Save that as newton.roff, then render it for a UTF-8 terminal:

groff -e -Tutf8 newton.roff

You should see an equation containing F = ma. The terminal driver may use escape sequences to underline italic letters, so do not treat the raw output as plain text. The same source can go to a different groff device, as long as that device is installed.

To inspect what the preprocessor itself emits, use:

eqn -Tutf8 newton.roff | sed -n '1,35p'

That output is intermediate roff, not a portable display format. Keep the -T option: without it, eqn warns that it was not given a device. Passing it in the pipeline stops the preprocessor and formatter making different device assumptions.

3. Build a less trivial expression

Tokens such as sup, over and sqrt describe structure, and braces group an expression. Without braces, a superscript applies to the next expression only. That is a frequent source of wrong-looking formulae.

.EQ
x = { - b ~ \[+-] ~ sqrt { b sup 2 - 4 a c } } over { 2 a }
.EN

Render it with the same command:

groff -e -Tutf8 quadratic.roff

The output contains a fraction, a plus-or-minus sign and a square root. Two details are worth knowing:

4. Add inline equations deliberately

For running text, define delimiters inside an equation block. This example uses two dollar signs and then turns them off, so later dollar signs in the document are ordinary text.

.EQ
delim $$
.EN
The distance is $x sup 2 + y sup 2$.
.EQ
delim off
.EN

Run it as:

groff -e -Tutf8 inline.roff

Delimiters apply to equations not enclosed by .EQ and .EN. A source-level delim xy overrides a command-line delimiter set with eqn -d xy.

Recovery: if an inline equation is accidentally left open, eqn -N prohibits newlines within delimiters and helps eqn recover from a missing closing delimiter.

5. Produce MathML when HTML is the target

Use the MathML device instead of the normal troff device:

eqn -T MathML newton.roff

The output keeps the .EQ and .EN lines, but puts MathML markup for the equation between them. In a larger groff workflow, pass the same device choice consistently through the preprocessors you use.

MathML is not troff with different spelling:

Tip: stick to ordinary equation structure when the same source must work in both output families.

Common traps

Nothing in these examples changes system state, so there is no service to restart and no undo step. If a document renders wrongly, keep the source and compare the intermediate output from eqn -Tutf8 with the final formatter output. That separates equation syntax errors from device or font problems.

Done means