Hi Branden, On Fri, May 02, 2025 at 07:01:39AM -0500, G. Branden Robinson wrote: > 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]
Hmmmm, it's very interesting. I was guessing that something like that might be going on. So, now I've looked more closely at the diff, and it seems that the blanks favour alternating left and right to compensate. That seems quite reasonable, and indeed a feature. > 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. By default, I prefer keeping adjustment. Often, I want to see changes in adjustment too as part fo the diff. Maybe I should add an option to disable adjustment optionally, which could be useful in those cases where the diff is a bit hard to understand. > 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 What's -msv? > > echo $0: $P >&2 > echo "groff $ARGS $LOCALE $P" > "$P.cR.txt" > groff $ARGS $LOCALE "$P" >> "$P.cR.txt" > ... > done Would you mind sharing the entire script? I might get ideas for improving diffman-git(1). (And maybe you can drop your script if diffman-git(1) would be good-enough for you.) > > I then diff(1) the ".cR.txt" file I saved from my last push > (corresponding to "origin/master") to the tip of the trunk. That would be `diffman-git origin/master master`. > 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. Makes sense. > > 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. The RE movement is intended to indent the "Since Linux 6.7," para. > > 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. Hmmm, I like it. It's good to know that I can disable it for diffing in some cases, but even for diffing I want it enabled by default. :) Cheers, Alex -- <https://www.alejandro-colomar.es/>
signature.asc
Description: PGP signature