Render Simple Equations in Terminal Documents with neqn

A man page sometimes needs a fraction or a square root without a full typesetting pipeline, and that is what neqn is for. It turns an equation block into character-cell output for a terminal, using the locally installed GNU groff 1.23.0 from the groff-base package, and it never touches your original source file.

Allow fifteen minutes: a shell, groff-base, and either a plain-text roff file or a here-document. Nothing here needs sudo. Keep expectations modest too: neqn is for equations inside terminal-oriented documents, not for producing a typeset PDF or something a browser would render.

1. Check the installed command

Confirm which binary will run and which package supplied it. Both are ordinary, read-only checks:

$ command -v neqn
/usr/bin/neqn
$ dpkg-query -W -f='${Package} ${Version}\n' groff-base
groff-base 1.23.0-3build2
$ neqn --version
GNU eqn (groff) version 1.23.0

That last line names the implementation behind neqn: a thin wrapper around eqn that just selects the ascii output device. Its own manual page does not define a separate equation language or its own formatting options, it borrows eqn's entirely.

Checkpoint: If command -v neqn finds nothing, install the package that provides /usr/bin/neqn through your normal package-management process. Do not drop a different binary into a system directory just to make an example run.

2. Write a minimal equation block

Equation input sits between .EQ and .EN, each starting its own line; everything around the block is ordinary roff. This writes a temporary document under /tmp, so it cannot touch anything in your working tree:

$ tmp_roff=$(mktemp)
$ printf '%s\n' \
    '.sp 1' \
    '.EQ' \
    'a over b' \
    '.EN' \
    '.sp 1' > "$tmp_roff"
$ sed -n '1,8p' "$tmp_roff"
.sp 1
.EQ
a over b
.EN
.sp 1

Inside the equation language, over stacks the expression before it over the expression after it. Spaces here separate tokens, they are not display spaces. Braces group a larger expression, which matters the moment an operator like sqrt, sup or over needs to consume more than one token.

A common trap is putting text on the same line as the markers, such as .EQ a over b. The documented form keeps .EQ alone on its line, the equation input after it, and .EN alone on its own line too. Keep that separation while you are still testing.

3. Run neqn as a preprocessor

neqn translates the equation block into roff instructions; it does not produce the final terminal display by itself. Pipe its output into nroff with the ASCII device selected:

$ neqn "$tmp_roff" | nroff -Tascii
                  a
                  -
                  b

Exact horizontal position depends on the surrounding roff and your terminal width, but the useful part is a fraction: a above a rule, b below it. A blank line before or after is normal whenever the document asks roff for vertical space.

Checkpoint: Run the same pipeline with an exit-status check. A shell pipeline's default status is just the last command's, so turn on pipefail when you are actually diagnosing a failed preprocessor:

$ set -o pipefail
$ neqn "$tmp_roff" | nroff -Tascii > /tmp/neqn-output.txt
$ printf 'pipeline status: %s\n' "$?"
pipeline status: 0
$ sed -n '1,12p' /tmp/neqn-output.txt

Do not treat the generated roff as a stable format worth keeping: it is an intermediate stream meant for GNU roff tools, and its control sequences are not readable as equation output on their own.

4. Put the equation in a real document

For anything you intend to keep, use an actual source file rather than a long one-off shell command. This adds a heading and some explanatory text using the basic requests nroff already understands:

$ cat > /tmp/terminal-equation.roff <<'ROFF'
.TH TERMINAL-EQUATION 1
.SH NAME
terminal-equation \- a small neqn example
.PP
The average is shown below.
.EQ
sum over n
.EN
.PP
The equation is part of the roff source, not a shell command.
ROFF
$ neqn /tmp/terminal-equation.roff | nroff -Tascii | sed -n '1,30p'

The quoted here-document marker stops the shell expanding backslashes or other characters in the source, keeping roff escapes and equation tokens under the document format's control rather than the shell's.

For a quick one-off test, standard input is simpler and skips creating a file at all:

$ printf '%s\n' '.EQ' 'sqrt { x sup 2 + y sup 2 }' '.EN' \
    | neqn \
    | nroff -Tascii

Both commands read standard input when you give them no file operand. The backslashes in that display are shell line continuations, nothing to do with the equation itself, which contains sqrt, sup and one braced expression.

5. Keep the device and the tool straight

The name neqn is itself a hint: this wrapper targets low-resolution, character-cell output. It calls eqn with the ascii device, and nroff -Tascii is the matching formatter for a terminal-style result afterwards.

Do not pipe neqn output straight into a PDF or PostScript viewer and expect a finished page: for typeset output, use the equivalent groff pipeline with its equation preprocessor option instead, a genuinely different workflow. Swapping only the final nroff call will not change what neqn already told eqn to generate.

The installed eqn(1) documentation itself warns that equation formatting is not well supported on terminal devices, though simple input works fine. Stick to fractions, superscripts and square roots. If alignment or glyphs start looking wrong, move to a typeset device rather than piling on terminal-specific escapes to compensate.

6. Diagnose failures without touching the system

If the output still contains a literal .EQ or .EN, check that each marker really starts its own line and that neqn ran before nroff, not after. If the equation itself is missing, inspect the source without passing it through another formatter first:

$ nl -ba /tmp/terminal-equation.roff | sed -n '1,20p'
$ neqn /tmp/terminal-equation.roff > /tmp/terminal-equation.expanded
$ sed -n '1,45p' /tmp/terminal-equation.expanded

Seeing roff control lines in the expanded file is expected and fine. What you are really checking is that neqn exits successfully and that it recognised the input markers rather than printing them as plain text.

If an equation throws a syntax error, strip it back one token at a time: try x, then x over y, then add grouping or another operator, and keep the last version that worked. Do not guess at TeX syntax here, GNU eqn has its own token rules even where the notation looks familiar.

If a command fails because it cannot open an input file, fix the path or the read permission; there is no reason to run this formatter as root. If you made the temporary files above, remove only those named files once you are done checking them:

$ rm -- "$tmp_roff" /tmp/neqn-output.txt /tmp/terminal-equation.roff /tmp/terminal-equation.expanded

That removal is optional, and it cannot be undone. Use the variable holding the real temporary filename, as shown, rather than guessing at a path.

Done means