Because roff formatters process their input in a single pass,
material on page 50, for example, cannot influence what appears on
page 1—this poses a challenge for a table of contents at its
traditional location in front matter, if you wish to avoid manually
maintaining it. ms enables the collection of material to be
presented in the table of contents as it appears, saving its page number
along with it, and then emitting the collected contents on demand toward
the end of the document. The table of contents can then be resequenced
to its desired location by physically rearranging the pages of a printed
document, or as part of post-processing—with a sed(1)
script to reorder the pages in troff’s output, with
pdfjam(1), or with gropdf(1)’s
‘.pdfswitchtopage’ feature, for example.
Define an entry to appear in the table of contents by bracketing its
text between calls to the XS and XE macros. A typical
application is to call them immediately after NH or SH and
repeat the heading text within them. The XA macro, used within
‘.XS’/‘.XE’ pairs, supplements an entry—for instance, when
it requires multiple output lines, whether because a heading is too long
to fit or because style dictates that page numbers not be repeated. You
may wish to indent the text thus wrapped to correspond to its heading
depth; this can be done in the entry text by prefixing it with tabs or
horizontal motion escape sequences, or by providing a second argument to
the XA macro. XS and XA automatically associate
the page number where they are called with the text following them, but
they accept arguments to override this behavior. At the end of the
document, call TC or PX to emit the table of contents;
TC resets the page number to ‘i’ (Roman numeral one), and
then calls PX. All of these macros are Berkeley extensions.
.XS [page-number] ¶.XA [page-number [indentation]] ¶.XE ¶Begin, supplement, and end a table of contents entry. Each entry is
associated with page-number (otherwise the current page number); a
page-number of ‘no’ prevents a leader and page number from
being emitted for that entry. Use of XA within
XS/XE is optional; it can be repeated. If
indentation is present, a supplemental entry is indented by that
amount; ens are assumed if no unit is indicated. Text on input lines
between XS and XE is stored for later recall by PX.
.PX [no] ¶Switch to single-column layout. Unless no is specified, center
and interpolate the TOC string in bold and two points larger than
the body text. Emit the table of contents entries.
.TC [no] ¶Set the page number to 1, the page number format to lowercase Roman
numerals, and call PX (with a no argument, if present).
Here’s an example of typical ms table of contents preparation.
We employ horizontal escape sequences \h to indent the entries by
sectioning depth.
.NH 1 Introduction .XS Introduction .XE … .NH 2 Methodology .XS \h'2n'Methodology .XA \h'4n'Fassbinder's Approach \h'4n'Kahiu's Approach .XE … .NH 1 Findings .XS Findings .XE … .TC |
The remaining features in this subsubsection are GNU extensions.
groff ms obviates the need to repeat heading text after
XS calls. Call XN and XH after NH and
SH, respectively.
.XN heading-text ¶.XH depth heading-text ¶Format heading-text and create a corresponding table of contents
entry. XN computes the indentation from the depth of the
preceding NH call; XH requires a depth argument to
do so.
groff ms encourages customization of table of contents
entry production.
.XN-REPLACEMENT heading-text ¶.XH-REPLACEMENT depth heading-text ¶These hook macros implement XN and XH, respectively.
They call XN-INIT and pass their heading-text arguments to
XH-UPDATE-TOC.
.XN-INIT ¶.XH-UPDATE-TOC depth heading-text ¶The XN-INIT hook macro does nothing by default.
XH-UPDATE-TOC brackets heading-text with XS and
XE calls, indenting it by 2 ens per level of depth beyond
the first.
We could therefore produce a table of contents similar to that in the previous example with fewer macro calls. (The difference is that this input follows the “Approach” entries with leaders and page numbers.)
.NH 1 .XN Introduction … .NH 2 .XN Methodology .XH 3 "Fassbinder's Approach" .XH 3 "Kahiu's Approach" … .NH 1 .XN Findings … |
To get the section number of the numbered headings into the table of
contents entries, we might define XN-REPLACEMENT as follows.
(We obtain the heading depth from groff ms’s internal
register nh*hl.)
.de XN-REPLACEMENT .XN-INIT .XH-UPDATE-TOC \\n[nh*hl] \\$@ \&\\*[SN] \\$* .. |
You can change the style of the leader that bridges each table of
contents entry with its page number; define the TC-LEADER special
character by using the char request. A typical leader combines
the dot glyph ‘.’ with a horizontal motion escape sequence to
spread the dots. The width of the page number field is stored in the
TC-MARGIN register.