Beautiful Documents with Groff (Part I)
The TXR manual is written in troff. It&#x27;s designed so that you can install it as a man page, but it has macros which retarget some of the formatting for HTML and PDF.  When compiled to PDF, it comes out to over 900 pages.<p>It may be the only man page you will ever see which auto-numbers its sections (down to three levels deep). I developed the macros for all that.<p>Pretty  much any large or large-ish man page you can think of does not have this feature.  E.g. type &quot;man gcc&quot; or &quot;man bash&quot;: no section numbers anywhere.<p>I use Lucifredi&#x27;s man2html converter from the man1.6 package. I think this is mostly abandonware. The man2html program is essentially a hacky reimplementation of enough of a subset of nroff to crank simple man pages into HTML. It does a better job than any other converter.  (There is at least one more thing called man2html, like one unrelated program written in Perl.)<p>I made some 30 commits to man2html, fixing bugs, adding some features, and making it understand and execute complex nroff macro definitions. One feature added is that man2html defines a variable M2 which the code can use to conditionally switch to code specific to man2html versus regular nroff. All that work is here:<p><a href="https:&#x2F;&#x2F;www.kylheku.com&#x2F;cgit&#x2F;man&#x2F;log&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.kylheku.com&#x2F;cgit&#x2F;man&#x2F;log&#x2F;</a><p>Anyone wanting to reproduce the HTML version of the TXR manual needs that version of man2html. A TXR program called genman.txr, in the root of the TXR source tree, analyzes the man2html output, and rearranges it, adds identifier cross-referencing, a collapsible table of contents (via a tiny bit of JS) and such.<p>I use another TXR program for running checks for common markup mistakes in the manual: checkman.txr in the root of the TXR source tree. It understands the usage of many of my custom macros and validates that they are correctly used, in their intended structures. For instance if a syntax synopsis block is opened with .synb, it will tell you there is a missing .syne closer.<p>There are &quot;weird&quot; formatting macros; e.g:<p><pre><code>  .coNP Operators @ let and @ let*
  .synb
  .mets (let &gt;&gt; ({ sym | &gt;&gt; ( sym &lt;&lt; init-form )}*) &lt;&lt; body-form *)
  .mets (let* &gt;&gt; ({ sym | &gt;&gt; ( sym &lt;&lt; init-form )}*) &lt;&lt; body-form *)
  .syne
  .desc
  The
  .code let
  and
  .code let*
  operators introduce  ...
</code></pre>
<i>coNP</i> is like <i>NP</i>, introducing a paragraph at a certain subsection level; the <i>co</i> refers to it having code markup. In <i>co</i> markup, a word preceded by @ will be typeset as code, e.g. typewriter font.  A word preceded by @, (at comma) will be typeset in a typewriter font, followed immediately by a comma in the original font.<p>.synb starts the syntax synopsis section and .synb ends it.<p>We use .mets for markup in the syntax synopsis. The &quot;met&quot; refers to &quot;meta&quot;: markup for meta-syntactic identifiers, which typically use italic in HTML and PDF of angle brackets like &lt;sym&gt; in the plain text man page.<p>In .mets, everything is typewriter by default.   When an argument is preceded by &lt;, it is marked up as a meta identifier, italic or &lt;angle&gt;.   When two arguments are preceded by &lt;&lt;, like &lt;&lt; body-form *) the left one is meta, and the right one is tacked onto it with no intervening space.  There is also &lt;&gt; with three arguments: &lt;&gt; A B C will typeset B as a meta, flanked by A and C with no space; and there is an opposite &gt;&lt; also.<p>All these macros are defined near the top of the txr.1 file.<p>The &quot;meta&quot; markup is implemented by lower-level macro called .getm which the higher level ones like .mets and .meti and .meIP use. That macro is implemented twice, conditionally switched for nroff mode (angle brackets) and regular (font switching).