roff(7)
roff(7) โ concepts and history of roff typesetting ๐
Miscellaneous Information Manual โ yes bestie, thatโs the manual name, and weโre folding it in right here at the top.
Name
roff โ concepts and history of roff typesetting
Description
Okay so the term roff denotes a whole family of document formatting systems, known by names like troff, nroff, and ditroff. A roff system consists of an interpreter for an extensible text formatting language and a set of programs for preparing output for various devices and file formats. Unix-like operating systems often distribute a roff system. The manual pages on Unix systems (โman pagesโ) and bestselling books on software engineering, including Brian Kernighan and Dennis Ritchie's The C Programming Language and W. Richard Stevens's Advanced Programming in the Unix Environment, have been written using roff systems. GNU roffโgroffโis arguably the most widespread roff implementation.
Below we present typographical concepts foundational to understanding any roff implementation, narrate the development history of some roff systems, detail the command pipeline managed by groff(1), survey the formatting language, suggest tips for editing roff input, and recommend further reading materials.
Concepts
AT&T troff was designed to take input as it would be composed on a typewriter, including the teletypewriters used as early computer terminals, and relieve the user drafting a document of concern with details like line length maintenance, hyphenation breaking, and consistent paragraph indentation. Early in its development, the program gained the ability to prepare output for a phototypesetter; a document could then be prepared for output to a teletypewriter, a phototypesetter, or both. GNU troff continues this tradition of permitting an author to compose a single master version of a document which can then be rendered upon a variety of output formats or devices, including PDF, HTML, laser printers, and terminal displays.
roff input contains text interspersed with instructions to control the formatter. Even in the absence of such instructions, a roff formatter still processes its input in several ways, by filling, hyphenating, breaking, and adjusting it, and supplementing it with inter-sentence space. These processes are basic to typesetting, and can be controlled at the input document's discretion.
Instructions to roff take two forms. One is the request, which occupies an input line and starts with the control character, a dot .. The other is the escape sequence, which can occur almost anywhere and starts with the escape character, a backslash \. Both characters are configurable.
.br \" break the output line
When a device-independent roff formatter starts up, it obtains information about the device for which it is preparing output from the latter's description file (see groff_font(5)). An essential property is the length of the output line, such as โ6.5 inchesโ.
The formatter interprets plain text files employing the Unix line-ending convention. It reads input a character at a time, collecting words as it goes, and fits as many words together on an output line as it canโthis is known as filling. To a roff system, a word is any sequence of one or more characters that aren't spaces or newlines. The exceptions separate words.
A roff formatter attempts to detect boundaries between sentences, and supplies supplemental inter-sentence space between them. It flags certain characters (normally โ!โ, โ?โ, and โ.โ) as potentially ending a sentence. When the formatter encounters one of these end-of-sentence characters at the end of an input line, or one of them is followed by two (unescaped) spaces on the same input line, it appends an inter-word space followed by an inter-sentence space in the output. The dummy character escape sequence \& can be used after an end-of-sentence character to defeat end-of-sentence detection on a per-instance basis. Normally, the occurrence of a visible non-end-of-sentence character (as opposed to a space or tab) immediately after an end-of-sentence character cancels detection of the end of a sentence. However, the formatter treats several characters transparently after the occurrence of an end-of-sentence characterโit does not cancel end-of-sentence status upon encountering them. Such characters are often used as footnote marks or to close quotations and parentheticals. The default set is ", ', ), ], *, \[dg], \[dd], \[rq], and \[cq]. The last four are examples of special characters, escape sequences whose purpose is to obtain glyphs that are not easily typed at the keyboard, or which have special meaning to the formatter (like \ itself).
When an output line is nearly full, it is uncommon for the next word collected from the input to exactly fill itโoften, there is room left over for only part of the next word. Hyphenation is the process of splitting a word so that it appears partially on one line, followed by a hyphen to indicate to the reader that the word has been broken, and that its remainder lies on the next. Hyphenation break points can be manually specified; GNU troff also uses a hyphenation algorithm and language-specific pattern files (based on TeX's) to decide which words can be hyphenated and where. Hyphenation does not always occur even when the hyphenation rules for a word allow it; it can be disabled, and when not disabled there are several parameters that can prevent it in certain circumstances.
Once an output line is full, the formatter places the next word (or remainder of a hyphenated one) on a different output line; this is called a break. In this document and in roff discussions generally, a โbreakโ if not further qualified always refers to the termination of an output line. When the formatter is filling text, it introduces breaks automatically to keep output lines from exceeding the configured line length. After an automatic break, the formatter adjusts the line if applicable (see below), and then resumes collecting and filling text on the next output line.
Sometimes, a line cannot be broken automatically. This usually does not happen with natural language text unless the output line length has been manipulated to be extremely short, but it can with specialized text like program source code. groff provides a means of telling the formatter where the line may be broken without hyphens. This is done with the non-printing break point escape sequence \:.
There are several ways to cause a break at a predictable location.
- A blank input line not only causes a break, but by default it also outputs a one-line vertical space (effectively a blank output line). Macro packages may discourage or disable this โblank line methodโ of paragraphing in favor of their own macros.
- A line that begins with one or more spaces causes a break. The spaces are output at the beginning of the next line without being adjusted (see below). Again, macro packages may provide other methods of producing indented paragraphs.
- Trailing spaces on text lines (see below) are discarded.
- The formatter breaks the pending output line without adjustment upon encountering the end of input.
After performing an automatic break, the formatter may then adjust the line, widening inter-word spaces until the text reaches the right margin. Extra spaces between words are preserved. Leading and trailing spaces are handled as noted above. You can align text to the left or right margin only, or center it, using requests.
A roff formatter translates horizontal tab characters, also called simply โtabsโ, in the input into movements to the next tab stop. Tab stops are by default located every half inch measured from the drawing position corresponding to the beginning of the input line; see subsection โPage geometryโ below. With them, simple tables can be made. However, this method can be deceptive, as the appearance (and width) of the text in an editor and the results from the formatter can vary greatly, particularly when proportional typefaces are used. A tab character does not cause a break and therefore does not interrupt filling. The formatter provides facilities for sophisticated table composition; there are many details to track when using the โtabโ and โfieldโ low-level features, so most users turn to the tbl(1) preprocessor to lay out tables.
Requests and macros
A request is an instruction to the formatter that occurs after a control character, which is recognized at the beginning of an input line. The regular control character is a dot .. Its counterpart, the no-break control character, a neutral apostrophe ', suppresses the break implied by some requests. These characters were chosen because it is uncommon for lines of text in natural languages to begin with them. If you require a formatted period or apostrophe (closing single quotation mark) where the formatter expects a control character, prefix the dot or neutral apostrophe with the dummy character escape sequence, \&.
An input line beginning with a control character is called a control line. Every line of input that is not a control line is a text line.
Requests often take arguments, words (separated from the request name and each other by spaces) that specify details of the action you expect the formatter to perform. If a request is meaningless without arguments, it is typically ignored. Requests and escape sequences comprise the control language of the formatter. Of key importance are the requests that define macros. Macros are invoked like requests, enabling the request repertoire to be extended or overridden. (Argument handling in macros is more flexible but also more complex.)
A macro can be thought of as an abbreviation you can define for a collection of control and text lines. When the macro is called by giving its name after a control character, it is replaced with what it stands for. The process of textual replacement is known as interpolation. Interpolations are handled as soon as they are recognized, and once performed, a roff formatter scans the replacement for further requests, macro calls, and escape sequences. In roff systems, the โdeโ request defines a macro.
๐ Page geometry ๐
okay so here's the vibe: roff systems format text while assuming certain things about how big the output medium โ the page โ actually is. Like, the formatter can't break a line it's filling unless it knows the line length, and it gets that from the page width. And it can't decide whether to slap an output line onto the current page or make it wait for the next one unless it knows the page length. โจ
A device's resolution is what converts practical units like inches or centimeters into basic units โ a comfy length measure for the output device or file format. Both the formatter and the output driver use basic units to reckon page measurements. And where do the resolution and page dimensions live? The device description file, bestie. See groff_font(5). ๐
So a page is a two-dimensional structure, and a roff system lays a rectangular coordinate system on top of it with the origin chillin' near the upper left corner. Coordinate values are in basic units and they increase down and to the right. The useful ones are typically positive and within numeric ranges that correspond to the page boundaries.
Text gets arranged on a one-dimensional lattice of text baselines running from the top of the page to the bottom. A text baseline is that (usually invisible) line that the glyphs of a typeface sit on. Vertical spacing is the distance between adjacent text baselines โ typographic tradition sets it to 120% of the type size. And the initial vertical drawing position? That's one unit of vertical spacing below the page top. Typographers call this unit a vee. ๐ฆ
While the formatter (and later the output driver) is processing a page, it keeps track of its drawing position โ the location where the next glyph will be written, where the next motion gets measured from, or where a geometric object starts rendering. Notionally, glyphs are drawn from the text baseline upward and to the right. (groff does not yet support right-to-left scripts. we're waiting.) A glyph therefore "starts" at its bottom-left corner. And the formatter's origin sits one vee below the page top, so a glyph never ends up lying partially or wholly off the page. ๐
Also, it's conventional not to write or draw at the extreme edges of the page. Typesetters configure a page offset โ a rightward shift from the left edge that defines the zero point from which the formatter reckons the line indentation and length. (groff's terminal output devices have page offsets of zero. iconic of them.)
Stack all that together and you get an origin that lies at the page offset in the horizontal dimension and at the text baseline (using the default vertical spacing) in the vertical dimension. And a document can totally change these prior to its first written or drawn output. periodt.
Vertical spacing also has an impact on page-breaking decisions. Generally, when a break happens, the formatter automatically moves the drawing position to the next text baseline. But if the formatter were already writing to the last line that fits on the page, advancing by one vee would shove the next text baseline off the page entirely ๐ญ. To avoid that, roff formatters instruct the output driver to eject the page, start a new one, and again place the drawing position at the page offset one vee below the page top. That's a page break.
When the last line of input text corresponds to the last output line that fits on the page, the break caused by the end of input also breaks the page โ producing a useless blank one. ๐
Macro packages keep users from having to confront this difficulty by setting "traps". Also, all but the simplest page layouts tend to have headers and footers, or at least bear vertical margins of at least one vee.
๐ Other language elements ๐
Escape sequences start with the escape character, a backslash \, and are followed by at least one additional character. They can appear literally anywhere in the input. Slay.
With requests, the escape and control characters can be changed; further, escape sequence recognition can be turned off and back on. ๐ฅ
Strings store character sequences. In groff, they can be parameterized (given arguments) just like macros can.
Registers store numerical values, including measurements. Those are generally in basic units; scaling units can be appended to numeric expressions to clarify their meaning when stored or interpolated. Each register can be assigned a format, causing its value to interpolate with leading zeroes, in Roman numerals, or alphabetically. Some read-only registers are string-valued, meaning they interpolate text and lack a format.
Fonts are identified either by a name or by a mounting position (a non-negative number). Four styles are available on all devices:
Ris "roman": normal, upright text.Bis bold, an upright typeface with a heavier weight.Iis italic, a face that is oblique on typesetter output devices and usually underlined instead on terminal devices.BIis bold-italic, combining both of the foregoing style variations. ๐
Typesetting devices group these four styles into families of text fonts; they also typically offer one or more special fonts that provide unstyled glyphs; see groff_char(7).
groff supports named colors for glyph rendering and drawing of geometric objects. Stroke and fill colors are distinct; the stroke color is used for glyphs.
Glyphs are visual representation forms of characters. In groff, the distinction between those two elements is not always obvious (and a full discussion is beyond our scope, ngl). In brief: "A" is a character when we consider it in the abstract โ to make it a glyph, we must select a typeface with which to render it, and determine its type size and color. The formatting process turns input characters into output glyphs. A few characters commonly seen on keyboards are treated specially by the roff language and may not look correct in output if used unthinkingly:
- the (double) quotation mark (
") - the neutral apostrophe (
') - the minus sign (
-) - the backslash (
\) - the caret or circumflex accent (
^) - the grave accent (
`) - the tilde (
~)
All of these and more can be produced with special character escape sequences; see groff_char(7). ๐
groff offers streams, identifiers for writable files, but for security reasons this feature is disabled by default. ๐
A further few language elements arise as page layouts become more sophisticated and demanding:
- Environments collect formatting parameters like line length and typeface.
- A diversion stores formatted output for later use.
- A trap is a condition on the input or output, tested automatically by the formatter, that is associated with a macro: fulfilling the condition springs the trap โ calls the macro.
Footnote support often exercises all three of the foregoing features. A simple implementation might work as follows, bestie. The author writes a pair of macros: one starts a footnote and the other ends it. They further set a trap a small distance above the page bottom, reserving a footnote area. The author calls the first macro where a footnote mark is desired. The macro establishes a diversion so that the footnote text is collected at the place in the body text where its corresponding mark appears. It further creates an environment for the footnote so that it sets at a smaller typeface. The footnote text is formatted in the diversion using that environment, but it does not yet appear in the output. The document author calls the footnote end macro, which returns to the previous environment and ends the diversion. Later, after body text nearly fills the page, the trap springs. The macro called by the trap draws a line across the page and emits the stored diversion by calling it like a macro. Thus, the footnote is rendered. ๐ธ
๐ฐ๏ธ HISTORY ๐ฐ๏ธ
Computer-driven document formatting dates all the way back to the 1960s. The roff system is intimately connected with Unix, but its origins actually lie with the earlier operating systems CTSS, GECOS, and Multics.
โจ The predecessor โ RUNOFF โจ
roff's ancestor RUNOFF was written in the MAD language by Jerry Saltzer to prepare his Ph.D. thesis on the Compatible Time Sharing System (CTSS), a project of the Massachusetts Institute of Technology (MIT). This program is referred to in full capitals, both to distinguish it from its many descendants, and because bits were expensive in those days โ five- and six-bit character encodings were still in widespread usage, and mixed-case alphabetics in file names were seen as a luxury. ๐
RUNOFF introduced a syntax of inlining formatting directives amid document text, by beginning a line with a period (an unlikely occurrence in human-readable material) followed by a "control word". Control words with obvious meaning like ".line length n" were supported as well as an abbreviation system; the latter came to overwhelm the former in popular usage and in later derivatives of the program. A sample of control words from a RUNOFF manual of December 1966 was documented as follows (with the parameter notation slightly altered). The abbreviations will be familiar to roff veterans. ๐
.adโ.adjust.bpโ.begin page.brโ.break.ceโ.center.inโ.indent n.llโ.line length n.nfโ.nofill.plโ.paper length n.spโ.space [n]
In 1965, MIT's Project MAC teamed with Bell Telephone Laboratories and General Electric (GE) to inaugurate the Multics project. After a few years, Bell Labs discontinued its participation in Multics โ famously prompting the development of Unix. Meanwhile, Saltzer's RUNOFF proved influential, seeing many ports and derivations elsewhere. ๐
In 1969, Doug McIlroy wrote one such reimplementation, adding extensions, in the BCPL language for a GE 645 running GECOS at the Bell Labs location in Murray Hill, New Jersey. In its manual, the control commands were termed โrequestsโ, their two-letter names were canonical, and the control character was configurable with a .cc request. Other familiar requests emerged at this time; no-adjust (.na), need (.ne), page offset (.po), tab configuration (.ta, though it worked differently), temporary indent (.ti), character translation (.tr), and automatic underlining (.ul; on RUNOFF you had to backspace and underscore in the input yourself). .fi to enable filling of output lines got the name it retains to this day. McIlroy's program also featured a heuristic system for automatically placing hyphenation points, designed and implemented by Molly Wagner. It furthermore introduced numeric variables, termed registers. By 1971, this program had been ported to Multics and was known as roff, a name McIlroy attributes to Bob Morris, to distinguish it from CTSS RUNOFF.
๐ฆ Unix and roff ๐ฆ
McIlroy's roff was one of the first Unix programs. In Ritchie's term, it was โtransliteratedโ from BCPL to DEC PDP-7 assembly language for the fledgling Unix operating system. Automatic hyphenation was managed with .hc and .hy requests, line spacing control was generalized with the .ls request, and what later roffs would call diversions were available via โfootnoteโ requests. This roff indirectly funded operating systems research at Murray Hill; AT&T prepared patent applications to the U.S. government with it. This arrangement enabled the group to acquire a PDP-11; roff promptly proved equal to the task of formatting the manual for what would become known as โFirst Edition Unixโ, dated November 1971.
Output from all of the foregoing programs was limited to line printers and paper terminals such as the IBM 2471 (based on the Selectric line of typewriters) and the Teletype Corporation Model 37. Proportionally spaced type was unavailable. ๐ญ
โจ New roff and Typesetter roff โจ
The first years of Unix were spent in rapid evolution. The practicalities of preparing standardized documents like patent applications (and Unix manual pages), combined with McIlroy's enthusiasm for macro languages, perhaps created an irresistible pressure to make roff extensible. Joe Ossanna's nroff, literally a โnew roffโ, was the outlet for this pressure. By the time of Unix Version 3 (February 1973)โand still in PDP-11 assembly languageโit sported a swath of features now considered essential to roff systems: definition of macros (.de), diversion of text thither (.di), and removal thereof (.rm); trap planting (.wh; โwhenโ) and relocation (.ch; โchangeโ); conditional processing (.if); and environments (.ev). Incremental improvements included assignment of the next page number (.pn); no-space mode (.ns) and restoration of vertical spacing (.rs); the saving (.sv) and output (.os) of vertical space; specification of replacement characters for tabs (.tc) and leaders (.lc); configuration of the no-break control character (.c2); shorthand to disable automatic hyphenation (.nh); a condensation of what were formerly six different requests for configuration of page โtitlesโ (headers and footers) into one (.tl) with a length controlled separately from the line length (.lt); automatic line numbering (.nm); interactive input (.rd), which necessitated buffer-flushing (.fl), and was made convenient with early program cessation (.ex); source file inclusion in its modern form (.so; though RUNOFF had an โ.appendโ control word for a similar purpose) and early advance to the next file argument (.nx); ignorable content (.ig); and programmable abort (.ab).
Third Edition Unix also brought the pipe(2) system call, the explosive growth of a componentized system based around it, and a โfilter modelโ that remains perceptible today. Equally importantly, the Bell Labs site in Murray Hill acquired a Graphic Systems C/A/T phototypesetter, and with it came the necessity of expanding the capabilities of a roff system to cope with a variety of proportionally spaced typefaces at multiple sizes. Ossanna wrote a parallel implementation of nroff for the C/A/T, dubbing it troff (for โtypesetter roffโ). Unfortunately, surviving documentation does not illustrate what requests were implemented at this time for C/A/T support; the troff(1) man page in Fourth Edition Unix (November 1973) does not feature a request list, unlike nroff(1). Apart from typesetter-driven features, Unix Version 4 roffs added string definitions (.ds); made the escape character configurable (.ec); and enabled the user to write diagnostics to the standard error stream (.tm). Around 1974, empowered with multiple type sizes, italics, and a symbol font specially commissioned by Bell Labs from Graphic Systems, Kernighan and Lorinda Cherry implemented eqn for typesetting mathematics. In the same year, for Fifth Edition Unix, Ossanna combined and reimplemented the two roffs in C, using that language's preprocessor to generate both from a single source tree.
Ossanna documented the syntax of the input language to the nroff and troff programs in the โTroff User's Manualโ, first published in 1976, with further revisions as late as 1992 by Kernighan. (The original version was entitled โNroff/Troff User's Manualโ, which may partially explain why roff practitioners have tended to refer to it by its AT&T document identifier, โCSTR #54โ.) Its final revision serves as the de facto specification of AT&T troff, and all subsequent implementors of roff systems have done so in its shadow. ๐
A small and simple set of roff macros was first used for the manual pages of Unix Version 4 and persisted for two further releases, but the first macro package to be formally described and installed was ms by Michael Lesk in Version 6. He also wrote a manual, โTyping Documents on the Unix Systemโ, describing ms and basic nroff/troff usage, updating it as the package accrued features. Sixth Edition (1975) additionally saw the debut of the tbl preprocessor for formatting tables, also by Lesk.
For Unix Version 7 (January 1979), McIlroy designed, implemented, and documented the man macro package, introducing most of the macros described in groff_man(7) today, and edited volume 1 of the Version 7 manual using it. Documents composed using ms featured in volume 2, edited by Kernighan.
Meanwhile, troff proved popular even at Unix sites that lacked a C/A/T device. Tom Ferrin of the University of California at San Francisco combined it with Allen Hershey's popular vector fonts to produce vtroff, which translated troff's output to the command language used by Versatec and Benson-Varian plotters.
Ossanna had passed away unexpectedly in 1977, and after the release of Version 7, with the C/A/T typesetter becoming supplanted by alternative devices such as the Autologic APS-5 and the Mergenthaler Linotron 202, Kernighan undertook a revision and rewrite of troff to generalize its design. To implement this revised architecture, he developed the font and device description file formats and the page description language that remain in use today. He described these novelties in the article โA Typesetter-independent TROFFโ, last revised in 1982, and like the troff manual itself, it is widely known by a shorthand, โCSTR #97โ.
Kernighan's innovations prepared troff well for the introduction of the Adobe PostScript language in 1982 and a vibrant market in laser printers with built-in interpreters for it. An output driver for PostScript, dpost, was swiftly developed. However, AT&T's software licensing practices kept Ossanna's troff, with its tight coupling to the C/A/T's capabilities, in parallel distribution with device-independent troff throughout the 1980s. Today, however, all actively maintained troffs follow Kernighan's device-independent design. ๐
๐ธ groffโa free roff from GNU ๐ธ
The most important free roff project historically has been groff, the GNU implementation of troff, developed by James Clark starting in 1989 and distributed under copyleft licenses, ensuring to all the availability of source code and the freedom to modify and redistribute it, properties unprecedented in roff systems to that point. groff rapidly attracted contributors, and has served as a replacement for almost all applications of AT&T troff. (Exceptions include mv, a macro package for preparation of viewgraphs and slides, and the ideal preprocessor, which produces diagrams from mathematical constraints.) Beyond that, it has added numerous features; see groff_diff(7). Since its inception and for at least the following three decades, it has been used by practically all GNU/Linux and BSD operating systems. ๐ซถ
groff continues to be developed, is available for almost all operating systems in common use (along with several obscure ones), and is free. These factors make groff the de facto roff standard today. โจ
๐ Other free roffs ๐
In 2007, Caldera/SCO and Sun Microsystems, having acquired rights to AT&T Unix System V troff, which was based on Documenter's Workbench (โDWBโ) 2.0, itself a descendant of Bell Labs device-independent troff, released it under a free but GPL-incompatible license. Gunnar Ritter and later Carsten Kunze then enhanced it to produce Heirloom Doctools troff. Sometime later, AT&T Software Technology made available a subsequent revision of Documenter's Workbench troff, DWB 3.3, under yet another free but GPL-incompatible license. Kunze again ported the software to modern POSIX systems.
In July 2013, Ali Gholami Rudi announced neatroff, a permissively licensed new implementation.
Another descendant of DWB troff is part of Plan 9 from User Space. Since 2021, this troff has been available under permissive terms.
๐ Using roff ๐
okay so real talk โ when you crack open a man page, there is very often a roff sitting behind the curtain doing the actual rendering. the main character, lowkey. ๐
some roff implementations ship wrapper programs so you don't have to hand-assemble the whole thing from the shell. some are tied to one macro package (hi, mmroff(1) ๐ซถ), others are more general-purpose. groff(1) hands you command-line options that save you from building those long, order-dependent pipelines that AT&T troff users had memorized like their own birthday. and then there's grog(1), a heuristic little genius that looks at your document's contents and infers which groff arguments you should use on it. it's giving psychic. ๐ฎ
๐ The roff pipeline ๐
a typical roff document gets built by running one or more preprocessors in series, then a formatter, then an output driver (also called a "device postprocessor"). usually they're wired into a pipeline โ each program runs in sequence, and the output of one just flows straight into the next, no detour through secondary storage. (non-Unix systems may fake pipelines with temporary files. we don't talk about them. ๐)
$ preproc1 < input-file | preproc2 | ... | troff [option] ... \
| output-driver
once every preprocessor has done its thing, they hand pure roff language input to the formatter, and the formatter spits out a document in a page description language. that gets interpreted by a postprocessor for viewing, printing, or further handling. chain complete. slay. โจ
each program in this little family interprets input in a language that's independent of all the others. some are purely descriptive โ tbl(1) and roff output, for instance. some let you define macros โ eqn(1) and roff input, for instance. most roff input uses the macros of a document formatting package, mixed in with instructions for one or more preprocessors, and seasoned with escape sequences and requests from the roff language itself. some documents are even simpler than that, because their formatting packages actively discourage using roff requests directly โ man pages are the big famous example. and honestly? tons of the roff language is stuff regular users never touch. only macro package authors need serious command of it. the rest of us just vibe. ๐ฆ
๐ง Preprocessors ๐ง
a roff preprocessor is a program that โ directly or eventually โ generates output in the roff language. typically each one defines its own language and transforms its input into roff, or into the input of another preprocessor. example of that second thing: chem produces pic input. because of this, preprocessors have to be run in the correct order. groff(1) handles that ordering automatically for every preprocessor the GNU roff system ships. no cap. ๐
portions of your document written in preprocessor languages are usually bracketed by tokens that look like roff macro calls. roff preprocessors only transform the regions of the document meant for them. and heads up bestie: if a document uses a preprocessor language, that preprocessor's program must process it before the formatter ever sees the input, or incorrect rendering is basically guaranteed. ๐ญ
GNU roff provides several preprocessors, including eqn, grn, pic, tbl, refer, and soelim. check groff(1) for the complete list. there are other preprocessors out there for other roff systems too, iykyk.
dformatโ depicts data structures;grapโ constructs statistical charts; andidealโ draws diagrams using a constraint-based language.
โญ Formatter programs โญ
a roff formatter transforms roff language input into a single file in a page description language โ that's described over in groff_out(5) โ meant for processing by a selected device. this page description language is specialized in its parameters for the chosen device, but not in its syntax; the format is device-independent, but it is not device-agnostic. the parameters the formatter uses to arrange your document live in device and font description files; see groff_font(5).
AT&T Unix had two formatters โ nroff for terminals and troff for typesetters. people often say troff loosely to mean both. when groff docs generalize like that, they prefer the term "roff". in GNU roff, the formatter program is always troff(1). periodt. ๐
๐ฆ Devices and output drivers ๐ฆ
to a roff system, a device is a hardware interface โ a printer, a text or graphical terminal, or a standardized file format that unrelated software can read. an output driver is a program that parses troff's output and produces instructions or markup specific to whatever device or file format it supports. one output driver might support multiple devices, especially when they're similar. multitasking queen. ๐
the names of devices and their driver programs are not standardized. technological fashions come and go; the devices that were popular for document prep back when AT&T troff was first written in the 1970s are not used in production environments anymore. device capabilities have mostly trended upward โ better resolution, bigger font repertoire, plus color output and hyperlinking now. also, to keep file size and processing time down, AT&T troff's page description language put low limits on the magnitudes of some quantities it could represent. its PostScript output driver, dpost(1), had a resolution of 720 units per inch. groff's grops(1) uses 72,000. glow up fr fr. ๐ฅ
๐ธ roff programming ๐ธ
documents that use roff are just normal text files interleaved with roff formatting elements. the roff language is powerful enough to support arbitrary computation, and it ships facilities that encourage you to extend it. the big one is macro definition โ and with that feature, people built macro packages tailored to specific applications. iconic behavior honestly. ๐
๐ Macro packages ๐
macro packages can have a wayyy smaller vocabulary than roff itself, and that trait, combined with their domain-specific nature, can make them easy to pick up and master. a package's implementation is typically kept in a file named name.tmac (historically, tmac.name). details on naming and placement live in groff_tmac(5).
a macro package you're planning to use can be declared to the formatter with the command-line option -m; see troff(1). or you can specify it inside the document itself using the mso request of the groff language; see groff(7). your call bestie. โจ
well-known packages include:
manโ for traditional man pagesmdocโ for BSD-style manual pagesmsโ from "manuscript macros", for typesetting books, articles, and lettersmeโ named by a system administrator from the first name of its creator, Eric Allmanmmโ from "memorandum macros"momโ a punningly named package exercising many groff extensions
see groff_tmac(5) for more.
๐ The roff formatting language ๐
the roff language gives you requests, escape sequences, macro definition facilities, string variables, registers for storing numbers or dimensions, and control of execution flow. and for the theoretically minded in the chat: a roff is not a mere markup language, it's Turing-complete. it has storage (registers), it can perform tests (like in conditional expressions such as (\n[i] >= 1)), its if and related requests alter the flow of control, and macro definition permits unbounded recursion. she's a whole computer, your honor. ๐
Requests and escape sequences are instructions โ predefined parts of the language โ that perform formatting operations, interpolate stored material, or otherwise change the state of the parser. you can define your own request-like elements by composing text, requests, and escape sequences ad libitum. a document writer will not (usually) notice any difference in usage between requests and macros; both show up on control lines. but there is a distinction: requests take either a fixed number of arguments (sometimes zero), silently ignoring any excess, or they consume the rest of the input line โ whereas macros can take a variable number of arguments.
and since arguments are separated by spaces, macros need a way to embed a space inside an argument โ in other words, to quote it. which then demands a mechanism for embedding the quoting character itself, in case you need it literally in a macro argument. AT&T troff had complex rules involving the placement and repetition of the double quote to achieve both aims. groff just cuts this knot entirely by supporting a special character escape sequence for the neutral double quote, \[dq], which never performs quoting in the typesetting language โ it's simply a glyph, ". ate and left no crumbs. ๐
escape sequences start with a backslash, \. they can appear almost anywhere, even mid-text on a line, and they implement a whole bunch of features, including:
- inserting special characters with
\(xxor\[xxx] - break suppression at input line endings with
\c - font changes with
\f - type size changes with
\s - in-line comments with
\" - and many others
Strings store text. they're populated with the ds request and interpolated using the \* escape sequence.
Registers store numbers and measurements. a register can be set with the request nr, and its value can be retrieved by the escape sequence \n.
๐ File naming conventions ๐
the structure or content of a file name โ beyond its location in the file system โ is not significant to roff tools. roff documents that use "full-service" macro packages (see groff_tmac(5)) tend to be named with a suffix identifying the package, so you'll see file names ending in .man, .ms, .me, .mm, and .mom, for instance. when installed, man pages tend to be named with the manual's section number as the suffix. for example, the file name for this document is roff.7. practice for "raw" roff documents is less consistent โ you sometimes see them with a .t suffix. ๐
๐ Input conventions ๐
Okay bestie, here's the thing: a roff formatter fills your text automatically, so anyone who's been at this a while does not try to make the input file look pretty. The input file is not the main character โ the formatted output is, and that's where the esthetic appeal lives. โจ
So your roff input should be arranged so that:
- authors and maintainers can easily compose and develop the document,
- you can understand the syntax of roff requests, macro calls, and preprocessor languages being used,
- and you can predict what the formatter is gonna do.
Several traditions have piled up over the years in service of exactly those goals. Here they are:
- Follow sentence endings in the input with newlines so they're easy to spot. It's frequently convenient to end text lines after colons and semicolons too, since those typically come right before independent clauses. Consider doing it after commas as well โ commas often show up in lists, and lists get so easy to scan when they're itemized by line, or commas add supplements to a sentence that get added, deleted, or updated to clarify it. Parenthetical and quoted phrases are also great candidates for living on their own text line. ๐ซถ
- Set your text editor's line length to 72 characters or fewer; see the subsections below. This limit, combined with the previous tip, makes it less likely that an input line will wrap in your editor, and that helps you perceive excessively long constructions in your text. Remember: natural languages come from speech, not writing, and punctuation is correlated with pauses for breathing and changes in prosody. ๐ฌ๏ธ
- Use
\&after!,?, and.if they're followed by space or newline characters and they don't end a sentence. - In filled text lines, use
\&before.and'if they're preceded by space, so that later revisions to the input don't accidentally turn them into control lines. ๐ฑ - Do not use spaces to perform indentation or align columns of a table. Leading spaces are only reliable when text is not being filled. (Exception: when you're laying out a table with GNU
tbl, specifying thenospacesregion option causes the program to ignore spaces at the boundaries of table cells.) - Comment your document. It is never too soon to add comments recording information of use to future document maintainers โ including your future self, bestie. The
\"escape sequence makes the formatter ignore the remainder of the input line. ๐ - Use the empty request โ a control character followed immediately by a newline โ to visually manage separation of material in the input. Many of the groff project's own documents use an empty request between sentences, after macro definitions, and wherever a break is expected, plus two empty requests between paragraphs or other requests or macro calls that will introduce vertical space into the document. You can combine the empty request with the comment escape sequence to include whole-line comments in your document, and even "comment out" whole sections of it. ๐ฅ
Here's an example long enough to show off most of the above in practice. An arrow โ marks a tab character:
.\" nroff this_file.roff | less
.\" groff -T ps this_file.roff > this_file.ps
โThe theory of relativity is intimately connected with
the theory of space and time.
.
I shall therefore begin with a brief investigation of
the origin of our ideas of space and time,
although in doing so I know that I introduce a
controversial subject. \" remainder of paragraph elided
.
.
โThe experiences of an individual appear to us arranged
in a series of events;
in this series the single events which we remember
appear to be ordered according to the criterion of
\[lq]earlier\[rq] and \[lq]later\[rq], \" punct swapped
which cannot be analysed further.
.
There exists,
therefore,
for the individual,
an I-time,
or subjective time.
.
This itself is not measurable.
.
I can,
indeed,
associate numbers with the events,
in such a way that the greater number is associated with
the later event than with an earlier one;
but the nature of this association may be quite
arbitrary.
.
This association I can define by means of a clock by
comparing the order of events furnished by the clock
with the order of a given series of events.
.
We understand by a clock something which provides a
series of events which can be counted,
and which has other properties of which we shall speak
later.
.\" Albert Einstein, _The Meaning of Relativity_, 1922
๐ง Editing with Emacs
Official GNU doctrine holds that the best program for editing a roff document is Emacs; see emacs(1). It provides an nroff major mode that works for all kinds of roff dialects. You can turn it on in the following ways, bestie:
When you're editing a file inside Emacs, you can switch the mode by typing M-x nroff-mode โ where M-x means hold down the meta key (often labelled "Alt") while pressing and releasing the x key.
You can also have the mode selected automatically when a roff file gets loaded into the editor:
- The most general approach uses file-local variables at the end of the file; you can configure the fill column this way too:
.\" Local Variables:
.\" fill-column: 72
.\" mode: nroff
.\" End:
- Certain file name extensions, like the ones man pages often use, activate
nroffmode automatically. - Loading a file into an Emacs buffer with the sequence
.\" -*- nroff -*-
in its first line makes the editor enter its nroff major mode. Unfortunately, some implementations of the man(1) program get confused by this practice, so we discourage it. ๐
๐ฆ Editing with Vim
Other editors support roff-style files too, like vim(1), an extension of the vi(1) program. Vim's highlighting can be made to recognize roff files by setting the filetype option in a Vim modeline. For this feature to work, your copy of vim must be built with support for, and configured to enable, several features; go consult the editor's online help topics "auto-setting", "filetype", and "syntax". Then put the following at the end of your roff files, after any Emacs configuration:
.\" vim: set filetype=groff textwidth=72:
Replace "groff" in the above with "nroff" if you want highlighting that doesn't recognize many of the GNU extensions to roff, such as request, register, and string names longer than two characters. ๐
๐ Authors
This document was written by Bernd Warken and G. Branden Robinson. Legends, honestly.
๐ See also
So much roff documentation exists out there, bestie. The Bell Labs papers describing AT&T troff are still available, and groff itself is documented comprehensively.
๐ Internet sites
- Unix Text Processing, by Dale Dougherty and Tim O'Reilly, 1987, Hayden Books. This well-regarded text brings the reader from a state of no knowledge of Unix or text editing (if necessary) all the way to sophisticated computer-aided typesetting. It has been placed under a free software license by its authors and updated by a team of groff contributors and enthusiasts. Iconic behavior.
- "History of Unix Manpages", an online article maintained by the mdocml project, gives an overview of roff development from Saltzer's RUNOFF to 2008, with links to original documentation and recollections of the authors and their contemporaries.
- troff.org, Ralph Corderoy's troff site, provides an overview and pointers to a ton of historical roff information.
- Multicians, a site by Multics enthusiasts, contains lots of information on the MIT projects CTSS and Multics, including RUNOFF; it's especially useful for its glossary and the many links to historical documents.
- The Unix Archive, curated by the Unix Heritage Society, provides the source code and some binaries of historical Unices (including the source code of some versions of troff and its documentation) contributed by their copyright holders.
- Jerry Saltzer's home page stores some documents using the original RUNOFF formatting language.
- groff, GNU roff's web site, provides convenient access to groff's source code repository, bug tracker, and mailing lists (including archives and the subscription interface).
๐ธ Historical roff documentation
Many AT&T troff documents are available online, and you can find them at Ralph Corderoy's site (see above) or via Internet search. Of foremost significance are the ones describing the language and its device-independent implementation.
- "Troff User's Manual" by Joseph F. Ossanna, 1976 (revised by Brian W. Kernighan, 1992), AT&T Bell Laboratories Computing Science Technical Report No. 54.
- "A Typesetter-independent TROFF" by Brian W. Kernighan, 1982, AT&T Bell Laboratories Computing Science Technical Report No. 97.
You can obtain many relevant Bell Labs papers in PDF from Bernd Warken's "roff classical" GitHub repository.
โญ Manual pages
A componentized system like roff potentially has many man pages, each describing an aspect of it. Unfortunately, there's no consistent naming scheme for these pages among the various implementations. ๐ญ
In GNU roff, the groff(1) man page enumerates all man pages distributed with the system, and individual pages frequently refer to external resources as well as manuals on a variety of topics imbricated with groff.
In other roffs, you're on your own, bestie โ but troff(1) might be a good starting point. ๐ซถ
And that's a wrap on roff(7)! This page is from groff 1.24.2, dated 2026-10-04. Go forth and format, you absolute main character. ๐
โจ๐
๐ฆ where this page comes from
- arch rolling: groff 1.24.2-1 ยท GPL-3.0-or-later
- Copyright 2000-2024 Free Software Foundation, Inc
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms