back-to-school Nroff by example: The basics

The first popular markup language was nroff, which formatted text for typewriter-like devices. Let's learn the basics of formatting text in the original nroff.

I first used a Unix workstation in 1993 in my university's computer lab, when I was an undergraduate student. I was fascinated to explore Unix, but I was immediately struck by the absence of desktop applications. At home, I ran DOS and used a DOS word processor to write my class papers. Unix didn't have a word processor.

Instead, I learned that the "Unix way" was to write documents using nroff and troff, the standard text formatting tools. Nroff generated output suitable for typewriter-like devices; the original nroff printed output to a teletype terminal. In our campus computer lab, nroff generated documents that I could print to a dot matrix printer. Printing to the laser printer required troff.

Aside from the output, nroff and troff were essentially the same. So my first step was to learn the basics of formatting with nroff

A gentle introduction

Nroff documents are always plain text, and use special commands or requests to do certain things on the page. Requests appear on their own lines in the nroff file, and begin with a period followed by one or more letters.

Nroff provides a set of basic requests that define the page size, create a margin, add vertical space, start a new paragraph, and so on. You can also create collections of requests called macros to do several things at once. Some of the more popular macros are collected into macro packages, but we will explore that in another article.

Without any markup requests, nroff will try to collect words and fill paragraphs according to certain defaults; each line is 65 characters wide, and each page is 66 lines long.  One or more empty lines starts a new paragraph. For example, let's start with a plain text file called lorem that contains these lines:

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Vestibulum volutpat felis sit amet elit eleifend, ut interdum metus condimentum.

Praesent volutpat mi sed odio pulvinar efficitur.
Pellentesque porta est nec libero scelerisque, quis posuere lectus cursus.

Processing this file with the nroff command generates 66 lines of output, but I'll only show the first few lines that actually have text on them:

$ nroff lorem | head -6
Lorem   ipsum   dolor  sit  amet,  consectetur  adipiscing  elit.
Vestibulum volutpat felis sit amet elit eleifend, ut interdum me‐
tus condimentum.

Praesent  volutpat  mi sed odio pulvinar efficitur.  Pellentesque
porta est nec libero scelerisque, quis posuere lectus cursus.

In the original text file, each sentence was on its own line. The output collects the words and fills the lines so that each line is 65 characters wide.

Nroff by example (the manual way)

Writing a class paper with nroff requires only a few other requests. Let's explore how to create a simple document using these formatting requests. I've included a sample document that you can format with nroff. A few things to notice about the example:

Set the left and right margins

Documents are easier to read with some space on either side of the printed page. By default, nroff creates output that has no left margin, although the 65-column lines give the document a wide right margin.

A typewriter-like printer has pages that are 85 columns wide and 66 lines long. We can add the .ll request to define the line length at 60 characters. That leaves 25 columns on a line, which we can balance by adding 10 columns to the page offset on the left side with the .po request. These requests effectively set up the left and right page margins for us:

.ll 60
.po 10 

If you add these two lines to the start of a new nroff document, the printed output will have approximately one inch margins on the left and right. That's the standard for academic papers, so that's what I used when I wrote my first class papers with nroff in the campus computer lab.

Add vertical space

By default, nroff starts printing the output immediately, on the first line of the page. To add some vertical space before the first paragraph, we need to use the .sp request with the number of blank lines to insert.

For example, this request will create six blank lines in the document. This is useful to effectively create a top margin, or to add space before a title or section heading:

.sp 6

Temporary indents

Nroff creates block paragraphs by default, where every line starts on the left edge. In more formal documents, technical writers might use a block paragraph as the first paragraph in a new section, such as after a title or section heading. Following paragraphs usually are indented on the first line. This provides a visual break for the reader, so long documents are easier to read.

To create a temporary indent in nroff, use the .ti request with the number of spaces to add before the first line of text. This request will start the next line of output as a new paragraph with five spaces of indent:

.ti 5

Center text

In most documents, we need to center certain information like the title and author. To center one or more lines, use the .ce request with the number of lines that should be centered. This indicates the next input lines in the file that should be centered, not the generated output lines after nroff processes the file.

For example, use this request to center the next two lines, even though there's a .sp request in there that adds an extra blank line in the output:

.ce 2
Sample Lorem Ipsum text
.sp 1
to demonstrate the basics of nroff

