Hi Alex,

At 2025-05-02T12:56:51+0200, Alejandro Colomar wrote:
> I'd like to understand why groff(1) formats differently a paragraph
> depending on the previous ones.  I sometimes experience different
> placement of spaces for an unchanged paragraph.  I use a script to
> diff manual pages at different commits, which is useful to quickly see
> the effects of a commit in a formatted page.  That script sometimes
> shows suprious space changes (produced by groff(1)) for parts of the
> page that haven't been changed, and which one would expect should not
> be formatted differently.

What you're observing is an artifact of the adjustment process that pads
out filled text lines to a consistent width.  It's a feature of *roff
formatters going back essentially forever--as in, to the early 1970s.

And it is indeed not a man page-specific phenomenon.

groff_diff(7) briefly mentions it:

     When adjusting output lines to both margins, AT&T troff at first
     adjusts spaces starting from the right; GNU troff begins from the
     left.  Both implementations adjust spaces from opposite ends on
     alternating output lines in this adjustment mode to prevent
     “rivers” in the text.

Some typography people refer to this practice as achieving "uniform
grayness".  Imagine your eyes defocused so that the text of a printed
page is a smear of gray--if every line were supplemented with space
favoring either the left or right side, you would perceive the opposite
side as being "blacker".  As far as I understand the concept, not being
a trained typographer, it's the same thing, or tautologically related.
Rivers create anisotropies in your grayness.

I have proposed the term "adjustment parity", a property that tells you
whether an output line requiring adjustment gets adjusted from the left
or the right.  Roughly, if you change filled text in a *roff document
that uses adjustment such that you add or delete an _even_ number of
lines, the adjustment of subsequent lines won't change.  If you add or
delete an odd number of lines, it will.  However, that's a *truly* rough
statement because a change prior to groff 1.23.0 made GNU troff ignore,
for purposes of adjustment parity, lines that don't get adjusted at all.
I'll put some more background in a footnote.[1]

When diffing changes to man pages for the groff and ncurses projects
(and occasional others to which I contribute), I disable adjustment when
rendering the pages before and after, using the `-d AD=l` option.

groff_man(7):

Options
     The following groff options set registers (with -r) and strings
     (with -d) recognized and used by the man macro package.  To ensure
     rendering consistent with output device capabilities and reader
     preferences, man pages should never manipulate them.

     -dAD=adjustment‐mode
              Set line adjustment to adjustment‐mode, which is typically
              “b” for adjustment to both margins (the default), or “l”
              for left alignment (ragged right margin).  Any valid
              argument to groff’s “.ad” request may be used.  See
              groff(7) for less‐common choices.

As you can see, I turn off adjustment when pasting man page contents
into emails as well.[2]

For example, the script I use to diff groff man pages before pushing a
set of commits has this stuff in it.

BFLAG=
#BFLAG=-b
...
: ${AD:=l}
...
ARGS="$BFLAG -ww -dAD=$AD -rCHECKSTYLE=3 -rU1 -Tutf8 -e -t -mandoc"
...
for P in *.[157]
do
    if [ "$P" = groff_mmse.7 ]
    then
      LOCALE=-msv
    else
      LOCALE=
    fi

    echo $0: $P >&2
    echo "groff $ARGS $LOCALE $P" > "$P.cR.txt"
    groff $ARGS $LOCALE "$P" >> "$P.cR.txt"
...
done

I then diff(1) the ".cR.txt" file I saved from my last push
(corresponding to "origin/master") to the tip of the trunk.

I will point out something about your diff, though.

>       @@ -118,11 +130,11 @@ .SH DESCRIPTION
>        this operation yields an
>        .B EINVAL
>        error.
>       -.RE
>        .IP
>       -Since Linux 6.7, using this subcode requires the
>       +Since Linux 6.7, using this selection mode requires the
>        .B CAP_SYS_ADMIN
>        capability.
>       +.RE
>        .TP
>        .BR subcode = TIOCL_PASTESEL
>        Paste selection.

This change involving movement of the `RE` macro call can potentially
change the output as well.

