ms TOC (The GNU Troff Manual)

Next: Differences from AT&T `ms`, Previous: Multiple columns, Up: Page layout [Contents][Index]

#### 4.6.6.5 Creating a table of contents

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.

Macro: `.XS` [page-number] ¶
Macro: `.XA` [page-number [indentation]] ¶
Macro: `.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`.

Macro: `.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.

Macro: `.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.

Macro: `.XN` heading-text ¶
Macro: `.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.

Macro: `.XN-REPLACEMENT` heading-text ¶
Macro: `.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`.

Macro: `.XN-INIT` ¶
Macro: `.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.

Next: Differences from AT&T `ms`, Previous: Multiple columns, Up: Page layout [Contents][Index]