Thread (5 messages) 5 messages, 2 authors, 2025-10-05

Re: tbl(1) issues in console_codes(4)

From: G. Branden Robinson <hidden>
Date: 2025-09-25 22:10:17

Hi Alex,

At 2025-09-25T11:36:37+0200, Alejandro Colomar wrote:
I see some issues in console_codes(4), and I don't understand them.
There are tables where groff(1) prints past the 80-col right margin,
but I don't understand tbl(1) enough to understand why.  Could you
help?
Sure.  By default, text formatted by tbl(1) is not filled.

tbl(1):
     Ordinarily, a table entry is typeset rigidly.  It is not filled,
     broken, hyphenated, adjusted, or populated with additional inter‐
     sentence space.  tbl instructs the formatter to measure each table
     entry as it occurs in the input, updating the width required by its
     corresponding column.

If you want to avoid overset lines with tbl(1), you must either

1.  pre-measure them so as not to exceed some reasonable minimum (for
    man pages, I recommend "65n" for consistency with historical
    practice and to accommodate low-vision users and others who might
    benefit from or prefer fewer characters per line than the
    groff/mandoc defaults of 78-80n;[1][2] or

2.  use text blocks.

tbl(1):
   Text blocks
     An ordinary table entry’s contents can make a column, and therefore
     the table, excessively wide; the table then exceeds the line length
     of the page, and becomes ugly or is exposed to truncation by the
     output device.  When a table entry requires more conventional
     typesetting, breaking across more than one output line (and thereby
     increasing the height of its row), it can be placed within a text
     block.

     tbl interprets a table entry of “T{” at the end of an input line
     specially, as a token starting a text block.  Similarly, an entry
     “T}” at the start of an input line ends a text block.  Text block
     tokens can share an input line with other table data (preceding T{
     and following T}).  Input lines between these tokens are formatted
     in a diversion by troff.  Text blocks cannot be nested.  Multiple
     text blocks can occur in a table row.

     ...
	$ MANWIDTH=80 man console_codes \
		| grep -n '.\{81\}' -C5 \
		| head -n 20;
	<standard input>:327: warning: table wider than line length minus indentation
	197-       terminator) is interpreted as a zero.
	198-       param      result
	199-       0          reset all attributes to their defaults
	200-       1          set bold
	201-       2          set half-bright (simulated with color on a color display)
	202:       3          set italic (since Linux 2.6.22; simulated with color on a color display)
	203:       4          set underscore (simulated with color on a color display) (the colors
	204-                  used to simulate dim or underline are set using ESC ] ...)
	205-       5          set blink
	206-       7          set reverse video
	207:       10         reset selected mapping, display control flag, and toggle meta flag
	208-                  (ECMA-48 says "primary font").
	209:       11         select null mapping, set display control flag, reset toggle meta flag
	210-                  (ECMA-48 says "first alternate font").
	211:       12         select null mapping, set display control flag, set toggle meta flag
	212:                  (ECMA-48 says "second alternate font").  The toggle meta flag causes the
	213:                  high bit of a byte to be toggled before the mapping table translation is
	214-                  done.
	215:       21         set underline; before Linux 4.17, this value set normal intensity (as is
	216-                  done in many other terminals)
I would format the document with `MANWIDTH=65` and, for any line that
still oversets, stuff the descriptive table entry into a text block.

Consulting my Git checkout of `man-pages`, I see that while some entries
in this table use text blocks, others don't.

$ nroff -t -rLL=65n -man -P-cbou man4/console_codes.4 | grep -E '.{66}' | wc -l
man4/console_codes.4:130: warning: table wider than line length minus indentation
man4/console_codes.4:330: warning: table wider than line length minus indentation
29

Those warnings will be wanting attention.  Also, I noticed that some of
the table entries overset _even though_ they're already _in_ text
blocks.  How is this possible?

Recall the introduction to tbl(1) above:

tbl(1):
     tbl instructs the formatter to measure each table entry as it
     occurs in the input, updating the width required by its
     corresponding column.

We need one more piece of information--the description of the `x` column
option that (most of) the tables in this page use for their description
columns.

tbl(1):
   Column modifiers
...
     x, X   Expand the column.  After computing the column widths,
            distribute any remaining line length evenly over all columns
            bearing this modifier.  Applying the x modifier to more than
            one column is a GNU extension.  This modifier sets the
            default line length used in a text block.