> There are several paragraphs which shouldn't report changes: every
> paragraph that doesn't start with "Since Linux 6.7," should be
> unchanged.

...unless the moved `RE` call creates a surprise.

> Is this a bug?  Is it a feature?

It's a feature.  Some people do hate adjustment of nroff output, though,
which is why I added a feature to groff man(7) to support disabling it.

The history of this practice is inconsistent.  Seventh Edition Unix
(1979) disabled adjustment of man pages when rendering in nroff mode,[3]
and BSD retained that disablement until death.  SunOS commented it as
early as SunOS 2.0 (1985), thus restoring adjustment in nroff mode, and
retained that all the way through Solaris 10 (2005).  When James Clark
wrote groff starting in about 1989, his man(7) implementation closely
emulated SunOS.  With the Solaris 11 release in 2010, Oracle discarded
its AT&T-descended troff in favor of the then-current groff release.
They're still on groff 1.22.2 (2013) today, and so they've been
adjusting their man pages in nroff mode for at least 40 years, as has
groff for about 35).  I don't know what other System V Unices did.

Some people have lobbied me to turn the default for adjustment off in
nroff mode for man pages, but I've resisted, in part for consistency
with groff's own entire history and the expectations of the once large
(but now aging) population of Sun Unix users, but also because I feel
that groff's defaults in nroff mode should be as similar to troff mode
as practical, to minimize surprises when switching among output devices.

As of groff 1.23.0 (2023) the default adjustment setting in groff man(7)
(and mdoc(7)) is completely under user control.

Regards,
Branden

[1]

commit 69efbe0a69a8e7de8904d78e3de8c7e8a58a8b92
Author: G. Branden Robinson <g.branden.robin...@gmail.com>
Date:   Sat Sep 4 23:20:54 2021 +1000

    [troff]: Don't adjust nonadjustable lines.

    This means that the direction from which an output line in adjustment
    mode "b" (or its "n" synonym) is filled with supplemental space is not
    changed if that output line does not require adjustment.  This will
    result in whitespace changes to documents using that adjustment mode,
    and these changes will be plainly visible on low-resolution output
    devices like terminals.

    To illustrate, in the following "A" means an output line requiring
    adjustment; "F" a line that is "full" and does not; and "L" and "R"
    indicate distribution of adjustment spaces from the left and right,
    respectively.

    groff 1.22.4    groff 1.23.0
    ------------    ------------
    A    L          A    L
    A    R          A    R
    F    L          F    R
    A    R          A    L

    * src/roff/troff/env.cpp (distribute_space): Return early if either the
      amount of desired space to be distributed or the count of space nodes
      in the output line to distribute it among is zero.

    * tmac/tests/an_TH-repairs-ad-damage.sh: Update test to expect space to
      be distributed differently.

    Fixes <https://savannah.gnu.org/bugs/?61089> and
    <https://savannah.gnu.org/bugs/index.php?60673>.

[2] $ type mailman
mailman is a function
mailman ()
{
    local cmd=;
    case "$1" in
        -*)
            opts="$opts $1";
            shift
        ;;
    esac;
    set -- $(man -w "$@");
    cmd=$(zcat --force "$@" | grog -Tutf8 -b -ww -P -cbou -rU0 -rLL=72n -rHY=0 
-dAD=l $opts);
    zcat --force "$@" | $cmd | less
}

[3] https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/lib/tmac/tmac.an

    Also see variously:

    https://minnie.tuhs.org/cgi-bin/utree.pl?file=32V/usr/lib/tmac/tmac.an
    https://minnie.tuhs.org/cgi-bin/utree.pl?file=3BSD/usr/lib/tmac/tmac.an.new
    https://minnie.tuhs.org/cgi-bin/utree.pl?file=4BSD/usr/lib/tmac/tmac.an.new
    
https://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD/usr/lib/tmac/tmac.an.new
    
https://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Tahoe/usr/lib/tmac/tmac.an.new
    
https://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD/usr/share/tmac/tmac.groff_an

Attachment: signature.asc
Description: PGP signature

Reply via email to