Thread (5 messages) 5 messages, 4 authors, 2025-05-23

Re: Learning man(7)

From: Zack Weinberg <hidden>
Date: 2025-05-23 16:22:45

[off topic for libc-alpha]

On Sat, May 17, 2025, at 8:01 PM, G. Branden Robinson wrote:
[shameless promotion of (in part) my own work follows]

I've tried hard over the past several years to make man(7) easy to
acquire.  I'm attaching a PDF of the groff_man_style(7) man page
(rendered with the forthcoming groff 1.24), which attempts the oft-
questioned objective of serving as both tutorial and a reference. I
seldom receive feedback on it, which means either that it's flawless
or no one reads it.
I regret to say that I think most people who attempt to read this
document will give up on it after only a few sentences.  It is densely
written, presents its material in a sequence that doesn't make any sense
to me, and frequently uses jargon that I only understand because I
already know the essentials of the troff markup language.

I suggest that you should look at the overall structure of the Texinfo
manual (https://www.gnu.org/software/texinfo/manual/texinfo/html_node/),
and reorganize your guide along similar lines.  The Texinfo manual is
not perfect, but it was written with a lot of care and attention
put into organizing the material into a sequence that will make sense to
someone who is brand new to writing documentation in a markup language.

Avoid forward references to definitions of terms at almost any cost.
Forward references to sections that will go into more detail on something
that was just mentioned are often a good idea, but make sure enough
detail was presented up front that a beginner knows enough to keep
reading!  Relegate information that most people don't need to know, such
as the specifications of deprecated macros and the portability quirks of
Solaris troff, to the very end.

Whenever possible, avoid troff-specific jargon; for example, instead of
talking about "input traps", which are a detail of how troff macros work
internally, say something like

.SH [heading-text]
    Set _heading-text_ as a section heading.  If .SH appears by itself
    on a line, the next normal line of input is used as _heading-text_.

Don't try to avoid repeating this language; write it out in full for
every macro that has this property.  In general, decompress your
language; take the time to spell everything out rather than relying on
words with precise definitions that readers might not already know,
whether or not they are defined in the text.  (Rudolf Flesch wrote two
excellent books on how to do this well, *The Art of Readable Writing* and
*The Art of Plain Talk*, which I recommend to everyone seeking to improve
their technical writing.)

Add lots and lots and lots of examples.

For a concrete example of the kind of change I would suggest you make,
take these sentences near the beginning:

    A roff document can contain control lines, which start with a dot (.)
    or neutral apostrophe ('). All other input lines are text lines to be
    formatted. A macro collects control and/or text lines to ease document
    composition.

There is a _ton_ of implicit knowledge referenced by these sentences.
Much of that knowledge does appear later in the document, but a reader
who isn't already familiar with troff won't be able to get that far,
because they need all that knowledge to continue reading!  I would
expand those sentences to all of this:

    The roff markup language is line-oriented; with a few exceptions,
    every construct consists of one or more whole input lines.  As usual
    for Unix programs, all input lines, including the very last one,
    must be ended with the "newline" character, ASCII LF (U+000A);
    the "carriage return" character (U+000D) should not be used.

    Each input line of a roff document is either a _text line_ or a
    _control line_.  Control lines start with either a dot (.) or a
    neutral apostrophe ('); the only difference is that control lines
    beginning with . sometimes force a line break in the output.
    Generally you should write all your control lines beginning with .,
    and then change dots to apostrophes only when you discover
    undesirable line breaks. Lines beginning with any other character
    are text lines.

    Most control lines invoke either a _macro_ or a primitive _request_,
    by naming the macro or request immediately after the . or the '.
    This will have some concrete effect on the typeset output, as we will
    explain throughout the rest of this guide.  A control line that
    _doesn't_ invoke anything has no direct effect, but can still
    be useful; we will also discuss this more below.

        This is a text line.
        .SH \" This is a control line, invoking the SH macro.
        .br \" This is a control line, invoking the br request.
        .   \" This is a control line that doesn't invoke anything.

    The distinction between macros and requests is usually not important
    unless you are writing your own "macro package."  However, by
    convention, macros have UPPERCASE names, and primitive requests have
    lowercase names.  Because roff is a very old markup language, the
    names are usually very short---one or two characters at most.  (GNU
    groff supports longer names but other implementations do not.)

    Both macros and requests frequently take _arguments_, consisting of
    the rest of the text on the control line, after their name.  For
    readability and ease of editing, control lines can be extended onto
    multiple physical input lines by putting a backslash (\, U+005C) at
    the very end of each input line but the last one.  (This also works
    for text lines, but it is almost never _needed_ for text lines.)

        .SH Arguments to the SH macro: text of a section heading.

        .SS A very long subsection heading that was split onto \
            two physical input lines.

    Backslash can also appear in the middle of a line, in which case
    it begins an _escape sequence_.  One escape sequence already
    appeared in the first group of examples above: \", which begins
    a comment--the \" and everything after it on that input line are
    discarded and have no effect on the output.  Thus, in those
    examples, the SH macro and the br request did not receive any
    arguments.

    Another escape sequence is \&, which inserts a "dummy character".
    It has no visible effect on the formatted output, but you can use
    it to begin a text line with either . or ':

        \&. This is a text line whose text begins with '.'.

    More escape sequences will be described below.

    For maximum portability, roff input should be restricted to ASCII;
    see the "Portability" section for precise details of what characters
    are permissible, and the "Special character escapes" section for how
    to typeset non-ASCII characters.  GNU groff supports input in Unicode
    (by means of the preconv(1) helper program).

Naturally, one can then remove *some* of this detail from later sections.
However, keep in mind that a little bit of repetition helps to embed
information in the reader's mind.

I hope this is useful to you.

zw
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help