Sample file

This sample file demonstrates the most essential requests to format a document in nroff:

.ll 60
.po 10
.sp 6
.ce 2
Sample Lorem Ipsum text
.sp 1
to demonstrate the basics of nroff
.sp 3
.ti 5
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Quisque laoreet est dictum maximus lacinia.
Aenean ultrices eros id est efficitur, suscipit laoreet ex consectetur.
Fusce at odio in diam feugiat pretium sit amet sit amet massa.
Donec pharetra nibh nec arcu euismod, quis tincidunt libero semper.
.sp 1
.ti 5
Cras a sapien suscipit, pretium dui vitae, varius ex.
Phasellus vitae ante in sem pulvinar tincidunt nec et diam.
Donec fringilla lorem id commodo tristique.
Quisque tincidunt purus at neque ultricies, fermentum luctus eros vestibulum.
Maecenas dapibus nisl quis nibh dapibus auctor.
Suspendisse fermentum arcu ut placerat imperdiet.
Praesent tincidunt neque quis metus mattis interdum.
.sp 1
.ti 5
Fusce id enim non orci suscipit tempus.
Mauris viverra ipsum at blandit ullamcorper.
Praesent sit amet ligula at ligula auctor dapibus in quis mauris.
Curabitur nec justo vestibulum, dapibus quam a, tempor eros.
Donec bibendum lorem et turpis lacinia facilisis.
Aenean quis augue vitae nisl pellentesque finibus.
Sed sodales lectus a cursus finibus.
.sp 1
.ti 5
In et dui pulvinar, rutrum nisl nec, congue mauris.
Cras pellentesque ipsum vitae sapien facilisis, non feugiat sem euismod.
Fusce a lectus id felis blandit hendrerit.

If you process this file with the nroff command, you'll get a new file that is formatted appropriately for a typewriter-like printer, assuming 85 columns per line and 66 lines per page. The new document has a one inch margin on the left, and six spaces at the top. Every paragraph starts with a five space indent.

So you can see all 66 lines in the new document, I'll filter the nroff output through another command that adds numbers before each line:

$ nroff lorem.nro | awk '{print NR $0}'
1
2
3
4
5
6
7                            Sample Lorem Ipsum text
8
9                       to demonstrate the basics of nroff
10
11
12
13               Lorem  ipsum  dolor  sit  amet,  consectetur adipiscing
14          elit.  Quisque laoreet est dictum maximus  lacinia.   Aenean
15          ultrices  eros  id  est  efficitur, suscipit laoreet ex con‐
16          sectetur.  Fusce at odio in diam feugiat  pretium  sit  amet
17          sit  amet massa.  Donec pharetra nibh nec arcu euismod, quis
18          tincidunt libero semper.
19
20               Cras a sapien suscipit, pretium dui vitae,  varius  ex.
21          Phasellus  vitae ante in sem pulvinar tincidunt nec et diam.
22          Donec fringilla lorem id commodo  tristique.   Quisque  tin‐
23          cidunt  purus  at  neque  ultricies,  fermentum  luctus eros
24          vestibulum.  Maecenas dapibus nisl quis nibh dapibus auctor.
25          Suspendisse  fermentum arcu ut placerat imperdiet.  Praesent
26          tincidunt neque quis metus mattis interdum.
27
28               Fusce id enim non orci suscipit tempus.  Mauris viverra
29          ipsum  at  blandit ullamcorper.  Praesent sit amet ligula at
30          ligula auctor dapibus in quis mauris.  Curabitur  nec  justo
31          vestibulum,  dapibus  quam  a,  tempor eros.  Donec bibendum
32          lorem et turpis lacinia facilisis.  Aenean quis augue  vitae
33          nisl  pellentesque  finibus.   Sed  sodales  lectus a cursus
34          finibus.
35
36               In et dui pulvinar, rutrum  nisl  nec,  congue  mauris.
37          Cras  pellentesque ipsum vitae sapien facilisis, non feugiat
38          sem euismod.  Fusce a lectus id felis blandit hendrerit.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

This shows the basics of how to use nroff to format text documents. Start with this sample to explore how nroff formats documents for typewriter-like printers. In an upcoming series, I'll build on this to show how to format documents using other macro packages. These essentials with nroff provide a solid understanding of the other formatting.