groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: groff now undoing .ad settings after .IP


From: G. Branden Robinson
Subject: Re: groff now undoing .ad settings after .IP
Date: Fri, 15 Mar 2024 08:33:54 -0500

Hi Russ,

Executive summary: go ahead with your "other obvious option".

For the non-executives, it appears to be Story Hour.

At 2024-03-14T22:02:26-0700, Russ Allbery wrote:
> pod2man has, for a couple of decades, added:
> 
>     .if n .ad l
> 
> to the top of every generated man page after the .TH macro on the
> grounds that, for an output device that only has full-width spaces and
> no support for subtle adjustments of interword spacing, ragged right
> is a more readable default than full justification.

I began composing a hyperlink-heavy paragraph explaining the historical
background of this issue, prepared to marshal against your claim
authorities who had judged differently, when I experienced a Hitchcock
zoom on my slackjawed face.

To set the scene, I keep a directory full of man(7) implementations
lying around, for research and testing purposes (to see how well groff
handles them).

$ for f in $(find HISTORY/MAN -name "tmac.an*"); do printf '%s:' "$f"; sed -n 
'/^\.de.*TH/{:X;n;/^\.\./q;p;bX}' "$f" | grep -E '\. *(ad|na)'; done | sort
HISTORY/MAN/1979-01-v7/tmac.an:.if n .na
HISTORY/MAN/1980-03-3BSD/tmac.an.new:.if n .na
HISTORY/MAN/1980-10-4BSD/tmac.an.new:.if n .na
HISTORY/MAN/1982-12-4.1cBSD/tmac.an.new:.if n .na
HISTORY/MAN/1983-09-4.2BSD/tmac.an.new:.if n .na
HISTORY/MAN/1986-06-4.3BSD/tmac.an.new:.if n .na
HISTORY/MAN/1987-01-4.3BSD-UWisc/tmac.an.new:.if n .na
HISTORY/MAN/1988-06-4.3BSD-Tahoe/tmac.an.new:.if n .na
HISTORY/MAN/1990-06-4.3BSD-Reno/tmac.an.old:.if n .na
HISTORY/MAN/1993-06-4.4BSD/tmac.an:.if n .na

For those not practiced at deciphering sed, what I did was effectively
just grep the `TH` macro definition in each of these files.

So.  You're right and at some point _groff_ made the innovation of
adjusting output lines to both margins in man pages by default even in
nroff mode.  That you've carried this code in pod2man "for a couple of
decades" suggests that, despite being one of the Usual Suspects, I can
abscond from this scene, leaving the coppers grumbling that they didn't
have the goods on me.  This time.

The decision would appear to be James Clark's, made at the very dawn of
groff.

https://minnie.tuhs.org/cgi-bin/utree.pl?file=Net2/usr/src/usr.bin/groff/macros/grot/tmac.an
https://minnie.tuhs.org/cgi-bin/utree.pl?file=Net2/usr/src/usr.bin/groff/VERSION

...making this an interesting case of Perl being more Catholic than the
Pope with respect to man page adjustment in nroff mode.[0]

> This broke in groff 1.23.0.

Yes.  Here's the NEWS item, which also appeared in the release
announcement[1].

o The an (man) and doc (mdoc) macro packages support a new `AD` string
  to put the default adjustment mode under user control at rendering
  time.  The default is "b" (adjust lines to both margins) as has been
  the Unix man(7) default since 1979.

Admittedly, this doesn't come right out and say, "the package works
harder to ensure that whatever adjustment mode is in place when the page
starts rendering is the one it sticks with throughout".  That aspect of
it, I considered more of a bug fix, and as a rule we don't announce bug
fixes in the NEWS file.

And the last five words of that NEWS item, I now see, are misleading.  I
hadn't looked at Seventh Edition Unix _nroff_ output, just the nicely
typeset manuals.  I'll fix that right away.

> Now, any .TP directive restores full justification for all subsequent
> text.  This appears to be due to the addition of:
> 
> .  ad \\*[AD]
> 
> in an-write-paragraph-tag.  I'm not sure why this was added,

Here's the commit message.

https://git.savannah.gnu.org/cgit/groff.git/commit/?id=e7094b209f0f39fc16de687f116ea9a9c1ba0364

