TBL(7)
π 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
TEmacro. 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 itframe.centerβ centers the table instead of left-adjusting it. for GNU compatibility you can also call itcentre(yes the british spelling slays too π¬π§).decimalpointβ uses the single-character argument as the decimal point when you're using thenlayout key. this one is a GNU extension.delimβ uses the two characters of the argument aseqn(7)delimiters. currently unsupported π«doubleboxβ draws a double-line box around the table. for GNU compatibility you can also call itdoubleframe. 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-slayout 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 theemodifier. 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 theroff(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 thexmodifier. 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
- debian trixie: mandoc 1.14.6-4 Β· ISC
- ubuntu questing: mandoc 1.14.6-4
- ubuntu resolute: mandoc 1.14.6-4build1 Β· ISC
- ubuntu stonking: mandoc 1.14.6-4build1 Β· ISC
- Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- Copyright (c) 2014,2015,2017,2018,2019 Ingo Schwarze <schwarze@openbsd.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms