TBL(7)

πŸ“¦
version 1.14.6 Β· 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– TBL(7) β€” tbl language reference for mandoc πŸ’–

okay bestie, listen up, this is the tbl page from the Miscellaneous Information Manual and it's literally the whole language reference for mandoc's table game. grab a snack, we're doing this πŸ“


✨ NAME ✨

tbl β€” the tbl language reference, but make it for mandoc πŸŽ€


🌸 DESCRIPTION 🌸

So the tbl language formats tables. that's the whole job. it lives inside mdoc(7) and man(7) pages like a lil gremlin 🧚

This manual describes the subset of the tbl language that the mandoc(1) utility actually accepts. subset!! not the whole buffet, just the part mandoc eats πŸ’…

Every table gets started with a roff(7) TS macro, and then it's:

  • at most one line of "Options"
  • one or more "Layout" lines
  • one or more "Data" lines
  • and then it ends with a TE macro. periodt.
🚨 all input must be 7-bit ASCII. no fancy unicode girls, sorry 😭

⭐ Options ⭐

Here's the vibe check: if the first input line of a table ends with a semicolon, then that line is holding case-insensitive options, separated by spaces, tabs, or commas. if it does not end with a semicolon, it's not options at all β€” it gets read as the first "Layout" line instead. iconic behavior honestly πŸ‘‘

The options available are these ones. heads up, some of them need their arguments wrapped in parentheses:

  • allbox β€” draws a single-line box around each table cell. every single one. bougie 🎁
  • box β€” draws a single-line box around the table as a whole. for GNU compatibility you can also call it frame.
  • center β€” centers the table instead of left-adjusting it. for GNU compatibility you can also call it centre (yes the british spelling slays too πŸ‡¬πŸ‡§).
  • decimalpoint β€” uses the single-character argument as the decimal point when you're using the n layout key. this one is a GNU extension.
  • delim β€” uses the two characters of the argument as eqn(7) delimiters. currently unsupported 🫠
  • doublebox β€” draws a double-line box around the table. for GNU compatibility you can also call it doubleframe. double the drama ✨
  • expand β€” increases the width of the table to the current line length. currently ignored 😢
  • linesize β€” draws lines with the point size given by the unsigned integer argument. currently ignored.
  • nokeep β€” allows page breaks within the table. this is a GNU extension and it's currently ignored.
  • nospaces β€” ignores leading and trailing spaces in data cells. this is a GNU extension.
  • nowarn β€” suppresses warnings about tables that exceed the current line length. this is a GNU extension and it's currently ignored.
  • tab β€” uses the single-character argument as the delimiter between data cells. by default, the horizontal tabulator character is the one used.

πŸ¦‹ Layout πŸ¦‹

The table layout comes after an "Options" line, or after a roff(7) TS or T& macro. each layout line says how one line of "Data" gets formatted.

The last layout line ends with a full stop. and that last line? it also applies to all the remaining data lines. so it's the main character for everything after it πŸ‘‘ multiple layout lines can be joined by commas on a single physical input line.

Each layout line is made of one or more layout cell specifications, optionally separated by whitespace. these case-insensitive key characters are the ones that start a brand new cell specification:

  • c β€” center the string in this cell. symmetrical, balanced, at peace 🧘
  • r β€” right-justify the string in this cell.
  • l β€” left-justify the string in this cell.
  • n β€” justify a number around its last decimal point. and if there's no decimal point found in the number, it's assumed to trail the number.
  • s β€” horizontally span columns from the last non-s layout cell. it's an error if a column span follows a _ or = cell, or if it comes first on a layout line. the combined cell as a whole consumes only one cell of the corresponding data line.
  • a β€” left-justify a string and pad it with one space.
  • ^ β€” vertically span rows from the last non-^ layout cell. it's an error to invoke a vertical span on the first layout line. and unlike a horizontal span, a vertical span consumes a data cell and discards the content πŸ’€
  • _ β€” draw a single horizontal line in this cell. this consumes a data cell and discards the content. you can also invoke it with -.
  • = β€” draw a double horizontal line in this cell. this also consumes a data cell and discards the content.

Each cell key can be followed by zero or more of these case-insensitive modifiers:

  • b β€” use a bold font for the contents of this cell. bold is a lifestyle πŸ’ͺ
  • d β€” move content down to the last row of this vertical span. currently ignored.
  • e β€” make this column wider to match the maximum width of any other column that also has the e modifier. matching widths, cute 🫢
  • f β€” the next one or two characters select the font to use for this cell. one-character font names must be followed by a blank or a period. check the roff(7) manual for the supported font names.
  • i β€” use an italic font for the contents of this cell.
  • m β€” specify a cell start macro. this is a GNU extension and it's currently unsupported.
  • p β€” set the point size to the following unsigned argument, or change it by the following signed argument. currently ignored.
  • v β€” set the vertical line spacing to the following unsigned argument, or change it by the following signed argument. currently ignored.
  • t β€” do not vertically center content in this vertical span; leave it in the top row instead. currently ignored.
  • u β€” move cell content up by half a table row. currently ignored.
  • w β€” specify a minimum column width.
  • x β€” after determining the width of all the other columns, distribute the rest of the line length among all columns that have the x modifier. sharing is caring ✨
  • z β€” do not use this cell for determining the width of this column.
  • | β€” draw a single vertical line to the right of this cell.
  • || β€” draw a double vertical line to the right of this cell.

