Trying to write my thesis with groff

Last month i managed to finish my master’s thesis. It was one of my largest writing projects and definitely the one i poured the most work into. In this post i want to talk about the search for a typesetting system that is fun to work with and why groff didn’t work out in the end.

groff homepage

The search

I did my bachelor’s degree in physics and my master’s in Computational Science with a strong focus on theoretical condensed matter physics with a bit of bioinformatics. Everything in physics is made with LaTeX. The experimental course work during my studies were expected to be typeset using LaTeX, introductory (and advanced) courses only existed in LaTeX, all journals expect LaTeX manuscripts, etc. This is for good reason though, the math typesetting quality in all of TeX is probably the best out there. I do however have some problems with it. The engine is slow, the packages required are huge (a complete TeXLive install is over 4 GiB) and the syntax is often verbose and unintuitive. I still like LaTeX, but i wondered if there is something better out there for individual projects.

LaTeX homepage TeXLive homepage

The first thing that comes to mind here are basic WYSIWYG text editors like LibreOffice Writer and MS Word, the latter being quite popular in medical papers. As someone who likes to work on laptops all day, i see the appeal of only working with one open window instead of an editor and a viewer. Now LibreOffice is great, but both editors seem inadequate for scientific writing in my field. While math formulas are fine-ish, vector graphics are not supported in both programs. Since all my plots and sketches are vectors, this is a deal breaker.

LibreOffice homepage

After doing some more searching, i found small communities of people doing scientific writing with two tools that seemed to improve on my main gripes with LaTeX. The first is Typst, a pretty new typesetting system from Berlin written in Rust. It is very small (~50 MiB binary) and fast. Being new, it lacks a lot of features of LaTeX and the support community however. The other one is groff, the tool that is mainly used to typeset man-pages. It is ancient and built into basically any UNIX system. The community around document typesetting is very small however and the tool quite outdated. I tested both programs for my thesis pretty extensively. While i settled for Typst in the end due to better pdf support (hyperlinks, etc), working with groff was quite interesting. Here i want to talk about the intricacies of developing a unique document style using groff.

Typst homepage Typst GitHub

What is groff?

Let’s talk about groff itself a bit more. While groff was written in the 90s, it is a reimplementation of AT&Ts troff typesetter, which dates back into the 60s. The tool provides a low-level description language for all kinds of documents. This language is pretty hard to read (and write). To alleviate this, a few macro packages exist for different kinds of document types. For paper documents, the ms macro package is one of the more popular options. The relation between groff - groff + ms is similar to TeX - LaTeX, the low-level descriptions are replaced by more understandable macros for headings, footnotes, headers, etc. The tool can be extended using preprocessors, which provide some rather basic functionality to groff.

PreprocessorFunction
tblFormat tables
eqnFormat math equations
picDraw pictures and diagrams; similar to tikz
grapPlot data and functions; similar to pgfplots
referCiting and bibliography

For my thesis i need all preprocessors, except tbl. The total installation size for groff (includes tbl, eqn, pic, refer) and grap in Debian is about 20 MiB. Compared to the 4 GiB of LaTeX this is tiny!

Working with groff

The basic usage should be familiar to all LaTeX people. We write a text document with text + instructions and compile it on the command-line. The compiler/filter is now called groff instead of pdflatex/lualatex. Groff doesn’t need any additional info. If we start with a text file test.ms with the content

Hello

we can successfully compile it using the command

groff test.ms > test.ps

The compiler reads our text file and interprets the groff commands - which are none in this case. In the next step postscript output (.ps) is produced with the complete document. Postscript is the predecessor of the more modern pdf standard. We can convert the .ps file using the tool ps2pdf.

ps2pdf test.ps

Now we can finally open the resulting file test.pdf. We should see an empty page with the word Hello in the top left corner. Success! Our first document.

Let’s move on to the ms macro package.

.TL
Document
.AU
Mia Schambeck
.AI
My Home

.NH 1
This is a Test
.LP
Hello, this is a document to test the basic functionality of groff!