Consider that final sentence.

If you have one non-text-block entry that oversets the line, and use the
`x` table modifier, all your text blocks in that column of the table use
the width determined by the one that caused the overset.

And that's what's happening here.

Fixing up a couple of spots where text blocks should have been used but
weren't (diff attached), I get the following result.

$ nroff -t -rLL=65n -man -P-cbou man4/console_codes.4 | grep -E '.{66}'\
    | wc -l
0

I made several other changes to fix things that drive me crazy.  Most
are cosmetic.

1.  Stop using `ad` requests.  They don't do what people think.[3]
    However, _do_ use `na` requests _inside text blocks_ where necessary
    to defeat adjustment, because they work reliably there, and cannot
    damage the rest of the page.[5]

2.  Add paragraph macros before tables so that they set like
    typographical "displays".  This is common (if not universal)
    practice, sometimes done already in the Linux man-pages[6] and I
    think it looks better.

3.  Add missing `x` column modifier to the descriptive column of the
    "VT100 console sequences not implemented on the Linux console"
    table.

4.  Spell out column heading "param" as a complete word, "parameter".
    To me, it makes little sense to abbreviate it when one of the
    entries in its column is "100..107" anyway.

5.  Remove trailing spaces from entries in the "Linux Console Private
    CSI Sequences" table.  This makes more efficient use of space and,
    for some screen widths, permits more table rows to fit on the line.

6.  Document the names of the "ESC s" and "ESC u" extension controls.
    This one is non-cosmetic.

7.  Stop using `\0` escape sequences to achieve indentation of table
    entries; favor `\ ` (an unbreakable space) instead.  We're not
    laying out numeric data, and both are universally portable.  We
    don't want to use groff's `\~` because we don't want these spaces to
    adjust.  Really, we shouldn't be using space to indent table entries
    at all.  That's what the `A` column classifier is for.  Using `A`
    brings the additional advantage that if a text block is in a column
    using that classifier, and it breaks, subsequent lines are indented
    the same as the first.  This advantage is unavailable with `\0`
    or `\ ` because you don't know in the document source what the width
    (line length) of the output device will be.  In fact, I'll attach a
    second version of the diff capturing that reform too.

The page renders fine for me now, at 65 columns and wider.

I figure you'll want these broken up into separate chunks for a proper
patch submission, so let me know which of the enumerated items you want
and how finely to slice the changes.

Regards,
Branden

[1] https://baymard.com/blog/line-length-readability

[2] Why "78-80"?  From the "NEWS" file of the forthcoming groff 1.24.0:

*  The an (man), doc (mdoc), and doc-old (mdoc-old) macro packages have
   changed the default line length when formatting on terminals from 78n
   to 80n.  The latter is a vastly more common device configuration, but
   that line length had been avoided since the groff 1.18 release in
   July 2002 (prior to that, the line length was 65n, as in AT&T nroff),
   for an undocumented reason.  That reason appears to have been the
   interaction of bugs in GNU tbl(1) with an aspect of grotty(1)'s
   design.  Those bugs have been resolved.  A man(1) program can still
   instruct groff to format for any desired line length by setting the
   `LL` register on {g,n,t}roff's command line.

[3] https://cgit.git.savannah.gnu.org/cgit/groff.git/tree/tmac/an.tmac?id=05036f82e9b09e026bbd8fa0504211a32a85fb62#n156

[4] tbl(1):

     Text blocks are formatted as was the text prior to the table,
     modified by applicable column descriptors.  Specifically, the
     classifiers A, C, L, N, R, and S determine a text block’s alignment
     within its cell, but not its adjustment.  Add na or ad requests to
     the beginning of a text block to alter its adjustment distinctly
     from other text in the document.  As with other table entries, when
     a text block ends, any alterations to formatting parameters are
     discarded.  They do not affect subsequent table entries, not even
     other text blocks.

[5] It groff 1.24.0, the _man_ package will perform a "paragraph reset"
    at every `P` macro call (and several others), restoring the
    adjustment and hyphenation mode defaults.

    https://savannah.gnu.org/bugs/?67363

[6] socketcall(2), TIOCMSET(2const), strfromd(3), double_t(3type),
    mouse(4), mount_namespaces(7), namespaces(7), operator(7),
    signal-safety(7), suffixes(7)

Attachments

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