The larger context within which I did this was a laborious project to
get batch man page rendering well; that is, running groff with a long
list of man page documents as arguments and fulfilling the promise of
andoc.tmac, which was documented as being able to seamlessly switch back
and forth between packages.  What I wanted was for people to be able to
produce a book of man pages at one stroke without a lot of fiddling,
complete with consecutive page numbering (and, in the longer run,
internally hyperlinked man page cross references, expected in groff
1.24).  Attempting this exposed numerous bugs in our man(7) and mdoc(7)
implementations.

Initially I used only groff's own corpus of man pages to measure my
progress.  This was good _and_ bad, because the authors of _groff's_ man
pages tend to have above-average competence with the formatter language.
(Way too much, in the view of mandoc(1) maintainer Ingo Schwarze, I
think.)  They also know, by instinct or experience, "what not to do".

So, when Alex Colomar applied the book-production approach to the much
larger collection of the Linux man-pages project--and I'll first point
out that the overall quality of the pages there from a macro language
usage perspective was high--there _were_ some bad habits and
unrecommended practices upon which some contributors leaned, and a
couple or three that got copied and pasted around with abandon.

Two of these involved punching through the floor: going around the macro
language to use *roff requests to manipulate hyphenation and adjustment.

There are two problems with doing that.

1.  Generally, when a man page author moves one of these things, they
    don't put it back at the end of the man page.  I'm sure many people
    would argue that they shouldn't have to, that the macro package
    should reset to defaults when it processes a new page.  And indeed,
    groff 1.23 does so more carefully than earlier versions did.  That
    same commit above is the one where, apparently for the first time
    ever, groff man(7) re-initialized the adjustment mode upon
    processing a new page (interpolating the `TH` macro).

2.  The man page author doesn't know what the reader's preferences are.
    A formative experience for me was encountering the procps-ng ps(1)
    man page as it existed in the late 1990s, where a contributor
    prepared the Worst Man Page That Has Ever Existed,[2] contemptuously
    thrusting aside all manner of common practice in man page
    composition and arrangement, and going out of his way to employ
    formatter features to revert package defaults.  All this due to his
    personal antipathy for man(7), expressed acidly in the comments at
    the top of the file, ensuring that any poor bastard of a Linux user
    who just wanted to understand ps's Byzantine and multiple-impedance
    interface ("Options?  We got both kinds!  AT&T _and_ BSD!") would be
    unable to read the man page without the page author's "See Figure 1"
    diagram[3] overlaying their vision for as long as the man page
    remained on the screen.  Nope, didn't need any fancy compositing
    alpha-blending window manager for _that_ message to come through.

It's one of the rudest and most antisocial things I've ever seen in
FLOSS development.  Our colleagues in Debian noticed and the author of
the page refused to concede any point.  He had delivered his masterwork
and anyone who questioned it could just eff off.[4]

I reckon he enjoyed a lucrative career.

> but I've already gotten multiple complaints about full justification
> cropping up in pod2man-generated man pages with current versions of
> groff.

I'm sorry for that.  :(

> Assuming this is intentional, is there some way that I can avoid this
> change in behavior shy of the brute force approach of adding .if n .ad
> l after every .TP tag?  That seems fairly ugly and also further
> undermines the intent of the AD register.

I agree; that would be a poor approach.

> The other obvious option is:
> 
>     .if n .ds AD l
> 
> before the .TH macro, which will technically work and which doesn't
> really break anything that isn't already broken because
> pod2man-generated man pages currently break the intent of the AD
> register anyway, but groff_man(7) makes it clear that you don't want
> me to do that and I do understand why.

Right.

> I would be happy to support the AD register and let the user choose if
> they have an explicit preference.  I just want to change the default
> under nroff to l to stay consistent with the past 20 years of pod2man
> output.  Maybe we can find some way that I can signal to the an macro
> set that I want a different default when running under nroff, but am
> happy to have my chosen default overridden by the AD register if it's
> set?

My first idea was this:

Before calling `TH`, do this:

.\" This is Perl; we live and work on the ragged right edge.
.if !d AD \
.  if n .ds AD l\"

...but that won't work because the package has already been _loaded_
("nroff -man perlre"), and the formatter interprets its last line before
the first of your man page.  So, to any man page, the contents of the
`AD` string already _look like_ the user's preference.

Hmm.  I need to gnaw on this.  The other ideas I've had, I don't like.

If I don't get back to you soon enough, go ahead with your initial idea.

    .if n .ds AD l

You'll want to keep

>     .if n .ad l

for the sake of non-groff formatters, of course.

