Typesetting with groff Macros

“In the beginning was the word.” And
from the wordy primordial void there soon arose the blank page, the
toner cartridge and the now ceaseless human craving for print. If
you have a desire to look good in print, or just need to knock out
a memo, term paper or letter to mom, you should know about
groff. groff is a rich yet
accessible set of document formatting tools and is available as
standard equipment on every Linux system. groff can help take your
words and typeset them beautifully on the printed page.

groff refers specifically to
the GNU and updated version of
troff (that venerable document
formatting system developed for UNIX in the prehistoric era, before
the Internet, compact disc and microwave popcorn). Traditional
troff was first written in the early 1970s by Joseph Ossana at Bell
Labs, rewritten a few years later by Brian Kernighan and designed
for the computers and typesetting equipment available at the time.
The GNU version of troff—first called
gtroff, now simply groff—was
written in the early 1990s by James Clark. While remaining
compatible with traditional troff, groff offers several key
enhancements making it easier to use, more powerful and containing
fewer limitations than the program it supersedes. GNU groff is
actively maintained and continues to evolve. In addition to Linux
and other UNIX/UNIX-like systems, ports of groff are available for
most of the other platforms out there. This ubiquity and
open-source freedom lets you publish and share your documents
portably and freely among platforms.

Using groff's macro capabilities for generating printed
output is the focus of this article. It should also be mentioned
that groff serves as the formatting engine for the on-line manual
pages produced by the man command.
If you need a sample of the typesetting prowess of groff, simply
generate a printed manual page with the -t
option to man:

man -t troff >troff.man.ps

This will produce a PostScript version of the manual page for
groff, which you can then view on-screen with one of the PostScript
previewers (gv, mgv), print
directly with a PostScript printer or print to a non-PostScript
printer using a PostScript interpreter such as GhostScript. (You
should really take a look at this man page, by the way. It provides
a thorough summary of all the additional features available in GNU
groff, with more detail than presented here.)

groff offers all the
niceties of computerized typesetting, including automatic
ligatures, kerning, hyphenation and end-of-sentence spacing. groff
also provides low-level control over all aspects of page layout by
means of typesetting commands embedded into an otherwise plain text
file. Most often these commands—or, in groff parlance,
requests—are specified with a period in the
first column of the line containing the command. For example, the
following snippet of document has embedded commands for increasing
the left indent and decreasing the current line length:

This is an example of a groff document..in +0.5i
.ll -0.5i
When formatted by groff, the text continuing
here will appear indented by one-half inch
from both of the previous margins.

Although it is possible to format a document completely using
such “raw” groff requests, it is more typical for endusers to
work with a collection of predefined macros
that encapsulate sequences of raw requests into single commands.
For example, if we wanted to create a macro for the block indent
commands in the previous snippet, it might look like this:

.de Bi.in +0.5i
.ll -0.5i
..

The .de request begins the definition of our
macro named Bi, and the double period on the
last line marks the end. Invoking a macro within a document follows
the same syntax as using a raw request (the name of the macro
follows on a line with a period in the first column). Our new macro
used in a document would look like:

This is another section of my groff document..Bi
Oh boy, now the text continuing here is indented
from both margins!

If at some later time we want to increase the block indent to
three-quarters of an inch, we need only change the macro
definition. All instances of Bi throughout the
document will then format with the new dimensions.

So far, we haven't seen a whole lot here to get excited
about. One of the limitations of traditional troff is that the
names of all commands, macros and other variables are limited to
two characters. Two measly characters? As mentioned earlier, troff
was developed in the veritable stone age of computing, when every
bit mattered, and succinctness was sublime. While the developers of
troff and the standard macro packages have done their best to
devise naming schemes that are as mnemonic as possible within this
two-character constraint, the resulting interface is about as
user-friendly as 80x86 assembly language (which at least uses three
characters for most of its instruction set!).

Fortunately, GNU groff eliminates this two-character naming
limitation. For both the macro developer and the eduser, the

most significant enhancement of groff is that all names,
including macros, numbers, strings, fonts and environments, can be
of arbitrary length. Groff also allows for the
aliasing of troff commands, macros and
variables to provide alternative names for existing ones. We will
exploit this feature heavily through the rest of the article. In
fact, let's begin right now by aliasing the groff alias command
itself:

.als ALIAS als

We can now use this command to provide a set of longer names
for other key groff commands:

.ALIAS MACRO de.ALIAS NUMBER nr
.ALIAS STRING ds

Sure, your old-time, hard-core troff jocks will gnash their teeth
at the syntactic sugar. But the rest of us will have an easier time
figuring out what in Sam Hill some macro is doing when we get back
to work on it after a long and pleasurable weekend—or some other
lapse into real life.

Trending Topics

Upcoming Webinar

Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report

August 27, 2015
12:00 PM CDT

DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.