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
- signature.asc [application/pgp-signature] 833 bytes