and here's a lil extra rule bestie: if a modifier consists of decimal digits, it specifies a minimum spacing in units of n between this column and the next column to the right. the default is 3. and if there's a vertical line, it gets drawn inside the spacing.


πŸŽ€ Data πŸŽ€

The data section comes right after the last "Layout" line. each data line is made of one or more data cells, delimited by tab characters.

Now, the special cases, and there are several, so stay with me:

  • If a data cell contains only the two bytes \^, the cell above spans down to this row β€” exactly as if the layout specification of this cell were ^.
  • If a data cell contains only the single character _ or =, a single or double horizontal line is drawn across the cell, joining its neighbours.
  • If a data cell contains only the two character sequence \_ or \=, a single or double horizontal line is drawn inside the cell, and it does not join its neighbours.
  • If a data line contains nothing but the single character _ or =, a horizontal line across the whole table is inserted, without consuming a layout row πŸ”₯

In place of any data cell, a text block can be used. it starts with T{ at the end of a physical input line. input line breaks inside the text block neither end the text block nor its data cell β€” they're just vibes, the block keeps going. it only ends if T} occurs at the beginning of a physical input line and is followed by an end-of-cell indicator. so:

  • If the T} is followed by the end of the physical input line, then the text block, the data cell, and the data line all end right there.
  • If the T} is followed by the tab character, then only the text block and the data cell end β€” the data line continues with the data cell following that tab character.
  • If T} is followed by any other character, it does not end the text block, and the block instead continues onto the following physical input line. sneaky 😏

part 1 done and honestly? we ate. more is coming bestie, don't go anywhere πŸ’œ

✨ EXAMPLES ✨

okay bestie, let's get into the actual glow-ups. πŸ’…

String justification and font selection:

.TS
rb c  lb
r  ci l.
r       center  l
ri      ce      le
right   c       left
.TE

and it renders like:

                 r   center   l
                ri     ce     le
             right   c      left

Some ports in OpenBSD 6.1 to show number alignment and line drawing:

.TS
box tab(:);
r| l
r  n.
software:version
_
AFL:2.39b
Mutt:1.8.0
Ruby:1.8.7.374
TeX Live:2015
.TE
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ software β”‚ version   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚      AFL       2.39b β”‚
β”‚     Mutt     1.8.0   β”‚
β”‚     Ruby   1.8.7.374 β”‚
β”‚ TeX Live    2015     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Spans and skipping width calculations:

.TS
box tab(:);
lz  s | rt
lt| cb| ^
^ | rz  s.
left:r
l:center:
:right
.TE
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”
β”‚ left       β”‚ r β”‚
β”‚ l β”‚ center β”‚   β”‚
β”‚   β”‚      right β”‚
β””β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Text blocks, specifying spacings and specifying and equalizing column widths, putting lines into individual cells, and overriding allbox:

.TS
allbox tab(:);
le le||7 lw10.
The fourth line:_:line 1
of this column:=:line 2
determines:_:line 3
the column width.:T{
This text is too wide to fit into a column of width 17.
T}:line 4
T{
No break here.
T}::line 5
.TE
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ The fourth line      β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚  line 1     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ of this column       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚  line 2     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ determines           β”‚ ─────────────────────  β”‚β”‚  line 3     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ the column width.    β”‚ This   text  is  too   β”‚β”‚  line 4     β”‚
β”‚                      β”‚ wide to fit  into  a   β”‚β”‚             β”‚
β”‚                      β”‚ column of width 17.    β”‚β”‚             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ No break here.       β”‚                        β”‚β”‚  line 5     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

These examples were constructed to demonstrate many tbl features in a compact way. In real manual pages, keep tables as simple as possible. They usually look better, are less fragile, and are more portable. No cap. πŸ’–


πŸ’€ COMPATIBILITY πŸ’€

The mandoc(1) implementation of tbl doesn't support mdoc(7) and man(7) macros and eqn(7) equations inside tables. That's the tea. β˜•


πŸ‘€ SEE ALSO πŸ‘€

M. E. Lesk, Tbl β€” A Program to Format Tables, June 11, 1976.


πŸ“œ HISTORY πŸ“œ

The tbl utility, a preprocessor for troff, was originally written by M. E. Lesk at Bell Labs in 1975. The GNU reimplementation of tbl, part of the groff package, was released in 1990 by James Clark. A standalone tbl implementation was written by Kristaps Dzonsons in 2010. This formed the basis of the implementation that first appeared in OpenBSD 4.9 as a part of the mandoc(1) utility.


πŸ‘‘ AUTHORS πŸ‘‘

This tbl reference was written by Kristaps Dzonsons <kristaps@bsd.lv> and Ingo Schwarze <schwarze@openbsd.org>.


😭 BUGS 😭

In -T utf8 output mode, heavy lines are drawn instead of double lines. This cannot be improved because the Unicode standard only provides an incomplete set of box drawing characters with double lines, whereas it provides a full set of box drawing characters with heavy lines. It is unlikely this can be improved in the future because the box drawing characters are already marked in Unicode as characters intended only for backward compatibility with legacy systems, and their use is not encouraged. So it seems unlikely that the missing ones might get added in the future. πŸ’€


Source: Debian · Version: TBL(7) · Date: September 18, 2021 🫢

πŸ“¦ where this page comes from