In this document, we used five ms instructions. All groff instructions start with a dot at the beginning of the line. Placing the instructions at the start of the line is mandatory. The first instruction .TL defines the title of our document. Arguments are provided in the next line. Our document is therefore called “Document”. The second instruction .AU takes the name of the author. The third one .AI defines the institution of the author, more important for official documents.

This concludes the document head. We want to start our document with the first heading. The macro .NH formats the following line as a heading of any depth. Using .NH 1 results in a heading of depth 1, usually a chapter. We want to follow it up by a paragraph of text. To do this we can use the instructions .LP and .PP. The latter .PP indents the first line of a paragraph, while .LP does not.

To compile the document, groff needs to know that we want to use the ms package. This is done by passing the -ms argument.

groff -ms test.ms > test.ps

We can add the pdf conversion to get usable output

groff -ms test.ms > test.ps && ps2pdf test.ps

If we want to discard the .ps file we can add

groff -ms test.ms > test.ps && ps2pdf test.ps && rm test.ps

With this we can format simple documents using groff-ms!

Building my own style

Our document is pretty bare bones right now. Visually pleasing documents help me concentrate longer and are more fun to read. Writing a thesis is also a pretty personal thing, so i like to leave a bit of personality in the formatting. With a bit of digging, the possibilities with groff are extensive. Using draw commands, we can customize headings and create colorful boxes. If you’re interested, i host my thesis attempt at sourcehut.

Thesis repo

Here i want to show off some of the formatting i did. Pull up the pdf from the repository, if you want to see what i’m talking about.

.ds CH \v'.8m'\D't 0.05m'\D'l 37.8 0'                               
.ds LH \\*[chap]
.ds RH \v'-.8m'\\n[%]

These are all the commands used to generate the page header. First .ds CH defines the center page header, then .ds LH and .ds RH the left and right headers. The syntax is quite unreadable here: The left header is the current chapter title \\*[chap], the right header the current page number. For the center header i used some plain groff draw instructions. First the draw pointer is moved .8m (0.8*fontsize) vertically, then a line with thickness 0.05m and length 37.8 in x direction is drawn.

.de decor                                                           
\h'-2.5m'\M[teal]
\v'0.4'
\D'P 0.3 0 0.6 -1.1 -0.3 0'
\v'1.1'
\h'-1.3'
\D'P 24.7 0 0 -0.02 -24.7 0'
\v'-0.38'
\h'1.5'
\M[]
..

This is my custom macro for the decoration around a big heading (.NH 1). After the .NH 1 instruction is used for a heading, the current number is written by groff and the pointer is positioned right after it. This macro moves the pointer 2.5m to the left, next to this number. After this it draws a polygon - a thin rectangle - down and left. Then it aligns the pointer and draws a second line. Finally it moves the pointer back to the original position. All in all it underlines the heading with a small decor line left of it. The instruction \M[teal] selects a color for the pointer according to my earlier definition.

.defcolor teal rgb #179299

This makes for an interesting custom document theme.

.de box
\M[base]\D'P 0.05 -0.1  0.075 -0.075  0.1 -0.05 \
0 0  \\n[boxw] 0 \
0.1 0.05  0.075 0.075  0.05 0.1 \
0 \\n[boxh] \
-0.05 0.1  -0.075 0.075  -0.1 0.05 \
-\\n[boxw] 0 \
-0.1 -0.05  -0.075 -0.075  -0.05 -0.1'\M[]
\M[teal]\D'P -0.23 0 0 -\\n[boxh] \
0.05 -0.1  0.075 -0.075  0.1 -0.05 \
1 0  0 \\n[boxh]  0 0.45  -1 0 \
-0.1 -0.05  -0.075 -0.075  -0.05 -0.1'\M[]
..

This last macro draws a colorful box around a text region. The two variables boxw and boxh control the width and height of the box, so the macro works with arbitrary paper sizes. It doesn’t automatically fit the region though. This semi-manual workflow is how i did all my work in groff. It’s a bit cumbersome, but also a lot of fun!


This site uses the wonderful Catppuccin color scheme.