Translators from another documentation format to man(7) _always_ give up
_some_ *roff (or even man(7)) features.  As you noted, Perl users are
already long unaccustomed to being able to persistently configure the
adjustment mode.  If they discover groff 1.23 man(7)'s 'AD' feature and
fall in love with it--I refuse to place a wager on this--you'll hear
from them.

But if I catch an author of an ordinary man(7) document doing this in a
page intended for distribution to the general public, I will send Jamie
MacDonald and Malcolm Tucker to remonstrate with them.  Respect the user
or else.

> (I understand that I can explain to users that they can set MANROFFOPT
> to -dAD=l

Or edit their man.local file as groff_man_style(7) illustrates:

     /etc/groff/man.local
            Put site‐local changes and customizations into this file.

                   .\" Put only one space after the end of a sentence.
                   .ss 12 0 \" See groff(7).
                   .\" Keep pages narrow even on wide terminals.
                   .if n .if \n[LL]>80n .nr LL 80n

            On multi‐user systems, it is more considerate to users whose
            preferences may differ from the administrator’s to be less
            aggressive with such settings, or to permit their override
            with a user‐specific man.local file.  Place the requests
            below at the end of the site‐local file to manifest
            courtesy.
                   .soquiet \V[XDG_CONFIG_HOME]/man.local
                   .soquiet \V[HOME]/.man.local
            However, a security‐sandboxed man(1) program may lack
            permission to open such files.

> to get this behavior for every man page, and I like that this option
> exists, but I'm not willing to take the regression and support hit of
> having to explain this to every user.)

I don't blame you.  Even if we were to change groff's default (for nroff
mode only, nobody hyperventilate) to restore historical authenticity
for groff 1.24,[5] you've got users with 1.23 installed who are pleading
for relief _now_.  And I will not counsel you to withhold it.

Regards,
Branden

[0] Since Doug McIlroy is still alive, maybe he's still the Pope in
    question, meaning James Clark held one of the other four
    Patriarchies.

    I should consider discarding the old cliché in favor of saying "more
    Orthodox than the Patriarch of Antioch".

[1] https://lists.gnu.org/archive/html/info-gnu/2023-07/msg00001.html
[2] 
https://gitlab.com/procps-ng/procps/blob/7ac9a0e1f5606696dc799b773d5ec70183ca91a3/ps/ps.1
[3] https://hald.ddns.us/postings/see-figure-1.html

[4] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=35137
    https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=45509

    For more from this luminary, see:

    https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=46442

[5] For the next groff release, I've reverted one of James Clark's groff
    man(7) innovations already: the base paragraph indentation amount.

    
https://git.savannah.gnu.org/cgit/groff.git/commit/?id=5d2e49f8182afc9bf210b7f6dd18e465319fef7b
    
https://git.savannah.gnu.org/cgit/groff.git/commit/?id=ab9e82cd9716d929051eedfb104d227a02c964e5

    I have mixed feelings about the adjustment issue.

    We're getting close to 35 years of ".ad b" being _groff's_ default,
    and even if I think a lot of people won't consciously notice the
    base paragraph indentation change--instead observing that, "huh,
    lines fit now when they didn't used to, that's nice, but
    weird"--_everybody_ will notice a change to adjustment, and some
    will be as loud and destructive as the author of the Worst Man Page
    That Has Ever Existed was.  I think it virtuous to stand up to
    brogrammers.

    Further, adjusting to both margins in man pages in nroff mode
    _exercises the adjustment code_--hell, it torture-tests it--and that
    is a good thing, because adjustment is so tricky.  I was looking at
    Heirloom Doctools nroff/man output the other day (while preparing
    patches for ncurses) and they actually have problems here.
    Occasionally, fell stars align and they set an output line with
    about a tab stop's worth of extra length, apparently thanks to some
    space that gets radically expanded _even when not adjusting to both
    margins_.  It's a crazy weird bug; one I'm glad we don't have.

    On the third hand, adjusting to both margins frequently frustrates
    me when I'm regression testing proposed patches to man pages that I
    submit to other projects, because of the "adjustment parity
    problem".[6]

    On the fourth hand, the previous point is a niche practice compared
    to people passively consuming man pages.  I know how to fix the
    adjustment dynamically (and how to script doing so), and changing
    things to better benefit expert users at the expense of novice ones
    can be discouraging to the latter.

[6] https://savannah.gnu.org/bugs/?57836

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]