Thank you Branden for those historical insights. 
Off-topic to Alejandro's initial question but related to the subject of
justifying text set in monospace, do we owe this typographic gesture to
the early *roff formaters or was it already a thing in previous
publication tool, either software or hardware ?
Are you aware of theory or paper on the subject ?

Martin


Le Fri, May 02, 2025 at 07:01:39AM -0500, G. Branden Robinson a écrit :
> 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



Reply via email to