groff_diff(7)
π NAME π
groff_diff(7) β differences between GNU roff and AT&T troff, straight from the Miscellaneous Information Manual. π
πΈ DESCRIPTION πΈ
Okay so GNU roff text processing system, groff, is a reimplementation and extension of AT&T troff, the typesetting system originating in Unix systems of the 1970s. groff removes many arbitrary limitations and adds features, both to the input language and to the page description language output by the troff formatter. We also note here differences arising from groff's implementation of AT&T troff features. The following discussion assumes familiarity with those features; see roff(7) for background. GNU troff can operate in a manner that increases support for documents written for AT&T troff; see section βCompatibility modeβ below. π¦
β¨ LANGUAGE β¨
GNU troff features identifiers of arbitrary length; supports color output, non-integral type sizes, user-defined characters, and automatic hyphenation in languages other than English; adds more conditional expression operators; recognizes additional scaling units and arithmetic operators; enables general file I/O (in βunsafe modeβ only); and exposes more formatter state. π
π¦ Long names π¦
GNU troff introduces many new requests; with three exceptions (cp, do, rj), they have names longer than two characters. The names of registers, fonts, strings/macros/diversions, environments, special characters, character classes, streams, hyphenation language codes, and colors can be of any length. Anywhere AT&T troff supports a parameterized escape sequence that uses an opening parenthesis ( to introduce a two-character argument, groff supports a square-bracketed form [] where the argument within can be of arbitrary length. β¨
π Font families, abstract styles, and translation π
GNU troff can group text typefaces into families. For example, groff ships with support for families containing each of the styles βRβ, βIβ, βBβ, and βBIβ (roman [upright], bold, italic [slanted], and bold-italic). So that a document need not be coupled to a specific font family, an output device can associate a style in the abstract sense with a mounting position. Thus the default family can combine with a style dynamically, producing a resolved font name. A document can translate, or remap, font names with the ftr request. π«Ά
Applying the requests cs, bd, tkf, uf, or fspecial to an abstract style affects the member of the default family corresponding to that style. The default family can be set with the fam request or -f command-line option. The styles directive in the output device's DESC file controls which mounting positions (if any) are initially associated with abstract styles rather than fonts, and the sty request can update this association. π
π Colors π
groff supports color output with a variety of color spaces and up to 16 bits per channel. Some devices, particularly terminals, may be more limited. When color support is enabled, two colors are current at any given time: the stroke color, with which glyphs, rules (lines), and geometric figures are drawn, and the fill color, which paints the interior of filled geometric figures. The color, defcolor, gcolor, and fcolor requests; \m and \M escape sequences; and .color, .m, and .M registers exercise color support. π
π Hyphenation π
GNU troff uses a hyphenation algorithm and language-specific pattern files (based on TeX's) to decide which words can be hyphenated and where. AT&T troff's hyphenation system (βsuftabβ) was specific to English. π§
New requests permit finer control over hyphenation breaking; hyphenation of a word might be suppressed due to a limit on consecutive hyphenated lines (hlm), a minimum line length threshold (hym), or because the line can instead be adjusted with additional inter-word space (hys). The hla request selects a hyphenation language, whereas hpf and hpfa respectively load and append to the language's hyphenation patterns. If no hyphenation language is set or no patterns are loaded, GNU troff does not perform automatic hyphenation. πΈ
For automatic hyphenation to work, the formatter must know which letters are equivalent. For example, the letter βEβ behaves like βeβ; only the latter typically appears in hyphenation pattern files. GNU troff expects characters that participate in automatic hyphenation to be assigned hyphenation codes that define these equivalence classes. At startup, GNU troff assigns hyphenation codes to the letters βaβββzβ, applies the same codes to βAβββZβ in one-to-one correspondence, and assigns a code of zero to all other characters. β
The hcode request enables application of hyphenation codes to characters outside the Unicode basic Latin set; without doing so, words containing such letters won't hyphenate properly even if the corresponding hyphenation patterns contain them. Localization files for the input character set and language configure hyphenation codes; see groff_tmac(5). π¦
GNU troff's \: escape sequence works like \% but produces no hyphen if the word breaks at that location. π
π₯ Fractional type sizes and new scaling units π₯
When configuring the type size, AT&T troff ignored scaling units and interpreted all measurements in points. Combined with integer arithmetic, this design choice made it impossible to support, for instance, ten-and-a-half-point type. In GNU troff an output device can select a scaling factor that subdivides a point into βscaled pointsβ. A type size expressed in scaled points can thus represent a non-integral size in points. π
A scaled point, scaling unit s, is equal to 1/sizescale points, where the device description file, DESC, specifies sizescale and otherwise defaults to 1; see groff_font(5). GNU troff also defines the typographical point, scaling unit z, which explicitly specifies a type size of potentially non-integral measure. The program multiplies typographical points by sizescale and converts the value to an integer. Arguments GNU troff interprets in z units by default comprise those to the escape sequences \H and \s, to the request ps, the third argument to the cs request, and the second and fourth arguments to the tkf request. In GNU troff, the register \n[.s] interpolates the type size in typographical points (z), whereas the register \n[.ps] interpolates it in scaled points (s). β\n[.ps]sβ, β\n[.s]zβ, and β1mβ are co-equal by definition. π
For example, if sizescale is 1000, then a scaled point is one thousandth of a point. Consequently, β.ps 10.5β is synonymous with β.ps 10.5zβ; both set the type size to 10,500 scaled points or 10.5 typographical points. β¨
It makes no sense to use the βzβ scaling unit in a numeric expression whose default scaling unit is neither βuβ nor βzβ, so GNU troff disallows this. Similarly, it is nonsensical to use scaling units other than βpβ, βsβ, βzβ, or βuβ, in a numeric expression whose default scaling unit is βzβ, and so GNU troff disallows those as well. π«Ά
Output devices may be limited in the type sizes they can employ. The .s and .ps registers represent the type size selected by the formatter as it understands a device's capability. The read-only registers .psr and (string-valued) .sr interpolate the last requested in scaled points and in points as a decimal fraction, respectively. Like the actual current and previous type size, the requested ones are properties of an environment. π
For example, if a document requests a type size of 10.95 points, and the nearest size permitted by a sizes request (or by the sizes or sizescale directives in the device's DESC file) is 11 points, groff uses the latter value. π
A further two new measurement units available in groff are βMβ, which indicates hundredths of an em, and βfβ, which multiplies by 65,536. The latter provides convenient fractions for color definitions with the defcolor request. For example, 0.5f equals 32768u. π
π Special fonts π
GNU troff's βspecialβ and fspecial requests permit a document to supplement the set of fonts the device configures for glyph search without having to use the fp request to manipulate the list of mounting positions, which can be tediousβby default, GNU troff mounts 40 fonts at startup when using the ps device. π¦
β Numeric expressions β
GNU troff permits spaces in a numeric expression within parentheses, and offers three new operators. π
e1>?e2β Interpolate the greater of expressionse1ande2.e1<?e2β Interpolate the lesser of expressionse1ande2.(c;e)β Interpolate expressioneusingcas the default scaling unit, ignoring scaling units ineifcis empty.
Arithmetic in GNU troff saturates instead of wrapping. π₯
π¦ Conditional expressions π¦
More conditions can be tested with the βifβ and ie requests, as well as the new βwhileβ request. π«Ά
c chrβ True if a characterchris available;chris an ordinary, special, or indexed character, whether defined by a font description file or a request.d namβ True if a string, macro, diversion, or requestnamis defined.F fntβ True if a fontfntis available;fntcan be an abstract style or a font name.fntis handled as if it were an argument to theftrequest (that is, the default family is combined with an abstract style and font translation is applied), butfntcannot be a mounting position, and no font is mounted.m colβ True if a colorcolis defined.r regβ True if a registerregis defined.S styβ True if an abstract stylestyis registered. Font translations apply.vβ Always false. This condition exists for compatibility with certain other troff implementations. (We refer tovtroff, a translator that converted the C/A/T command stream produced by early-vintage AT&T troff to a form suitable for Versatec and Benson-Varian plotters.)
πΈ Drawing commands πΈ
GNU troff extends the \D escape sequence with drawing commands to create filled circles and ellipses, and polygons. Stroked (outlined) objects are drawn with the stroke color and filled (solid) ones shaded with the fill color. These are independent properties; if you want a filled, stroked figure, you must draw the same figure twice using each command. A filled figure is smaller than a stroked one using the same parameters because the former is drawn only within its defined area, whereas strokes have a line thickness, set with another new drawing command. π
Notational conventions π
Okay so here's the vibe for all the request and escape sequence descriptions below: GNU troff reads arguments named character-sequence, command, contents, file, and message in copy mode until the end of the input line. A character-sequence is literally one or more ordinary, special, or indexed characters; spaces; or escape sequences that interpolate only these. We name the remaining arguments for clarity, but bestie, they're also character-sequences.
A neutral double quote β"β can optionally prefix a character-sequence; the formatter discards one if present, permitting initial embedded spaces in the argument.
input means arbitrary character sequences β up to a newline or delimiter β that GNU troff fully interprets, in contrast to copy mode. Slay, that's the distinction. β¨
Escape sequences β¨
groff introduces several new escape sequences, extends the syntax of the AT&T troff escape sequences \D, \f, \k, \n, \s, \$, and \*, and alters the behavior of \X. The following list collates escape sequences alphabetically at first, and then by symbol roughly in Unicode code point order. Neutral apostrophes ' illustrate escape sequences with a user-selectable delimiter. Many others are available; see subsection βMiscellaneousβ and section βCompatibility Modeβ below.
\A'input'β interpolate1if input is a valid identifier, and0otherwise. Because GNU troff ignores any input character with an invalid code when reading it, invalid identifiers are empty or contain spaces, tabs, newlines, or escape sequences that interpolate something other than a sequence of ordinary characters. You can employ\Ato validate a macro argument before using it to construct another escape sequence or identifier. Validation era π\B'input'β interpolate1if input is a valid numeric expression, and0otherwise. You might use\Balong with the βifβ request to filter out invalid macro arguments. Gatekeeping, but make it numeric.\D'C d'β draw filled circle of diameter d with its leftmost point at the drawing position.\D'E h v'β draw filled ellipse of axis lengths h and v, with its leftmost point at the drawing position.\D'p h1 v1 ... hn vn'β draw polygon with vertices at the drawing position and each point in sequence. GNU troff closes the polygon by drawing a line from (hn, vn) back to the initial drawing position; DWB and Heirloom troffs do not. Afterward, the drawing position is left at (hn, vn). Closure is iconic, ngl.\D'P h1 v1 ... hn vn'β as\D'p', but the polygon is filled. groff does not specify how the output device must fill concave or self-intersecting polygons. No cap, no promises on the fill algorithm π«Ά\D't n'β set line thickness of geometric objects to n basic units. A zero n selects the minimum supported thickness. A negative n (the default) selects a thickness proportional to the type size.\Eβ embed an escape character that is not interpreted in copy mode (compare with\aand\t). You can use it to ease the writing of nested macro definitions. It is also convenient to define strings containing escape sequences that need to work when used in copy mode (for example, as macro arguments), or that will be interpolated at varying macro nesting depths. Nested macro queen π\f[fnt]β select typeface fnt, which may be a mounting position, abstract style, or font name.\f[],\f[P], and\fPare synonyms; we recommend the first. Bestie, take the recommendation.\Ff,\F(fm,\F[fml]β select default font family.\F[]makes the previous font family the default.\FPis unlike\fP; it selects font family βPβ as the default. See thefamrequest below.\k(rg,\k[reg]β store the horizontal drawing position, relative to that corresponding to the start of the input line (ignoring page offset and indentation), in two-character register name rg or arbitrary register name reg. Saving your spot, but make it typographic.\mc,\m(cl,\m[col]β set stroke color to col.\m[]restores the previous stroke color, or the default if there is none.\Mc,\M(cl,\M[col]β set fill color to col.\M[]restores the previous fill color, or the default if there is none.\n[reg]β interpolate register reg. Your fave little value retrieval.\On,\O[n]β suppress troff output of glyphs and geometric objects. The sequences\O2,\O3,\O4, and\O5are intended for internal use bygrohtml(1). This is lowkey the image-generation control room, so buckle up.\O0,\O1β disable and enable, respectively, the emission of glyphs and geometric objects to the output driver, provided that this sequence occurs at the outermost suppression level (see\O3and\O4). Horizontal motions corresponding to non-overstruck glyph widths still occur. These sequences also reset the registersopminx,opminy,opmaxx, andopmaxyto-1. These four registers mark the top left and bottom right hand corners of a box encompassing all written or drawn output. Plot twist: even suppressed output leaves a bounding-box paper trail π\O2β at the outermost suppression level, enable emission of glyphs and geometric objects, and write to the standard error stream the page number and values of the four aforementioned registers encompassing glyphs written since the last interpolation of a\Osequence, as well as the page offset, line length, image file name (if any), horizontal and vertical device motion quanta, and input file name. Numeric values are in basic units. Diagnostics with main character energy.\O3,\O4β begin and end a nested suppression level, respectively.grohtmluses this mechanism to create images of output preprocessed withpic,eqn, andtbl. At startup,troffis at the outermost suppression level.pre-grohtmlgenerates these sequences when processing the document, usingtroffwith thepsoutput device, Ghostscript, and the PNM tools to produce images in PNG format. These sequences start a new page if the device is nothtmlorxhtml, to reduce the number of images crossing a page boundary. Page-boundary damage control, we love to see it.\O5[Pfile]β at the outermost suppression level, write the name file to the standard error stream at position P, which must be one ofl,r,c, ori, corresponding to left, right, centered, and inline alignments within the document, respectively. file is a name associated with the production of the next image.
\R'name Β±n'β synonymous with β.nr name Β±nβ. Same energy, different spelling.\s[0],\s'0'β restore the previous type size; no operation if there is none. Rewind the font-size moment π\s[Β±n],\sΒ±[n],\s'Β±n',\sΒ±'n'β set the type size to, or increment or decrement it by, n typographical points. Big mood, small mood, your call.\Ve,\V(ev,\V[env]β interpolate contents of the system environment variable env (one-character name e, two-character name ev) as returned bygetenv(3).\Vis interpreted even in copy mode. Environment variables said βI'm the moment.β\X'character-sequence'β unlike AT&T troff, GNU troff performs some limited processing of the sequence of ordinary characters, special characters, and spaces in character-sequence. This one's a whole saga, so stay with me.
The formatter's special character repertoire is unknown to output drivers outside of glyphs named in a device's fonts, and even then they may not possess complete coverage of the names documented in groff_char(7). Further, escape sequences that produce horizontal or vertical motions, hyphenation breaks, or that are dummy characters may appear in strings or be converted to nodes, particularly in diversions. When they occur in a device extension command, they produce warnings in category βcharβ. These are not representable when interpolated directly into device-independent output, as might be done when writing out tag names for PDF bookmarks, which can appear in a viewer's navigation pane. This is also the case for a small number of special characters, such as \[ru], the baseline rule, that lack a Unicode definition. Not the baseline rule catching strays π
So that any Unicode code point can be represented in device extension commands, for example in an author's name in document metadata or as a usefully named bookmark or hyperlink anchor, GNU troff transforms its argument to represent characters outside the Unicode Basic Latin range as Unicode code points expressed in groff's notation for these, β\[uXXXX]β; see groff_char(7). For these transformations, the formatter ignores character translations and definitions. Unicode representation, no gatekeeping.
GNU troff converts several ordinary characters that typeset as non-basic Latin code points to code points outside that range so that they are used consistently whether they are formatted as glyphs or used in a device extension command argument. These ordinary characters are ', -, ^, `, and ~; others are written as-is. Thus, ' transforms to \[u2019].
Contrariwise, GNU troff translates special characters that typeset as Unicode basic Latin characters to basic Latin characters accordingly. Thus, \[ga] transforms to `, \[Do] to $, and so on. Consistency is the moment β¨
\Ym,\Y(ma,\Y[mac]β interpolate a macro or string as a device extension command. As\X'\*[mac]', except that GNU troff does not interpret the contents of mac; further, mac can be a macro and thus contain newlines, unlike the argument to\X. This inclusion of newlines requires an extension to the AT&T troff device-independent page description language, and their presence confuses drivers that do not know about it (see subsection βDevice control commandsβ ofgroff_out(5)). Chaos, but documented chaos π\Z'input'β save the drawing position, format input, then restore it. GNU troff ignores tabs and leaders in input with an error diagnostic. Snapshot the position, do the thing, put it back β but tabs and leaders? Absolutely not, says troff.\#β bestie, this one reads literally everything up to and including the next newline in copy mode, then yeets it ποΈ. Itβs like\", except\"does not ignore a newline, so\"canβt be used by itself for a whole-line comment β it leaves a blank line on the input stream. Not iconic behavior, but now you know π\$0β interpolates the name by which the macro being interpreted was called. In GNU troff this name can vary; see thealsrequest. Slay, aliases β¨\$(nn,\$[nnn]β in a macro or string definition, interpolate the *nn*th or *nnn*th argument. In GNU troff, macros and strings can have an unlimited number of arguments. No cap π§’\$*β in a macro or string definition, interpolate the catenation of all arguments, separated by spaces. Group-chat energy fr fr π¬\$@β in a macro or string definition, interpolate the catenation of all arguments, with each surrounded by double quotes and separated by spaces. Quoted and cute π\$^β in a macro or string definition, interpolate the catenation of all arguments constructed in a form suitable for passage to thedsrequest. Built for the assignment moment π\)β interpolate a transparent dummy character, one that is ignored by end-of-sentence detection. It behaves as\&, except that\&is treated as letters and numerals normally are after β.β, β?β, and β!β;\&cancels end-of-sentence detection, and\)does not. Sneaky little punctuation lore π\*[string [arg ...]]β interpolate string, passing it arg ... as arguments. String said βbring the whole crewβ π\/β apply an italic correction: modify the spacing of the preceding glyph so that the distance between it and the following glyph is correct if the latter is of upright shape. Example time: if an italic βfβ is followed immediately by a roman right parenthesis, then in many fonts the top right portion of the βfβ overlaps the top of the right parenthesis, which is ugly π. Inserting\/between them avoids this problem. Consider using\/whenever a slanted glyph is immediately followed by an upright glyph without any intervening space. Typography glow-up activated β¨\,β apply a left italic correction: modify the spacing of the following glyph so that the distance between it and the preceding glyph is correct if the latter is of upright shape. Example: if a roman left parenthesis is immediately followed by an italic βfβ, then in many fonts the bottom left portion of the βfβ overlaps the bottom of the left parenthesis, which is ugly π. Inserting\,between them avoids this problem. Consider using\,whenever an upright glyph is followed immediately by a slanted glyph without any intervening space. Left-side correction, same slay π\:β insert a non-printing break point. That is, a word can break there, but the soft hyphen character does not mark the break point if it does (in contrast to β%β). The remainder of the word is subject to hyphenation as normal. Invisible break, real impact π¦\?character-sequence\?β suppress formatting of character-sequence. This feature has two applications, and yes bestie, both matter π«Ά- Surround operands to the output comparison operator with
\?to compare them by character rather than as formatted output. Since GNU troff reads comparands protected with\?in copy mode, they need not even be valid groff syntax. The escape character is still lexically recognized, however, and consumes the next character. Read that again: it still eats the next char π - When used in a diversion,
\?transparently embeds input, read in copy mode, until its own next occurrence on the input line. Use\!if you want to embed newlines in a diversion. Unlike\!,\?is interpreted even in copy mode, and a character-sequence in the top-level diversion is not sent to device-independent output. Diversion girlie behavior, documented π₯
- Surround operands to the output comparison operator with
\[char]β typeset the special character char. Seegroff_char(7). Character cameo unlocked π\[base-char combining-component ...]β typeset a composite glyph consisting of base-char overlaid with one or more combining-components. For example, β\[A ho]β is a capital letter βAβ with a βhook accentβ (ogonek). See thecompositerequest below; Groff: The GNU Implementation of troff, the groff Texinfo manual, for details of composite glyph name construction; andgroff_char(7)for a list of components used in composite glyph names. Composite glyph lore is lowkey deep π§\~β insert an adjustable, unbreakable space. As with ordinary spaces, GNU troff discards any sequence of these at the end of an output line if a break occurs. Soft space, strong boundaries π
β¨ Restricted requests β¨
To mitigate risks from untrusted input documents, GNU troff disables the cf, pi, and sy requests by default. Its -U option enables βunsafe modeβ, restoring their function (and enabling additional groff extension requests, βopenβ, opena, and pso). Security vibe check: these are off unless you deliberately turn on unsafe mode π
π Altered requests π
.bd special-font fontβ stop emboldening special-font when font is selected. special-font must be a font name, not a mounting position. No fake bold energy here π«.cf ["]fileβ break and copy the contents of file as βthroughputβ to GNU troff's output. If a diversion is in use, GNU troff performs the copy only when the diversion is emitted. In AT&T troff, the contents of file are immediately copied to the output regardless of whether a diversion is being written to; this behavior is so anomalous that it must be considered a bug. Straight-up bug behavior, not a cute quirk π GNU troff removes a leading neutral double quote β"β from the argument, permitting initial embedded spaces in it, and reads it to the end of the input line in copy mode. If file does not exist or is not readable, a warning in category βfileβ is emitted and the request has no other effect. File said βnot foundβ and left the chat π.de name [end-name],.am name [end-name],.ds name [["]contents],.as name [["]contents]β in compatibility mode, these requests behave asde1,am1,ds1, andas1, respectively: GNU troff inserts a compatibility save token at the beginning of the macro, string, or appendment thereto as applicable and a compatibility restore token at its end, enabling compatibility mode during its interpolation. Thus they work as expected even if the interpolation context disables compatibility mode. Compatibility mode said βI got youβ π«Ά.hy nβ new values16and32are available; the former enables hyphenation before the last character in a word, and the latter enables hyphenation after the first character in a word. If invoked without an argument, the mode configured by thehydefaultrequest is selected. Hyphenation settings got new lore β¨.lf input-line-number [["]file-identifier]β in GNU troff the first argument becomes the input line number of the next line the formatter reads. It also removes a leading neutral double quote β"β from file-identifier, permitting initial embedded spaces in it, and reads it to the end of the input line in copy mode. Line number glow-up, with filename manners π.nx [["]file]β GNU troff removes a leading neutral double quote β"β from file, permitting initial embedded spaces in it, and reads it to the end of the input line in copy mode. Next-file behavior, but make it polite π.pi ["]commandβ GNU troff strips a leading neutral double quote from the argument, permitting initial embedded spaces in it. Command, but with space respect π«Ά.pm name ...β GNU troff reports, to the standard error stream, the JSON-encoded name and contents of each macro, string, or diversion name. JSON reveal, standard-error style π.so ["]fileβ GNU troff removes a leading neutral double quote β"β from file, permitting initial embedded spaces in it, and reads it to the end of the input line in copy mode. GNU troff searches for file in any directories specified by-Icommand-line options, followed by the current working directory. If file does not exist or is not readable, GNU troff emits a warning in category βfileβ. Source-hunting quest activated πΊοΈ.ss word-space-size [additional-sentence-space-size]β a second argument sets the amount of additional space separating sentences on the same output line. If omitted, this amount is set to word-space-size. Both arguments are in twelfths of current font's space width (typically one-fourth to one-third em for Western scripts; seegroff_font(5)). The default for both parameters is12. Negative values are erroneous. Sentence spacing said βdo not test meβ π€.sy ["]commandβ GNU troff strips a leading neutral double quote from the argument, permitting initial embedded spaces in it. System command, but with the quote handled first π.ta [[n1 n2 ... nn ]T r1 r2 ... rn]β GNU troff supports an extended syntax to specify repeating tab stops after the βTβ mark. These values are always taken as relative distances from the previous tab stop. This is the idiomatic way to specify tab stops at equal intervals in groff. GNU troff's startup value is βT 0.5iβ. The syntax summary above instructs groff to set tabs at positions n1, n2, ..., nn, then at nn+r1, nn+r2, ..., nn+rn, then at nn+rn+r1, nn+rn+r2, ..., nn+rn+rn, and so on. Tab stop math, but make it fashion π
π¦ New requests π¦
Several GNU troff requests work like AT&T troff's βasβ and ds requests, accepting an optional leading neutral double quote, notated β["]β, in an argument that the formatter reads in copy mode to the end of the input line, permitting inclusion of leading spaces. Yes bestie, leading spaces are getting their moment πΈ
.aln new-register existing-registerβ create alias (additional name) new-register of existing-register, causing the names to refer to the same stored object. If existing-register is undefined, the formatter ignores the request. GNU troff produces a warning in category βregβ. See section βWarningsβ oftroff(1)regarding the enablement and suppression of warnings. To remove a register alias, invokerron its name. A register's contents do not become inaccessible until it has no more names. Register aliases: shared custody, but make it troff π―.als new-name existing-nameβ create alias (additional name) new-name of request, string, macro, or diversion existing-name, causing the names to refer to the same stored object. If existing-name is undefined, the formatter ignores the request. GNU troff produces a warning in category βmacβ. If new-name already exists, its contents are lost unless already aliased. See section βWarningsβ oftroff(1)regarding the enablement and suppression of warnings. To remove an alias, invokermon its name. The object itself is not destroyed until it has no more names. Alias drama, but the object survives until the last name is gone π
Ever wondered what happens when you alias a request, macro, string, or diversion? π Okay so: redefinitions and appendments βwrite throughβ alias names. Like, the alias is a window, not a copy. So if you wanna replace an alias with a totally separately defined object, you gotta remove its name first. No cap. π
.am1name [end-name] β it's giving βambut with a glow-upβ: GNU troff disables compatibility mode while interpreting the appendment to name. It drops a compatibility save token at the start of the appendment and a compatibility restore token at the end. The result?am,am1,de, andde1can be intermixed freely π because those save/restore tokens only touch the parts of the macro populated byam1andde1..aminame [end-name] β append to a macro indirectly. Seedeibelow. (iykyk).ami1name [end-name] β asami, but GNU troff disables compatibility mode while interpreting the appendment to the macro named by the contents of the string name. Seeam1above. β¨.as1name [["]contents] β as βasβ, except GNU troff disables compatibility mode while interpreting the appendment to the string name: it sticks a compatibility save token at the beginning of the appendment and a compatibility restore token at its end. Soas,as1,ds, andds1can be intermixed freely, bestie, since the save/restore tokens only affect the portions of the string populated byas1andds1. π¦.asciifydiv β unformat the diversion div so that Unicode basic Latin (US-ASCII) characters, characters translated with thetrinrequest, space characters, and some escape sequences that were formatted inside div get treated like ordinary input characters when div is interpolated. This is lowkey iconic when you're pairing it with thewritemrequest. π₯
When it's transforming a glyph node back into an input sequence that demands expression as a special character escape sequence, GNU troff uses the default escape character.
Real talk though: asciify cannot return all nodes in a diversion to their source equivalents β nodes produced by indexed characters (\N), for example, stay as nodes, so the result can't be guaranteed to be a character sequence the way a macro or string is. π Pass the diversion name as an argument to the pm request to inspect its contents and node list. Also, glyph parameters like the type face and size are not preserved; use βunformatβ if that's the vibe you're after.
.backtraceβ writes a backtrace of the input stack to the standard error stream. See the-boption oftroff(1). π«Ά.blm[name] β set a blank line macro (a trap, bestie). If a blank line macro is defined this way, groff executes name whenever a blank line shows up in the input, instead of doing the usual thing. And a line consisting only of spaces also counts as blank and gets subjected to this trap β sneaky. π If you pass no argument, the default blank line behavior is (re-)established..box[name].boxa[name]
Divert (or append) output to name, just like the di and da requests respectively. Heads up: any pending output line is not included in the diversion. π With no argument, it stops diverting output β and any pending output line inside the diversion gets discarded. Gone. Periodt.
.breakβ exit a βwhileβ loop. Do not confuse this request with a typographical break or thebrrequest, babes, they are not the same thing. See βcontinueβ. π.brpβ break and force adjustment of the output line per the current adjustment mode. Likebr, it does absolutely nothing if it's invoked with the no-break control character..cflagsn c... β assign the properties encoded by the non-negative integer n to each character or class c. Spaces are not required between the c arguments. β¨
n is the sum of any of the following. Some combos are straight-up nonsensical, like β33β (1 + 32). π₯΄
- Recognize the character as ending a sentence if it's followed by a newline or two spaces. Initially, the characters β
.?!β have this property. - Enable breaks before the character. A line is not broken at a character with this property unless the characters on each side both have non-zero hyphenation codes. That exception can be overridden by adding 64. Initially, no characters have this property.
- Enable breaks after the character. Same deal β a line isn't broken at a character with this property unless the characters on each side both have non-zero hyphenation codes, and adding 64 overrides that exception. Initially, the characters β
-\[hy]\[em]β have this property. - Mark the glyph associated with this character as overlapping other instances of itself horizontally. Initially, the characters β
\[ul]\[rn]\[ru]\[radicalex]\[sqrtex]β have this property. - Mark the glyph associated with this character as overlapping other instances of itself vertically. Initially, the character β
\[br]β has this property. - Mark the character as transparent for the purpose of end-of-sentence recognition β meaning an end-of-sentence character followed by any number of characters with this property is treated as the end of a sentence if followed by a newline or two spaces. This is the same as having a zero space factor in TeX. Initially, the characters β
'")]*\[dg]\[dd]\[rq]\[cq]β have this property. π - Ignore hyphenation codes of the surrounding characters. Use this value in combination with values 2 and 4. Initially, no characters have this property.
The remaining values were implemented for East Asian language support; if you're exclusively using alphabetic scripts, you can totally disregard them. π§
- Prohibit a break before the character, but allow a break after it. This only works in combination with values 256 and 512, and has no effect otherwise. Initially, no characters have this property.
- Prohibit a break after the character, but allow a break before it. Only works in combination with values 128 and 512, no effect otherwise. Initially, no characters have this property.
- Allow a break before or after the character. Only works in combination with values 128 and 256, no effect otherwise. Initially, no characters have this property.
In contrast to values 2 and 4, the values 128, 256, and 512 work pairwise. If, for example, the left character has value 512 and the right character 128, no break will be automatically inserted between them. But if we use value 6 instead for the left character, a break after the character can't be suppressed, since the neighboring character on the right doesn't get examined. π
.charc [["]contents] β define an ordinary, special, or indexed character c as contents. Omit contents and c gets an empty definition.
Defining (or redefining) a character c creates a formatter object that GNU troff recognizes like any other ordinary, special, or indexed character on input, and which produces contents on output. When formatting c, GNU troff processes contents in a temporary environment and encapsulates the result in a node (see section βGNU troff Internalsβ in Groff: The GNU Implementation of troff, the groff Texinfo manual); it disables compatibility mode and sets the escape character to \ while interpreting contents. Any emboldening, constant spacing, or track kerning applies to this object rather than to the individual glyphs resulting from formatting contents. π
A character defined by char can be used just like a glyph provided by the output device. Specifically:
- other characters can be translated to it with the
trrequest; - it can be made the tab or leader fill character with the
tcandlcrequests; - sequences of it can be drawn with the
\land\Lescape sequences; - and, if the
hcoderequest is used on c, it's subject to automatic hyphenation.
However π a user-defined character c does not participate at its boundaries in kerning adjustments or italic corrections. Sorry bestie.
The formatter prevents infinite recursion by treating an occurrence of a character in its own definition as if it were undefined; when interpolating such a character, GNU troff emits a warning in category βcharβ. (Mutually recursive character definitions get handled the same way, don't worry.)
The tr and trin requests take precedence if char also applies to c. And the rchar request removes character definitions. π
.chopname β remove the last character from the macro, string, or diversion name. Super useful for removing the newline from the end of a diversion that's about to be interpolated as a string. You can use this request repeatedly on the same name; see section βGNU troff Internalsβ in Groff: The GNU Implementation of troff, the groff Texinfo manual, for the discussion of nodes inserted by groff. βοΈ.classident c... β define a character class (or just βclassβ) ident comprising the members c..., where each c is an ordinary, special, or indexed character, or a range expression. A class defined this way can then be referred to in acflagsrequest instead of listing out all the characters inside it. πΈ
Since class and special character names share the same name space, we recommend starting and ending the class name with β[β and β]β respectively, so you avoid collisions with existing special character names defined by GNU troff or by the user (with char and related requests). This practice applies the presence of β]β in the class name to prevent the usage of the special character escape form β\[...]β β so you must therefore access a class named this way via the \C escape sequence. π¦
okay so also β an argument c can alternatively be a range expression, which is a start character, then a -, then an end character. under the hood GNU troff converts those two character names to Unicode code points (per the groff glyph list [GGL]), and those are what set the start and end values of the range. if that conversion fails, GNU troff just skips the range expression and any remaining arguments. gone. not invited. π
.closestream β closes the named stream, which straight up invalidates it as an argument to thewriterequest. peepopenfor the origin story π«Ά.compositec1 c2 β maps ordinary or special character c1 to c2 when c1 is a combining component in a composite character. typically you usecompositeto map a spacing character onto a combining one. seegroff_char(7)β¨.continueβ skips the rest of awhileloop's body and immediately retests its conditional expression. seebreakabove, bestie π.color[b] β turns output of color-related device-independent output commands on or off per Boolean expression b. it's enabled by default, and also enabled if b is omitted. π.cp[b] β turns AT&T troff compatibility mode on or off per Boolean expression b. it's disabled by default, and enabled if b is omitted. in compatibility mode, long names are not recognized, and the incompatibilities they cause don't arise. no cap π.defcolorident scheme color-component ... β defines a color named ident. scheme identifies a color space and determines how many color-components you need; it must be one ofrgb(three components),cmy(three components),cmyk(four components), orgray(one component).greyis accepted as a synonym ofgrayπ
each color component can be encoded as a hexadecimal value starting with # or ##. the former means each component is in the range 0β255 (0βFF), the latter means the range 0β65535 (0βFFFF). alternatively, a component can be given as a decimal fraction in the range 0β1, interpreted using a default scaling unit of f, which multiplies its value by 65,536 (but clamps it at 65,535).
each output device has a color named default, and that one cannot be redefined. also a device's default stroke and fill colors aren't necessarily the same, so don't assume, ok? π
.de1ident [end-name] β same asde, except GNU troff disables compatibility mode while interpreting name: it inserts a compatibility save token at the beginning of the macro definition, and a compatibility restore token at its end. see.am1above π.deiname [end-name] β defines a macro indirectly, with the name of the macro to be defined living in string name, and the name of the end macro that terminates its definition living in string end-name. sneaky but iconic π§.dei1name [end-name] β asdei, but GNU troff disables compatibility mode while interpreting the macro named by the contents of string name. seeam1andde1above β.device[["]character-sequence] β embeds character-sequence into GNU troff output as parameters to anxXdevice extension command; seegroff_out(5). the output driver or whatever other postprocessor is hanging around interprets character-sequence however it sees fit. yes, it's giving "you're on your own" π₯.devicemname β writes the contents of macro or string name to troff output as the argument to a device extension command. π¦.doname [argument ...] β interprets the string, request, diversion, or macro name (plus any further arguments) with compatibility mode disabled. compatibility mode gets restored (only if it was active) when the interpolation of name is interpreted β meaning the restored compatibility state applies to the request or contents of the macro, string, or diversion name, to its arguments, and to data read from files or pipes if name is theso,soquiet,mso,msoquiet, orpsorequest. yeah it's a whole chain, keep up π.ds1name [["]contents] β asds, but GNU troff disables AT&T compatibility mode while interpreting name: it inserts a βcompatibility saveβ token at the beginning of contents, and a βcompatibility restoreβ token after it. π.ecrβ restores the escape character saved withecs, or sets the escape character to\if none has been saved. rewind moment βͺ.ecsβ saves the current escape character. bookmark it, bestie π.evcenv β copies the properties of environment env to the current environment, except for:- a partially collected line, if present;
- the interruption status of the previous input line (due to use of the
\cescape sequence); - the count of remaining lines to center, to right-align, or to underline (with or without underlined spaces) β these get set to zero;
- the activation status of temporary indentation;
- input traps and their associated data;
- the activation status of line numbering (which can be reactivated with
.nm +0); and - the count of consecutive hyphenated lines (set to zero).
copying an environment to itself discards all of the above data. self-care but make it destructive π
.fam[fml] β sets the default font family to fml. with no argument, the previous font family is selected, and if there isn't one, the formatter's default family. that default isT(Times), but the output device can override it β seegroff_font(5). the default font family is associated with the environment. see\F. π.fcharc [["]contents] β defines fallback character c as contents. it's likechar, except while that request hides a glyph with the same name in the selected font,fchardefinitions only get used if the font lacks a glyph for c. GNU troff runs this test before it searches special fonts. priorities, honestly πΈ.fcolor[col] β selects col as the environment's fill color, or, with no argument, restores the previous fill color, or the default if there isn't one. ποΈ.fscharf c [["]contents] β defines fallback special character c for font f as contents. likechar, but GNU troff locates a character defined byfscharafter any fonts named as arguments tofspecialare searched, and before those named as arguments to thespecialrequest. order matters, periodt π«Ά.fspecialf [s ...] β declares each font s as special only when font f is selected. at first, a font f's list of associated special fonts is empty for every f. GNU troff searches fonts given as arguments to thespecialrequest after those given as arguments to thefspecialrequest. seespecial. π«.ftrf [g] β translates font f to g. whenever a font named f is referred to in an\fescape sequence, in theFandSconditional expression operators, or in theft,ul,bd,cs,tkf,special,fspecial,fp, orstyrequests, font g gets used instead. if g is missing or identical to f, then font f is not translated. simple as that π.fzoomf [zoom] β sets zoom factor zoom for font f. zoom must be a non-negative integer; it scales the magnification by thousandths, with 1000 as the basis. if zoom is missing or equal to zero or 1000, font f is not magnified. f must be a resolved font name, not an abstract style or mounting position. read that again, it's important π.gcolor[col] β selects col as the environment's stroke color, or, with no argument, restores the previous stroke color, or the default if there isn't one. matchingfcolorenergy, slay β¨.hcodedst1 src1 [dst2 src2] ... β sets the hyphenation code of character dst1 to that of src1, and so on. dst1 must be an ordinary character (other than a numeral) or a special character, and src1 must be an ordinary character (other than a numeral) or a special character that already has a hyphenation code applied to it. assigning the code of an ordinary character to itself effectively creates a unique hyphenation code (which you can then copy to others).hcodeignores spaces between arguments. if any argument is invalid,hcodereports an error and stops reading them β no partial nonsense π.hla[lang] β sets the hyphenation language to lang, or clears it if there's no argument. hyphenation exceptions specified with thehwrequest, plus hyphenation patterns and exceptions specified with thehpfandhpfarequests, are associated with the hyphenation language. thehlarequest is usually invoked by a localization file, which is in turn loaded by thetroffrcortroffrc-endfile; see thehpfrequest below. π.hlm[n] β sets the consecutive automatically hyphenated line limit to n. a negative value means βno limitβ. omitting n implies a limit of-1. this value is associated with the environment. only lines output from a given environment count toward the maximum associated with that environment. hyphens resulting from\%are counted; explicit hyphens are not. the audacity π.hpf["]pattern-file β reads hyphenation patterns from pattern-file. this file is sought the same way macro files are with themsorequest. π
pattern-file should have the same format as (simple) TeX pattern files. the following scanning rules are implemented:
- a percent sign starts a comment (up to the end of the line) even if it's preceded by a backslash.
- βDigraphsβ like
\$are not supported. ^^xx(where each x is 0β9 or aβf) and^^c(character c in the code point range 0β127 decimal) are recognized; other uses of^cause an error.- no macro expansion is performed.
hpfchecks for the expression\patterns{...}(possibly with whitespace before or after the braces). everything between the braces is taken as hyphenation patterns. consequently,{and}are not allowed in patterns.- similarly,
\hyphenation{...}gives a list of hyphenation exceptions. \endinputis recognized too.- for backward compatibility, if
\patternsis missing, the whole file is treated as a list of hyphenation patterns (but the%character is still recognized as the start of a comment).
that's the whole ruleset β no skipping, we read all of it together π§ββοΈ
Use the hcode request (see above) to map the encoding used in hyphenation pattern files to groff's input encoding. that's the whole vibe π§
GNU troff ties the set of hyphenation patterns to the hyphenation language code selected by the hla request. The hpf request is usually invoked by a localization file loaded by the troffrc file. groff provides localization files for several languages; See subsection βLocalization packagesβ of groff_tmac(5). For Western languages, the localization file sets the default hyphenation mode and loads hyphenation patterns and exceptions. By default, troffrc loads the localization file for English. π
A second call to hpf (for the same language) replaces the old patterns with the new ones. out with the old, in with the new, periodt β¨
Invoking hpf causes an error if there is no hyphenation language. no language, no patterns, bestie π
If no hpf request is specified (either in the document, in a file loaded at startup, or in a macro package), GNU troff won't automatically hyphenate at all. zero auto-hyphenation, fr fr π
.hpfa ["]pattern-fileβ Ashpf, except that the hyphenation patterns and exceptions from pattern-file are appended to the patterns already applied to the hyphenation language of the environment. append not replace, queen behavior π«Ά.hpfcode a b [c d] ...β Caution: This request will be withdrawn in a future groff release. Usehcodeinstead.
Define mapping values for character codes in pattern files. hpf or hpfa apply the mapping after reading or appending to the active list of patterns. Its arguments are pairs of character codesβintegers from 0 to 255. The request maps character code a to code b, code c to code d, and so on. Character codes that would otherwise be invalid in GNU troff can be used. By default, every code maps to itself except those for letters βAβ to βZβ, which map to those for βaβ to βzβ. uppercase girlies get lowercased, that's just the rule π
.hydefault modeβ Set hyphenation mode default to mode. When thehyrequest is invoked without an argument, this mode is selected. The hyphenation mode default is associated with the environment. The formatter's default is1for AT&T troff compatibility. groff locale files generally set a more appropriate one; seegroff_tmac(5). πΈ.hym [length]β Set the (right) hyphenation margin to length. If the adjustment mode is not βbβ or βnβ, the line is not hyphenated if it is shorter than length. Without an argument, the default hyphenation margin is reset to its default value,0. The default scaling unit is βmβ. The hyphenation margin is associated with the environment. A negative argument resets the hyphenation margin to zero, emitting a warning in category βrangeβ. negative = reset + warning, no cap π.hys [hyphenation-space]β Suppress hyphenation of the line in adjustment modes βbβ or βnβ, if that adjustment can be achieved by adding no more than hyphenation-space extra space to each inter-word space. Without an argument, the hyphenation space adjustment threshold is set to its default value,0. The default scaling unit is βmβ. The hyphenation space adjustment threshold is associated with the environment. A negative argument resets the hyphenation space adjustment threshold to zero, emitting a warning in category βrangeβ. same energy, different register π.itc n [mac]β As βitβ, but lines interrupted with the\cescape sequence do not apply to the line count. the\cgirlies are exempt, slay π.kern [b]β Enable or disable pairwise kerning of glyphs in the environment per Boolean expression b. It is enabled by default, and if b is omitted. kerning is ON unless you say otherwise, bestie β¨.length reg [["]contents]β Compute the number of characters in contents and store the count in the register reg. If reg doesn't exist, GNU troff creates it. π
Caution: If you interpolate a macro or diversion in contents (see section βPunning Namesβ ingroff(7)), thelengthrequest counts characters (or nodes) only up to the first newline, and leaves the rest on the input stream. In conventional circumstances, that means the remainder is interpreted, and may be formatted. To discover the length of any string, macro, or diversion, use thepmrequest. See section βDebuggingβ below.
.linetabs [b]β Activate or deactivate line-tabs in the environment per Boolean expression b. They are inactive by default, and activated if b is omitted. When line-tabs are active, tab stops are computed relative to the start of the pending output line instead of the drawing position corresponding to the start of the input line. tab math but make it relative π¦.lsm [name]β Set a leading space trap, calling the macro name when GNU troff encounters leading spaces on a text line; the implicit line break that normally happens in this case is suppressed. The formatter stores the count of leading spaces on the text line in registerlsn, and the amount of corresponding horizontal motion in registerlss, irrespective of whether a leading space trap is set. When it is, GNU troff removes the leading spaces from the input line and produces no motion before calling name. πΈ
If no argument is supplied, GNU troff reΓ«stablishes the default handling of leading spaces on text lines (breaking the line when filling, and formatting a horizontal motion of \n[lsn] word spaces). back to default, no drama π«Ά
.mso ["]fileβ As βsoβ, except that GNU troff searches for the specified file in the same directories as macro files; seeGROFF_TMAC_PATHin section βEnvironmentβ ofgroff(1)and-min section βOptionsβ of the same page. If file does not exist or is not readable, a warning in category βfileβ is emitted and the request has no other effect. macro-path bestie behavior π.msoquiet ["]fileβ Asmso, but no warning is emitted if file does not exist. silent mode, ninja style π§.nop [input]β Interpret input as if it were an input line.nopresembles β.if 1β; it puts a break on the output if input is empty. Unlike βifβ, it cannot govern conditional blocks. Its application is to maintain consistent indentation within macro definitions even when formatting output. indentation consistency is self care β¨.nroffβ Make thenconditional expression evaluate true andtfalse. Seetroff. one-line icon π.open ident ["]fileβ Open file for writing and associate a stream named ident with it, making it available for βwriteβ requests. Unsafe request; disabled by default. Also seewritecand βcloseβ. unsafe and off by default, do not casually touch π.opena ident ["]fileβ As βopenβ, but appends to file if it already exists instead of overwriting it. additive not destructive, we love to see it π.output ["]character-sequenceβ Emit character-sequence, transparently to GNU troff output; this usage is similar to that of\!when it occurs in the top-level diversion. sneaky little byte pipeline π¦.pchar c ...β Report, to the standard error stream, information about each character (be it ordinary, special, or indexed) or character class c. A character defined by a request (char,fchar,fschar, orschar) reports its contents as a JSON-encoded string, but the output is not otherwise in JSON format. JSON string but NOT JSON overall, read that twice π.pcolor [col ...]β Report, to the standard error stream, each defined color named col, its color space identifier, and channel value assignments, or, without arguments, those of all defined colors. A device's default stroke and/or fill colors, βdefaultβ, are not listed since they are immutable and their details unknown to the formatter. default is untouchable and unknowable, iconic π.pcompositeβ Report, to the standard error stream, the list of configured composite character mappings. See βcompositeβ above. The βfromβ code point is listed first, followed by its βtoβ mapping. from first, then to, in that order β.pevβ Report the state of the current environment followed by that of all other environments to the standard error stream. every environment gets a shoutout π.pfpβ Report, to the standard error stream, the list of occupied font mounting positions. Occupied mounting positions are listed, one per line, in increasing order, followed by the typeface name; if the name corresponds to an abstract style, the entry ends there. Otherwise, the name of the font description file and the font's βinternal nameβ datum, the meaning of which varies by output device, follow. mounting positions in increasing order, no skipping π.pftrβ Report, to the standard error stream, the list of font translations. Seepftrabove. The βfromβ font identifier is listed first, followed by its βtoβ translation. again: from, then to π.phwβ Report, to the standard error stream, the list of hyphenation exception words associated with the hyphenation language selected by thehlarequest. A β-β marks each hyphenation point. A word prefixed with β-β is not hyphenated at all. The report suffixes words to which automatic hyphenation applies (meaning those defined in a hyphenation pattern file rather than with thehwrequest) with a tab and asterisk β*β. little dash, big meaning π.plineβ Report, in JSON syntax to the standard error stream, the list of output nodes corresponding to the pending output line. In JSON, a pair of empty brackets β[ ]β represents an empty list. A pending output line has not yet undergone adjustment, and lacks a line number and margin character (all as applicable). empty list =[ ], and yes it's pending pending β¨.pnr [reg ...]β Report the name and value and, if its type is numeric, the autoincrement amount and assigned format of each register reg, or, without arguments, those of all defined registers, to the standard error stream. register gossip, all of it π.psbb fileβ Get the bounding box of a PostScript image file. This file must conform to Adobe's Document Structuring Conventions; the request attempts to extract the bounding box values from a%%BoundingBoxcomment. After invocation, the x and y coordinates (in PostScript units) of the lower left and upper right corners can be found in the registers\n[llx],\n[lly],\n[urx], and\n[ury], respectively. If an error occurs, these four registers are set to zero. error = all four go to zero, no half measures π.pso ["]commandβ As βsoβ, except that input comes from the standard output stream of command, which is passed topopen(3). command output piped straight into your doc, iykyk π§.pstreamβ dumps the whole guest list of currently open streams to the standard error stream, in JSON syntax no less π . For every stream you get its name, the name of the file backing it, and its mode β writing or appending. Very "who's at the party right now" energy..pwhβ reports the names and vertical positions, in basic units, of all page location traps, straight to the standard error stream. And yes, GNU troff will literally show you empty slots in that list too β the ones where a trap got planted and then subsequently (re)moved β because those ghost slots can affect the visibility of traps you plant later. Spooky but useful π«Ά.pvsΒ±n β sets the post-vertical line spacing to n; default scaling unit isp. Call it with no argument and the post-vertical line space just snaps back to its previous value, like nothing happened.
Ok so in GNU troff the distance between text baselines is genuinely a little squad of contributions, bestie: the extra pre-vertical line spacing set by the most negative \x argument on the pending output line, the vertical spacing (vs), the extra post-vertical line spacing set by the most positive \x argument on the pending output line, and the post-vertical line spacing set by this request. All four. Periodt.
.rcharc... β removes the definition of each ordinary, special, or indexed character c, undoing the effect of achar,fchar, orscharrequest. Spaces need not separate the c arguments (go off). The character definition removed (if any) is the first one encountered in the resolution process documented in section βUsing Symbolsβ of Groff: The GNU Implementation of troff. And no, you can't touch glyphs β those are defined by font description files and cannot be removed. Not up for discussion π.return[input] β stops interpreting an interpolated macro, skipping to the end of its definition. Do not confusereturnwithrt, they are not the same bestie π. If called with an argument input, GNU troff performs the skip twice β once within the macro being interpreted and once in an enclosing macro β which is exactly what lets a macro wrap the request (the waytrace.tmacdoes). Iconic behavior honestly..rfscharf c ... β removes each fallback special character c for font f. Spaces need not separate the c arguments. Seefschar. Cleanup era β¨.rj[n] β breaks, right-aligns the next n (default: 1) input lines, then breaks again.rjimplies.ce 0, andceimplies.rj 0β they're mutually obsessed with each other. Invoking the request with the no-break control character suppresses the first break..rnnr1 r2 β renames register r1 to r2. If r1 doesn't exist? The request is simply ignored, no drama, no warning π.scharc [["]contents] β defines global fallback character c as contents. Works likechar, except GNU troff locates a character defined withscharafter any fonts named as arguments to the βspecialβ request and before any mounted special fonts. Order matters, iykyk..shc[c] β sets the soft hyphen character to c β that's the one inserted when a word is hyphenated automatically or at a hyphenation character. If c is omitted, the soft hyphen character gets set to the default,\[hy]. If the selected glyph doesn't exist in the font in use at a potential hyphenation point, then the line is not broken at that point, full stop. And ngl: neither character definitions (charand similar) nor translations (trand similar) are considered when assigning the soft hyphen character. It plays by its own rules π.shift[n] β shifts macro or string parameters n places (by 1 if n is omitted): argument i becomes argument i-n, and arguments 1 to n become unavailable. Shifting by a non-positive amount, or doing it outside of a macro or string definition, performs no operation β it's a no-op, it's giving nothing. The register.$adjusts its value accordingly though, so that stays in sync π.sizess1 s2 ... sn [0] β sets the available type sizes to s1, s2, ... sn scaled points. The list of sizes can be terminated by an optional0. Each si can also be a range mβn. But heads up: in contrast to the device description file directive of the same name (seegroff_font(5)), the argument list can't extend over more than one line. One line only, no exceptions π€.soquiet["]file β as βsoβ, but no warning is emitted if file does not exist. Peace and quiet, we love a low-drama include π.special[s ...] β declares each font s as special, irrespective of its description file, populating a list that GNU troff searches, in order, to find the glyph demanded. GNU troff also mounts each font s. Invokingspecialwith no arguments empties the list entirely (reset slay). A font is not automatically unmounted if a subsequentspecialrequest removes it from the list, jsyk. Initially, the list is empty. And GNU troff searches fonts specified as arguments to the βspecialβ request after those given as arguments to thefspecialrequest β queue order, bestie π.spreadwarn[limit] β emits a βbreakβ warning if the additional space inserted for each space between words in an output line adjusted to both margins with.ad bis larger than or equal to limit. A negative value is treated as zero; an absent argument toggles the warning on and off without changing limit. The default scaling unit ism. At startup,spreadwarnis inactive and limit is3 m.
For example, .spreadwarn 0.2m warns if troff must add 0.2 m or more to each inter-word space in a line. She's watching π
.stringdownstr.stringupstr β these two alter the string named str by replacing each of its bytes with its lowercase (down) or uppercase (up) version (if one exists). Special characters (seegroff_char(7)) will often transform in the expected way, thanks to the regular naming convention for accented characters π¦. When they don't, use substrings and/or catenation β that's the workaround, that's the move..stypos style β associates an abstract style with the non-negative font mounting position pos. Matching making, but for fonts π.substringstr start [end] β replaces the string named str with its substring bounded by the indices start and end, inclusively. The first character in the string has index 0. Negative indices count backward from the end of the string: the last character has index -1, the character before the last has index -2, and so on. If end is omitted, -1 is implied. So.substring thing 0 -1is literally the whole thing. Math ate π.tkff s1 n1 s2 n2 β enables track kerning for font f. When the current font is f, the width of every glyph is increased by an amount between n1 and n2. Specifically: when the current type size is less than or equal to s1, the width is increased by n1; when it's greater than or equal to s2, the width is increased by n2; and when the type size is greater than or equal to s1 and less than or equal to s2, the increase in width is a linear function of the type size. Smooth interpolation, we love to see it π₯.tm1[["]message] β astm, but removes a leading neutral double quote"from message, permitting initial embedded spaces in it. Sneaky little trick for indentation π.tmc[["]message] β astm1, but does not append a newline. Chainable, chaotic, love her..trffile β breaks and copies file as βthroughputβ to GNU troff output, discarding characters that are invalid as input; contrast withcf. Each line of file is output as if preceded by\!, but is not interpreted by the formatter. If file doesn't end with a newline,trfappends one (she finishes what you started). Invoking the request with the no-break control character suppresses the break..trinabcd β as thetrrequest, but theasciifyrequest uses the character code (if any) before the character translation. Order of operations queen π.trntabcd β as thetrrequest, but the translations do not apply to text that is transparently throughput into a diversion with\!. Different rules for the transparent girlies π§.troffβ makes thetconditional expression evaluate true andnfalse. Seenroff. Flip the switch, gaslight the conditionals β¨.unformatdiv β unformats the diversion div. Unlikeasciify, βunformatβ handles only tabs and spaces between words, the latter usually arising from spaces or newlines in the input. Tabs are treated as input tokens, and spaces become adjustable again. The vertical sizes of lines are not preserved, but glyph information (font, type size, space width, and so on) is retained. Partial de-formatting, we respect the commitment π.vpt[b] β enables or disables vertical position traps per the Boolean expression b. They're enabled by default, and also if b is omitted. Vertical position traps are those set by thech,wh, anddtrequests. And this enablement is global β no per-file nonsense, one switch for everyone π.warn[n] β selects categories of warnings to be reported. n is the sum of the numeric codes associated with each warning category that is to be enabled; all other categories are disabled. The categories and their associated codes are listed in section βWarningsβ oftroff(1). For example,.warn 0disables all warnings, and.warn 1disables all warnings except those about missing glyphs. If no argument is given, all warning categories are enabled. Choose your chaos π₯.warnscalescaling-unit β selects the scaling unit used in certain warnings (one ofu,i,c,p, orP; default:i). Ignored on nroff-mode output devices, for which these diagnostics report the vertical page location in lines, and the horizontal page location in ens. Different device, different units, them's the rules π¦.whilecond-expr input β evaluates the conditional expression cond-expr, and repeatedly executes input unless and until cond-expr evaluates false. input, which is often a conditional block, is referred to as the βwhileβ request's body. Main character of the request, honestly.
GNU troff treats the body of a βwhileβ request similarly to that of a de request (albeit one not read in copy mode), but stores it under an internal name and deletes it when the loop finishes. Real talk though: the operation of a macro containing a βwhileβ request can slow significantly if its body is large π. Each time GNU troff interpolates the macro, it parses and stores the βwhileβ body again. An often better solution β and one that is more portable, since AT&T troff lacked the βwhileβ request β is to instead write a recursive macro, which is parsed only once (unless you redefine it). To prevent infinite loops, GNU troff limits the default number of available recursion levels to 1,000 or somewhat less (because things other than macro calls can be on the input stack). You can disable this protective measure, or alter the limit, by setting the slimit register. See section βDebuggingβ below. And one final gotcha: if a βwhileβ body begins with a conditional block, its closing brace must end an input line. Non-negotiable, bestie π
Okay so the break and continue requests alter a while loop's flow of control. π
.write stream [["]character-sequence]β Writecharacter-sequence, a sequence of ordinary characters, spaces, or tabs read in copy mode, tostream, which must previously have been the subject of anopen(oropena) request, followed by a newline. GNU troff flushes the stream after writing to it. β¨.writec stream [["]character-sequence]β Aswrite, but does not append a newline to contents..writem stream nameβ Write the contents of the macro or stringnametostream, which must previously have been the subject of anopen(oropena) request. GNU troff reads the contents ofnamein copy mode. π«Ά
π« Altered registers π«
GNU troff alters the semantics of two AT&T troff registers and imparts semantics to two others that CSTR #54 documented as βreservedβ. No cap, bestie β this is real:
\n[.R]β Because GNU troff dynamically manages register storage, it repurposes the.Rregister to interpolate the maximum integer representable in the formatter. Favor its use over numeric literals with many zeroes or nines to indicate an arbitrary large quantity. π₯\n[.s]β In GNU troff, the.sregister is string-valued; it interpolates the type size in typographical points, which can be represented as a decimal fraction.\n[.x]β Interpolate major version number of the running troff formatter. For example, if the version number is1.23.0, then\n[.x]contains1.\n[.y]β Interpolate minor version number of the running troff formatter. For example, if the version number is1.23.0, then\n[.y]contains23. Also see\n[.Y]below. π¦
π New registers π
GNU troff exposes more formatter state via many new read-only registers. Their names often correspond to the requests that affect them. It's giving formatter lore, and honestly? Iconic.
\n[.br]β Within a macro definition, interpolate1if the macro is called with the βnormalβ control character (β.β by default), and0otherwise. This facility allows requests to be reliably wrapped by a macro. Interpolating the.brregister outside of a macro definition makes no sense. π\n[.C]β Interpolate1if AT&T troff compatibility mode is in effect,0otherwise. Seecp.\n[.cdp]β Interpolate depth of last glyph added to the environment. It is positive if the glyph extends below the baseline.\n[.ce]β Interpolate count of input lines remaining to be centered in the environment.\n[.cht]β Interpolate height of last glyph added to the environment. It is positive if the glyph extends above the baseline.\n[.color]β Interpolate1if color output is enabled,0otherwise. π\n[.cp]β Within adorequest, interpolate the saved value of compatibility mode (see\n[.C]above).\n[.csk]β Interpolate skew of last glyph added to the environment. The skew of a glyph is how far to the right of the center of a glyph the center of an accent over that glyph is to be placed.\n[.ev]β Interpolate name of current environment. This is a string-valued register.\n[.fam]β Interpolate name of the environment's default font family. This is a string-valued register.\n[.fn]β Interpolate resolved name of the font selected in the environment. This is a string-valued register.\n[.fp]β Interpolate next free non-zero font mounting position.\n[.g]β Interpolate1. Test withiforieto check whether GNU troff is the formatter.\n[.height]β Interpolate the rescaled height of the environment's selected font, in scaled points. It is zero if the font height is not rescaled. See\H.\n[.hla]β Interpolate hyphenation language of the environment. This is a string-valued register.\n[.hlc]β Interpolate count of immediately preceding consecutive hyphenated lines in the environment.\n[.hlm]β Interpolate maximum number of consecutive hyphenated lines allowed in the environment.\n[.hy]β Interpolate automatic hyphenation mode of the environment.\n[.hydefault]β Interpolate hyphenation mode default of the environment.\n[.hym]β Interpolate hyphenation margin of the environment.\n[.hys]β Interpolate hyphenation space adjustment threshold of the environment.\n[.in]β Interpolate indentation amount applicable to the output line pending in the environment.\n[.int]β Interpolate1if the text most recently formatted in the environment was βinterruptedβ or continued with\c,0otherwise.\n[.it]β Interpolate count of input lines remaining in the environment's pending input trap.\n[.itc]β Interpolate1if the environment's pending input trap honors the output line continuation escape sequence (\c),0otherwise.\n[.itm]β Interpolate the name of the macro associated with the environment's pending input trap. This is a string-valued register.\n[.kern]β Interpolate1if pairwise kerning is enabled,0otherwise.\n[.lg]β Interpolate ligature mode.\n[.linetabs]β Interpolate1if line-tabs mode is enabled in the environment,0otherwise.\n[.ll]β Interpolate line length applicable to the environment's pending output line.\n[.lt]β Interpolate the environment's title line length.\n[.m]β Interpolate name of the environment's selected stroke color. This is a string-valued register.\n[.M]β Interpolate name of the environment's selected fill color. This is a string-valued register.\n[.ne]β Interpolate amount of space demanded by the most recentnerequest that sprang a page location trap. See\n[.trunc].\n[.nm]β Interpolate1if output line numbering is enabled in the environment (even if temporarily suppressed),0otherwise.\n[.nn]β Interpolate count of lines remaining in the environment for which numbering is suppressed while output line numbering is enabled.\n[.ns]β Interpolate1if no-space mode is enabled,0otherwise.\n[.O]β Interpolate output suppression level. See\O.\n[.P]β Interpolate1if the current page is selected for output,0otherwise. See-ocommand-line option totroff(1).\n[.pe]β Interpolate1during page ejection,0otherwise.\n[.pn]β Interpolate next page number (either that set bypn, or that of the current page plus1).\n[.ps]β Interpolate the environment's type size in scaled points.\n[.psr]β Interpolate the environment's most recently requested type size in scaled points.\n[.pvs]β Interpolate the environment's post-vertical line spacing amount.\n[.rj]β Interpolate count of input lines remaining to be right-aligned in the environment.\n[.slant]β Interpolate slant in degrees of the environment's selected font. See\S.\n[.sr]β Interpolate the environment's most recently requested type size in typographical points. This is a string-valued register.\n[.ss],\n[.sss]β Interpolate values of the environment's minimum inter-word space and supplemental inter-sentence space, respectively, in twelfths of the space width of the selected font.\n[.sty]β Interpolate the environment's selected abstract font style, if any. This is a string-valued register.\n[.tabs]β Interpolate the environment's tab stop settings (if any) in a form suitable for passage to thetarequest. This is a string-valued register.\n[.trap]β Interpolate the name of the next vertical position trap after the vertical drawing position. This is a string-valued register.\n[.trunc]β Interpolate amount of vertical space truncated by the most recently sprung page location trap, or, if the trap was sprung by annerequest, minus the amount of vertical motion produced by thenerequest. In other words, at the point a trap is sprung,\n[.trunc]represents the difference of what the vertical position would have been but for the trap, and what the vertical position actually is. See\n[.ne]. π\n[.U]β Interpolate1if in unsafe mode,0otherwise. See-Ucommand-line option totroff(1).\n[.vpt]β Interpolate1if vertical position traps are enabled,0otherwise.\n[.warn]β Interpolate warning mask. See section βWarningsβ oftroff(1).\n[.Y]β Interpolate revision number of the running troff formatter. For example, if the version number is1.23.0, then\n[.Y]contains0. Also see\n[.x]and\n[.y]above.\n[.zoom]β Interpolate magnification of the environment's selected font, in thousandths, or0if magnification unused. Seefzoom.
The following (writable) registers are set by the psbb request. π
\n[llx],\n[lly],\n[urx],\n[ury]β Interpolate the (upper, lower, left, right) bounding box values (in PostScript units) of the most recently processed PostScript image.
The following (writable) registers are set by the \w escape sequence. π¦
\n[rst],\n[rsb]β Like\n[st]and\n[sb], but taking account of the heights and depths of glyphs. In other words, these registers store the highest and lowest vertical positions attained by the argument formatted by the\wescape sequence, doing what AT&T troff documented\n[st]and\n[sb]as doing.\n[ssc]β The amount of (possibly negative) horizontal space to add to the last glyph before a subscript.\n[skw]β How far to right of the center of the last glyph in the\wargument, to place the center of an accent from a roman font over that glyph.
Other writable registers are as follows. Those relating to date and time are initialized using localtime(3) at formatter startup. β
\n[c.]β Interpolate input line number.\n[.c]is a read-only alias of this register.\n[hours]β interpolates the number of hours elapsed since midnight. time check, bestie β¨\n[hp]β interpolates the horizontal position relative to the position at the start of the input line. where u at on the line π\n[lsn],\n[lss]β interpolate the count of leading spaces on the input line and the amount of corresponding horizontal motion, respectively. space detective vibes π΅οΈββοΈ\n[minutes]β interpolates the number of minutes elapsed in the hour. minute by minute β±οΈ\n[seconds]β interpolates the number of seconds elapsed in the minute. seconds slay π\n[systat]β interpolates the return value of thesystem(3)function executed by the most recentsyrequest. system call receipts π§Ύ\n[slimit]β interpolates the maximum quantity of objects on troff's internal input stack (default:1000). If it's non-positive, there is no limit: recursion can continue until program memory is exhausted. no cap, but also no cap π\n[year]β interpolates the Gregorian year. AT&T troff's\n[yr]interpolates the Gregorian year minus 1900. calendar queen π
π Delimiters π
Okay so AT&T troff recognized slightly varying sets of delimiters when it was expecting numerical expressions (as with the \h escape sequence), string expressions (as with the \w escape sequence and tl request), and output comparisons (as in .if #foo#bar# .tm match). messy, but iconic in its own way π
GNU troff, when not in compatibility mode, recognizes a single consistent set of delimiters. Compatibility mode emulates AT&T troff only up to a point. GNU troff accepts leaders and tabs as delimiters, as well as Control+D (EOT or EOF), Control+H (BS or backspace), and Control+L (FF or form feed), all of which, when used as delimiters, cause AT&T troff to behave in ways difficult to predict. literally unpredictable energy, proceed with caution bestie π¨
π Miscellaneous π
A font not listed in the output device's DESC file's fonts directive is automatically mounted at the next available font position when it is selected. If you mount a font explicitly with the fp request, you should do so on the first unused position, which can be found in the .fp register. font parking spot rules π
Unparameterized string interpolation does not conceal the arguments to a macro being interpreted. Thus, in a macro definition, the call of another macro with the existing argument list,
.xx \\$@
is more efficiently done with
\\*[xx]\\
(that is, with string interpolation). The trailing backslashes prevent the final newline in the macro definition from being interpolated, potentially putting an unwanted blank line on the output. efficiency era β¨ See section βPunning Namesβ in groff(7).
If a font description file contains pairwise kerning information, glyphs from that font are kerned. Kerning between two glyphs can be inhibited by placing a dummy character \& between them. personal space for glyphs π«Ά
GNU troff keeps track of the nesting depth of escape sequence interpolations and other uses of delimiters, as in the tl request and the output comparison operator (that is, input like 'foo'bar' as a conditional expression), so the only characters you need to avoid using as delimiters are those that appear in the arguments you input, not any that result from interpolation. Typically, ' works fine. Use visible characters as delimiters in GNU troff, not US-ASCII controls like BEL (Control+G). The implementation of \$@ ensures that the double quotes surrounding an argument appear at an interpolation depth different from that of the arguments themselves. Similarly, in bracket-form escape sequences like \f[ZCMI], a right bracket ] does not end the sequence unless it occurs at the same interpolation depth as the opening [. In compatibility mode, no attention is paid to the interpolation depth. depth perception but make it troff π
In GNU troff, the tr request can map characters to the unbreakable space escape sequence \~ as a special case (tr normally operates only on characters). This feature replaces the odd-parity tr mapping trick used in AT&T troff documents, where a character, often ~, was βsacrificedβ by mapping it to βnothingβ, drafting it into use as an unadjustable, unbreakable space. (This feature was gratuitous even in early AT&T troff, which supported the \space escape sequence by 1976.) Often, it makes more sense to use GNU troff's \~ escape sequence instead, which has been adopted by every other active troff implementation except that of Illumos, as well as by the non-troff mandoc. Translation of a character to \~ is generally unnecessary, but might be employed to obtain an unbreakable space when the escape character will subsequently be disabled. space lore, unlocked π§
GNU troff permits tabs and spaces after the first dot on a control line that ends a macro definition. tiny flex, but a flex π
π FORMATTER OUTPUT π
okay so the page description language that GNU troff spits out is modeled after the one AT&T troff used, once AT&T hopped on the device-independent train in the early 1980s. and bestie, only the differences are documented right here β for the full tea, go read groff_out(5).
Glyph and font names can be literally any length you want, so postprocessors better not assume they're "at most two characters," because that assumption is so 1980s. A glyph that's getting formatted is always drawn from the current font β and like, in contrast to AT&T device-independent troff, drivers do not need to go searching through special fonts to find a glyph. slay.
Units
The argument to the s command is in scaled points β and those are units of points/n, where n is the argument to the sizescale command in the DESC file. The argument to the x H command? Also in scaled points. twin behavior π
Simple commands
If the tcommand directive is present in the output device's DESC file, GNU troff pulls out these two commands:
t xyz...β typeset the word xyz, i.e. set a sequence of ordinary glyphs named x, y, z, β¦, terminated by a space or a newline. An optional second integer argument is ignored (it exists so the formatter can generate an even number of arguments β king behavior tbh). Each glyph gets set at the current drawing position, and then the position is advanced horizontally by that glyph's width. The width comes from its metrics in the font description file, scaled to the current type size, then rounded to a multiple of the horizontal motion quantum. And if you want to emplace glyphs of special characters? Use theCcommand for that. π«Άu n xyz...β typeset the word xyz with track kerning. literally just liket, but after placing each glyph, the drawing position gets advanced horizontally a little extra bynbasic units. extra credit energy β¨
New commands implement color support:
mc cyan magenta yellowmdmg graymk cyan magenta yellow blackmr red green blue
These set the components of the stroke color with respect to the various color spaces. md resets the stroke color back to the default value, no cap. The arguments are integers in the range 0 to 65535. π
And there's a new device control subcommand available:
x u nβ ifnis 1, start underlining of spaces. Ifnis 0, stop underlining of spaces. This facility is needed for thecurequest in nroff mode and is ignored otherwise. π
Extended drawing commands
Heads up bestie: GNU pic does not produce troff escape sequences employing these extensions if its -n option is given. iykyk
Df nβ set the shade of gray used to fill geometric objects ton, which must be an integer.0corresponds to white and1000to black, and a grayscale ramp spans the two. A value outside this range uses the stroke color as the fill color. The fill color is opaque. Normally the default is black, but some drivers may provide a way of changing this.Dfis obsolete since 2002, superseded byDFgbelow. π«
The corresponding\D'f'escape sequence should not be used: its argument is rounded to an integer multiple of the horizontal motion quantum, which can limit the precision ofn. don't do it, bestie.
DC dβ draw a filled circle of diameterdwith its leftmost point at the drawing position.DE h vβ draw a filled ellipse, of horizontal axishand vertical axisv, with its leftmost point at the drawing position.Dp dx1dy1...dxndynβ draw a polygon with, fori=1,...,n+1, its ith vertex at the drawing position+jΞ£1(dxj,dyj). groff output drivers automatically close polygons, drawing a line from(dxn,dyn)back to(dx1,dy1). The drawing position is left at the last specified vertex, but fair warning: this may change in a future version of GNU troff. Heirloom Doctools troff, like DWB troff, by default does not close the polygon. In its groff compatibility mode, Heirloom closes the polygon but leaves the drawing position unchanged β that is, at the polygon's initial drawing position. messy but ok πDP dx1dy1...dxndynβ asDp, but draw a filled rather than a stroked polygon. glow-up moment β¨Dt nβ set the line thickness tonbasic units. AT&T troff output drivers use a thickness proportional to the type size; this is the GNU troff default. A negativenrequests this explicitly. Annof zero selects the smallest available line thickness. iconic.
okay so here's the drama: there's a difficulty in how the drawing position should be changed after these commands execute. And honestly? It has little importance to most users, since the output of GNU grn and pic doesn't depend on it. π
Given a drawing command of the form Dz x1y1...xnyn, where z is not c or e, AT&T troff treats each xi as a horizontal motion, each yi as a vertical one, and therefore assumes the width of the drawn object is iΞ£1xi, and its height is iΞ£1yi. (Verify its assumption about height by examining the st and sb registers after using such a drawing command in a \w escape sequence.) So after executing a D command of the form Dz x1y1...xnyn, the drawing position increases by (iΞ£1xi,iΞ£1yi).
For the sake of compatibility, GNU troff follows this rule β even though it frustrates extensions to the D command that set drawing parameters rather than rendering objects, which produces ugly results in the case of Dt and Df. it's also annoying for anything that doesn't parameterize objects as a series of vertices, like GNU troff's filled ellipse, DE. π In a future release, GNU troff and its output drivers may abandon the application of this assumption to drawing commands not explicitly specified in the AT&T "Troff User's Manual". You can ensure predictable output by enclosing drawing commands in the zero-motion escape sequence \Z. do with that what you will, bestie π«Ά
GNU troff implements fill color selection with another set of extensions:
DFc cyan magenta yellowDFdDFg grayDFk cyan magenta yellow blackDFr red green blue
These set the components of the fill color as described under the \M escape sequence above. DFd restores the device's default fill color. And the drawing position is not updated, in contrast to Df. subtle but important π
Device control syntax extension
GNU troff introduces a line continuation convention, permitting the argument to the x X command to contain newlines. A newline in the input is transformed to the sequence "newline+".
So when interpreting an x X command, a postprocessor should therefore be prepared for a plus sign after a newline β if it shows up, preserve the newline, discard the plus sign, and keep collecting the input into the argument of the x X command. A newline not followed by a plus sign terminates the x X command. periodt. One very chic application of this feature: embedding PostScript or PDF language command streams into troff output. π¦
GNU troff guarantees that the first three output commands it emits are as follows:
x T device
x res n h v
x init
like clockwork, every time π
π DEBUGGING π
In addition to AT&T troff's debugging features, GNU troff emits more error diagnostics when syntactical or semantic nonsense is encountered β and it supports several warning categories, the output of which can be selected with "warn". Also go peek at the -E, -w, and -W options of troff(1). π
A trace of the formatter's input processing stack can be emitted when errors or warnings occur, by means of the GNU troff -b option β or produced on demand with the backtrace request. main character debugging energy fr fr β¨
groff also adds more flexible diagnostic output requests (tmc and tm1). Examine the state of the formatter with requests that write lists of:
- defined colors (
pcolor) - composite character mappings (
pcomposite) - environments (
pev) - font translations (
pftr) - automatic hyphenation codes (
pchar) and exceptions (phw) - registers (
pnr) - open streams (
pstream) - page location traps (
pwh)
Requests can also disclose to the standard error stream the internal properties and representations of characters and classes (pchar), macros (and strings and diversions) (pm), and the list of output nodes corresponding to the pending input line (pline). obsessed, honestly π
π COMPATIBILITY MODE π
Okay so some syntactical and behavioral differences between AT&T and GNU troffs are thought too important to neglect, bestie β GNU troff therefore makes available a compatibility mode in an effort to keep documents prepared for AT&T troff rendering well. Iconic, honestly. π
Identifiers of arbitrary length may be GNU troffβs most obvious innovation. AT&T troff interprets .dsabcd as defining a string ab with contents cd. Normally, GNU troff interprets this input as calling a macro named dsabcd. AT&T troff also interprets \*[ and \n[ as interpolating a string or register, respectively, named [. GNU troff, however, normally interprets [ as bracketing a long name (with ] at the distal end). In compatibility mode, GNU troff interprets names in the traditional way β they thus can be two characters long at most. See the -C option in troff(1) and, above, the .C and .cp registers, and cp and do requests, for more on compatibility mode. π
The register \n[.cp] is specialized and may require a statement of rationale. When writing macro packages or documents that use GNU troff features and which may be mixed with other packages or documents that do not β common scenarios include serial processing of man pages or use of the so or mso requests β you may desire correct operation regardless of compatibility mode enablement in the surrounding context. It may occur to you to save the existing value of \n(.C into a register, say, _C, at the beginning of your file, turn compatibility mode off with .cp 0, then restore it from that register at the end with .cp \n(_C. At the same time, a modular design of a document or macro package may lead you to multiple layers of inclusion. You cannot use the same register name everywhere lest you βclobberβ the value from a preceding or enclosing context. The two-character register name space of AT&T troff is confining, but employing GNU troffβs more capacious one, as with .nr _my_saved_C \n(.C does not work in compatibility mode; the register name is too long. Employing the do request is no help: .do nr _my_saved_C \n(.C always saves zero to the register, because do turns compatibility mode off while it interprets its argument list. ππ«Ά
GNU troff normally tracks the interpolation depth of escape sequence parameters and other delimited structures, but not in compatibility mode. Peep the section called βMiscellaneousβ above βοΈ.
The escape sequences \f, \H, \m, \M, \R, \s, and \S are transparent to control character recognition at the beginning of an input line, or after the conditional expression of an if or ie request, only in compatibility mode. That is, upon interpreting them, GNU troff normally no longer recognizes a control character on the input line; but in compatibility mode, it does, just like AT&T troff. β¨
Normally, the syntax form \sn accepts only a single character (a digit) for n, consistently with other forms that originated in AT&T troff, like \*, \$, \f, \g, \k, \n, and \z. In compatibility mode only, a non-zero n must be in the range 4β39.
π¨ Legacy documents relying upon this quirk of parsing should migrate to another \s form.
[Background: The Graphic Systems C/A/T phototypesetter (the original device target for AT&T troff) supported only a few discrete type sizes in the range 6β36 points, so Ossanna contrived a special case in the parser to do what the user must have meant. Kernighan warned of this in the 1992 revision of CSTR #54 (Β§2.3), and more recently, McIlroy referred to it as a βliving fossilβ.] π¦π
π Other differences π
Okay so GNU troff is lowkey not gonna emit any output if it literally has nothing to format. Like, if your input document is just nr and tm requests, it treats that as empty and produces nothing on its standard output stream. AT&T troff, on the other hand, does, creating a blank page. π
Using C0 control characters in identifiers is not portable, bestie. Solaris, Plan 9, and Heirloom Doctools troffs accept Control+B, Control+C, Control+E, Control+F, and Control+G (only); DWB 3.3 troff does not. GNU troff rejects C0 controls in identifiers with an error diagnostic. π«
Formatters that don't implement GNU troff extension request names tend to ignore them, and if they don't support a GNU troff extension escape sequence, they are liable to format its function selector character as text. For example, the adjustable, non-breaking space escape sequence \~ is also supported by Heirloom Doctools troff 050915 (September 2005), mandoc 1.9.5 (2009-09-21), neatroff (commit 1c6ab0f6e, 2016-09-13), and Plan 9 from User Space troff (commit 93f8143600, 2022-08-12), but not by Solaris or Documenter's Workbench troffs, which both render it as β~β. The \A escape sequence (see subsection βEscape sequencesβ above) may be helpful in avoiding their use. β¨
AT&T troff discards trailing spaces from input lines, like GNU troff, but when it does so, AT&T troff also cancels end-of-sentence detection. Use of the dummy character escape sequence \& is more portable. π
When adjusting output lines to both margins, AT&T troff at first adjusts spaces starting from the right; GNU troff begins from the left. Both implementations adjust spaces from opposite ends on alternating output lines in this adjustment mode to prevent βriversβ in the text. π
GNU troff does not always hyphenate words as AT&T troff does. The AT&T implementation uses a set of hard-coded rules specific to U.S. English, while GNU troff uses language-specific hyphenation pattern files derived from TeX. Some versions of troff reserved meager storage for hyphenation exception words (arguments to the hw request); GNU troff has no such restriction. When the hy request is invoked without an argument, GNU troff sets the automatic hyphenation mode to the value of the .hydefault register; the AT&T implementation sets it to β1β, which is not suitable in GNU troff for some languages, including English. π
Unlike GNU troff, AT&T troff does not recognize an occurrence of \% at the beginning of a word as suppressing its hyphenation; instead, it (uselessly) marks the start of the word as a potential hyphenation point, permitting output lines to end with hyphens that are not interior to a word. π
GNU troff handles the dummy character \& differently from AT&T troff when it is followed by the hyphenation control escape sequence \% at the beginning of a word. GNU troff does not regard the dummy character as βstartingβ the word; AT&T troff does. Further, Heirloom Doctools troff does not honor an explicit hyphenation point marked with \% after a word-initial one. π
GNU troff interprets request arguments representing file names and system commands in the same way it does the contents argument to the ds and βasβ requests: it removes a leading neutral double quote β"β from the argument to the cf, nx, pi, βsoβ, and sy requests, and the second argument (if present) to the lf request, permitting initial embedded spaces in it, and reads it to the end of the input line in copy mode. This difference permits the formatter to handle files with spaces in their names, but requires more care with trailing comments, and doubling of an initial neutral double quote β"β if the file name has one. π
The existence of the .T string is a common feature of device-independent troffsβDWB 3.3, Solaris, Heirloom Doctools, and Plan 9 troff all support itβbut valid values are specific to each implementation. π
The (read-only) register .T interpolates 1 if GNU troff is run with the -T option, and 0 otherwise. In contrast, AT&T troff interpolated 1 only if nroff was the formatter and was run with -T. π€―
AT&T troff ignored attempts to remove read-only registers; GNU troff honors such requests. π
The lf request sets the number of the current input line in AT&T troff, and the next in GNU troff. π
AT&T troff had only environments named β0β, β1β, and β2β. In GNU troff, any number of environments may exist, using any valid identifiers for their names. π
As noted above in βFractional type sizes and new scaling unitsβ, AT&T troff's ps request ignores scaling units and thus β.ps 10uβ sets the type size to 10 points, whereas in GNU troff it sets the type size to 10 scaled points, possibly a much smaller measurement. AT&T's behavior also means that β.ps 10pβ and β.ps 10zβ are portable. π―
The ab request differs from AT&T troff: GNU troff writes no message to the standard error stream if no arguments are given, and it exits with a failure status instead of a successful one. π
The bp request differs from AT&T troff: GNU troff does not accept a scaling unit on the argument, a page number; the former does (uselessly). π₯΄
In AT&T troff the pm request reports macro, string, and diversion sizes in units of 128-byte blocks, and an argument reduces the report to a sum of the above in the same units. GNU troff reports their lengths in characters or nodes if given no arguments, and otherwise dumps the JSON-encoded name, contents, and other properties of each named argument. π
AT&T troff ignores the ss request if the output is a terminal device; GNU troff rounds down the values of minimum inter-word and additional inter-sentence space each to the nearest multiple of 12. β¨
GNU troff distinguishes characters from glyphs. Characters can be ordinary, special, or indexed, and populate strings and macros. Characters per se have not (yet) been formatted. Glyphs represent graphemes (supplied by the output device) and populate diversions. Formatting converts characters into (sequences of) glyphs. GNU troff stores properties of the environment that affect how a glyph is rendered with the glyph node's data. Thus, subsequent formatting operations do not affect it, including bd, cs, tkf, tr, and fp requests. Normally, a macro or string contains only a list of characters and a diversion contains only a list of nodes. However, applying the asciify or unformat requests to a diversion converts some of its nodes back into characters. Where the formatter cannot recover the character representation of a node, it stores a null character in the character list corresponding to a single node in the node list. Consequently, a glyph node does not behave as a character does in macro interpolation: it does not inherit special properties that the character from which it was constructed might have had. π§¬
One way to format a backslash in most documents is with the \e escape sequence; this formats the glyph of the current escape character, regardless of whether it is used in a diversion; it also works in both GNU troff and AT&T troff. (Naturally, if you've changed the escape character, you need to prefix the βeβ with whatever it isβand you'll likely get something other than a backslash in the output.) π
The other correct way, appropriate in contexts independent of the backslash's common use as a roff escape characterβperhaps in discussion of character sets or other programming languagesβis the special character escape sequence \(rs or \[rs], for βreverse solidusβ, from its name in the ECMA-6 and ISO 10646 standards. [AT&T troff 's font description files did not define the rs special character, but those of its descendant Heirloom Doctools troff do, as of its 060716 release (July 2006).] π
To store an escape sequence in a diversion that is interpreted when the diversion is interpolated, either use the traditional \! transparent output facility, or, if this is unsuitable, the new \? escape sequence. See subsection βEscape sequencesβ above and sections βDiversionsβ and βGNU troff Internalsβ in Groff: The GNU Implementation of troff, the groff Texinfo manual. π«Ά
Like AT&T troff, GNU troff maintains a buffer of device-independent output commands, populating the buffer as formatted output accumulates. GNU troff always flushes this buffer when processing a break; AT&T troff does so according to no obvious schedule (perhaps, if the buffer is of fixed size, the formatter performs the flush when the buffer runs out of room). π§Ί
In the somewhat pathological case where a diversion exists containing a partially collected line and a partially collected line at the top-level diversion has never existed, AT&T troff outputs a partially collected but otherwise empty line (as if β\cβ were in the top-level diversion) at the end of input; GNU troff does not. π³οΈ
π₯ Formatter output incompatibilities π₯
Its extensions notwithstanding, GNU troff's page description language has some incompatibilities with that of AT&T troff, but better compatibility is sought; problem reports and patches are welcome. The following incompatibilities are known. π
- The drawing position after rendering polygons is inconsistent with AT&T troff practice. Other implementations have diverged on this point as well. π
- The output cannot be easily rescaled to other devices as AT&T troff's could. π±
π Authors π
This document was written by James Clark, Werner Lemberg, Bernd Warken, and G. Branden Robinson. βοΈ
π See also π
Groff: The GNU Implementation of troff, by Trent A. Fisher and Werner Lemberg, is the primary groff manual. You can browse it interactively with βinfo groffβ. π
β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, widely called simply βCSTR #54β, documents the language, device and font description file formats, and page description language referred to collectively in groff documentation as AT&T troff. ποΈ
βA Typesetter-independent TROFFβ by Brian W. Kernighan, 1982, AT&T Bell Laboratories Computing Science Technical Report No. 97, provides additional insights into the device and font description file formats and page description language. π§
Also go peek at groff(1), groff(7), and roff(7). π
This absolute icon of a page is from groff 1.24.2, dated 2026-10-01, and it's groff_diff(7) β mwah, love u, bye bestie ππ
π¦ where this page comes from
- alpine 3.24: groff-doc 1.24.2-r0 Β· GPL-3.0-or-later
- Copyright 1989-2024 Free Software Foundation, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms