diff --git a/doc/01-impatient.tex b/doc/01-impatient.tex index d65204a..d384156 100644 --- a/doc/01-impatient.tex +++ b/doc/01-impatient.tex @@ -1,16 +1,18 @@ \chapter{Tabularray for the Impatient} -\section{Conceptualisation} -Specification of tabular typesetting in \pkg{tabularray} is conceptualised as two components: \vrb{inner, outer}. -The \vrb{inner} specification refers to any and all specification that is directly related to the table itself, including column and row specifications. These are supplied within the \arg{inner spec} argument in a key--value format. -Whereas, the \vrb{outer} specification refers to all elements of typesetting that are not directly related to the table itself, but rather to the environment in which the table is placed. These are supplied within the \oarg{outer spec} as an optional argument, also in a key--value format. +This chapter is written for readers who need a working table before they need a full account of the package. It favours speed over completeness, introducing each construct only as far as a first table requires, and leaves the worked examples and their qualifications to the chapters that follow. -Based on this conceptualisation, \pkg{tabularray} provides the following environments for tabular typesetting: \tsobj[env]{tblr,tallblr,longtblr}. +\section{Conceptualisation}\label{impatient:concept} +Specification of tabular typesetting in \pkg{tabularray} is conceptualised as two components: \vrb{inner, outer}. The \vrb{inner} specification refers to everything directly related to the table itself, including its columns and rows, and is supplied within the \arg{inner spec} argument in a key--value format. The \vrb{outer} specification refers to the elements of typesetting that belong to the environment in which the table is placed, and is supplied within the \oarg{outer spec} as an optional argument, also in a key--value format. -\begin{codedescribe}[env]{tblr,tallblr,longtblr} +The value of this division lies in the independence it affords, as the structure of a table can be revised without disturbing its caption or notes. It is not a perfectly clean one, however: \key[no index]{baseline} appears on both sides, and telling where a given option belongs takes some familiarity. + +Based on this conceptualisation, \pkg{tabularray} provides the following environments for tabular typesetting: \tsobj[env]{tblr,talltblr,longtblr}. + +\begin{codedescribe}[env]{tblr,talltblr,longtblr} \begin{codesyntax} \tsobj[code, no index]{\begin{tblr}}[\oarg{outer spec}]\{\arg{inner spec}\} - \quad\ldots - \tsmacro{\end{tblr}}{} + \quad\ldots + \tsmacro{\end{tblr}}{} % \bigskip % \tsobj[code]{\begin{talltblr}}\oarg{outer spec}\arg{inner spec} % \quad\ldots @@ -19,86 +21,119 @@ \section{Conceptualisation} % \tsobj[code]{\begin{longtblr}}\oarg{outer spec}\arg{inner spec} % \quad\ldots % \tsmacro{\end{longtblr}}{} - \end{codesyntax} + \end{codesyntax} \end{codedescribe} -The feature comparison is typeset in +The feature comparison is typeset in Table~\ref{comparison-of-tblr}. \begin{table}[!hbtp] -\centering -\begin{talltblr}[ - caption = {Feature matrix of the \pkg{tabularray} environments}, - label = {comparison-of-tblr}, - entry = {Comparison of tblr, tallblr and longtblr environments}, - note{a} = {\footnotesize Whether the environment can be placed inside a float, such as \env{table}.} -]{ - columns = {c}, - row{1} = {preto={\bfseries}}, - process = \YNColour -} - \hline - & Caption/label & Float\TblrNote{a} & Pagebreak\\ - \hline - \env{tblr} & No & No & No\\ - \env{tallblr} & Yes & Yes & No\\ - \env{longtblr} & Yes & No & Yes\\ - \hline -\end{talltblr} + \centering + \begin{talltblr}[ + caption = {Feature matrix of the \pkg{tabularray} environments}, + label = {comparison-of-tblr}, + entry = {Comparison of tblr, talltblr and longtblr environments}, + note{a} = {\footnotesize Whether the environment can be placed inside a float, such as a \env*{table}.} + ]{ + columns = {c}, + row{1} = {preto={\bfseries}}, + process = \YNColour + } + \hline + & Caption/label & Float\TblrNote{a} & Pagebreak \\ + \hline + \env{tblr} & No & Yes & No \\ + \env{talltblr} & Yes & Yes & No \\ + \env{longtblr} & Yes & No & Yes \\ + \hline + \end{talltblr} \end{table} +\section{A First Table}\label{impatient:first} +A first table calls for little beyond the package and the 2 specifications introduced above. With \tsverb*{\usepackage{tabularray}} in the preamble, the example below is complete: its caption and label belong to the \oarg{outer spec}, its columns and rules to the \arg{inner spec}, and the table body contains only text. + +\begin{codestore}[st = first-table] + \begin{talltblr}[ + caption = {Poets and their works}, + label = {first-table}, + ]{ + colspec = {lll}, + hline{1,2,Z} = {solid}, + row{1} = {font=\bfseries}, + } + Poet & City & Work \\ + Ferdowsi & Tus & Shahnameh \\ + Rumi & Konya & Masnavi \\ + Hafez & Shiraz & Divan + \end{talltblr} +\end{codestore} + +\begin{center} + \tsdemo*[tblr]{first-table} +\end{center} + +\key{colspec} gives each column a type, \key{hline} draws the rules selected by index, in which \vrb{Z} is the last, and \key{row} styles the head row. The rest of this chapter lists what else each specification accepts. + +A cell with a line break needs a pair of braces around its text, as in \tsverb*{{Surplus \\ Enjoyment}}, because \tsverb{\\} otherwise ends the row. A key value that contains a comma needs braces as well, as in \tsverb*{caption = {France, on the left}}. + \section{Specifications of the Inner Components}\label{impatient:inner} +The inner specification accounts for most of the interface of \pkg{tabularray}, so a first table depends on it far more than on its outer counterpart. This section is confined to the column and row keys that such a table is likely to need, which \S\ref{inner:colrow} then examines at length. + \subsection{Column and Row Specifications} To specify columns and rows in \pkg{tabularray}, \key{columns,rows} keys may be used. As the names suggest, \key{columns,rows} represent global specifications that apply to all columns/rows of a given \env{tblr}; whereas \key{column, row} represent specifications that apply to a specific column/row, which may be useful in customisation. -\begin{codedescribe}[keys]{column, columns, row, rows} +\begin{codedescribe}[keys, update = 2026A]{column, columns, row, rows} \begin{codesyntax} - \tsobj[code, no index]{\begin{tblr}}\tsobj[oarg]{outer spec}\{ - \quad\keyval{columns}{kwargs}, - \quad\keyval{rows}{kwargs}, - \quad\ldots - \} - \quad\ldots - \tsmacro{\end{tblr}}{} - \end{codesyntax} + \tsobj[code, no index]{\begin{tblr}}[\oarg{outer spec}]\{ + \quad\keyval{columns}{kwargs}, + \quad\keyval{rows}{kwargs}, + \quad\ldots + \} + \quad\ldots + \tsmacro{\end{tblr}}{} + \end{codesyntax} \begin{describelist*}{keys} - \deschead{Positioning \& Dimensions}\label{colrow:positioning} + \deschead{Positioning \& Dimensions\footnotemark[1]}\label{colrow:positioning} \describe{halign} - {Horizontal alignment: \val{l, c, r, j} (Default: \val{j})} + {Horizontal alignment: \val{l, c, r, j} (Default: \val{j})} \describe{valign} - {Vertical alignment: \val{t, m, b, f} (Default: \val{t})} + {Vertical alignment: \val{t, m, b, h, f} (Default: \val{t})} \describe{ht} - {Height of the row. \vrb{row} only} + {Height of the row. \vrb{row} only} \describe{wd} - {Width of the column. \vrb{column} only} + {Width of the column. \vrb{column} only} \deschead{Colour and Font}\label{colrow:colour} - \describe{bg} - {Colour of the background of the column/row} - \describe{fg} - {Colour of the text in the column/row} + \describe{bgcolor} + {Colour of the background of the column/row\footnotemark[1]} + \describe{fgcolor} + {Colour of the text in the column/row} \describe{font} - {Font of the text in the column/row} + {Font of the text in the column/row} \describe{mode} - {Mode in which the text will be typeset: \val{math, imath, dmath, text} (Default: \val{text})} + {Mode in which the text will be typeset: \val{math, imath, dmath, text} (Default: \val{text}, or \val{math} when the table itself is in math mode)} \describe{\$} - {Alias to \keyval{mode}{math, imath}, i.e. inline math mode} + {Alias to \keyval{mode}{math}} \describe{\$\$} - {Alias to \keyval{mode}{dmath}, i.e. display math mode} + {Alias to \keyval{mode}{dmath}, i.e. display math mode} \deschead{Utilities} \describe{cmd}{Control sequence to execute for every cell's text} \describe{preto}{Material to insert \emph{before} the text of every cell.} \describe{appto}{Material to insert \emph{after} the text of every cell.} \begin{tsremark} If you supply values for \key{preto, appto} in both \key{columns} and \key{rows}, the order in which they are typeset will be determined by the order in which you specify the keys. - For example, \vrb{columns={preto=+, appto=!}, rows={preto=X, appto=Z}} will yield ``\tsobj[code, no index]{X+text!Z}'', whereas \vrb{rows={preto=X, appto=Z}, columns={preto=+, appto=!}} will yield ``\tsobj[code, no index]{+XtextZ!}''. + For example, \vrb{{columns={preto=+, appto=!}, rows={preto=X, appto=Z}}} will yield ``\tsobj[code, no index]{X+text!Z}'', whereas \vrb{{rows={preto=X, appto=Z}, columns={preto=+, appto=!}}} will yield ``\tsobj[code, no index]{+XtextZ!}''. \end{tsremark} \begin{tsremark} \key{preto} may also be used for font purposes, but \key{font} always comes before \key{preto}---which may have its use.\footnotemark[2] \end{tsremark} + \begin{tsremark} + \key{bg, fg} are shorter aliases for \key{bgcolor, fgcolor} respectively.\footnotemark[3] + \end{tsremark} \end{describelist*} \end{codedescribe} -\footnotetext[1]{The values of these keys may be supplied without need to specify the key itself. For example, \vrb{l, t, 5cm, red} will be understood as \vrb{halign=l, valign=t, wd=5cm, bg=red}.} +\footnotetext[1]{The values of these keys may be supplied without need to specify the key itself. For example, \vrb{{l, t, 5cm, red}} will be understood as \vrb{{halign=l, valign=t, wd=5cm, bg=red}}.} \footnotetext[2]{The key difference is that \key{font} executes \tsobj[code]{\selectfont} after.} -\clearpage +\footnotetext[3]{\key{bgcolor, fgcolor} replace the older \key{bg, fg} as of \pkg{tabularray} 2026A; the short forms remain valid.} + \begin{codedescribe}{} \begin{describelist*}{keys} \deschead{Spacing -- Rows}\label{colrow:rowspacing} @@ -117,66 +152,411 @@ \subsection{Column and Row Specifications} \describe{rightsep+}{Horizontal space after the column, added to the value of \tsobj[keys]{rightsep} (Default: none). \vrb{column} only} \end{describelist*} \begin{tsremark} - Setting values via \key{rowsep, rowsep+} is equivalent to that of using \key{abovesep, belowsep} (or that of \key{abovesep+, belowsep+}) with the same value. That is, \vrb{rowsep=3pt} will be the same as \vrb{abovesep=3pt, belowsep=3pt}. The same applies to the column spacing keys. - \end{tsremark} + Setting values via \key{rowsep, rowsep+} is equivalent to that of using \key{abovesep, belowsep} (or that of \key{abovesep+, belowsep+}) with the same value. That is, \vrb{rowsep=3pt} will be the same as \vrb{{abovesep=3pt, belowsep=3pt}}. The same applies to the column spacing keys. + \end{tsremark} + \begin{tsremark} + \key{rowsep, abovesep, belowsep} and \key{colsep, leftsep, rightsep} can also be written directly in the \arg{inner spec} to apply to every row or column. The \key[no index]{+} variants cannot. + \end{tsremark} +\end{codedescribe} + +\subsection{Selecting Columns and Rows}\label{impatient:selectors} +\begin{codedescribe}{} + Keys that address part of a table, such as \key{column}, \key{row}, \key{cell}, \key{hline} and \key{vline}, select what they apply to with any of the forms below. These may be combined in a comma-separated list, e.g.\ \vrb{{row{1,3-4,Z}}}, and \S\ref{inner:selectors} shows them in use. + \begin{describelist*}{values} + \describe{2}{A single index} + \describe{2-4}{A range of indexes} + \describe{-}{Every row or column} + \describe{odd}{Every odd index. \vrb{odd[5]} starts from index 5} + \describe{even}{Every even index. \vrb{even[4]} starts from index 4} + \describe{every}{\vrb{every}[\tsmeta{step}]\{\tsmeta{start}\}\{\tsmeta{end}\} selects the indexes from \tsmeta{start} to \tsmeta{end}} + \describe{U...Z}{The last 6 indexes: \vrb{Z} is the last, \vrb{Y} the second last, and so on} + \end{describelist*} +\end{codedescribe} + +\subsection{Table Commands}\label{impatient:commands} +\begin{codedescribe}[code]{SetRow, SetRows, SetColumn, SetColumns} + \begin{codesyntax} + \tsobj[code, no index]{\SetRow}\{\tsmeta{keys}\} \tsmeta{cell text} + \tsobj[code, no index]{\SetColumn}\{\tsmeta{keys}\} \tsmeta{cell text} + \end{codesyntax} + These commands set the keys above from inside the table body, at the start of a cell. \tsobj[code, no index]{\SetRow} and \tsobj[code, no index]{\SetColumn} apply to the row and column of that cell, whereas \tsobj[code, no index]{\SetRows, \SetColumns} apply to every row and column, as \key{rows, columns} do. +\end{codedescribe} + +\section{[Practice] The Q-type}\label{impatient:qtype} +Traditional column types spread their features across many letters, each with its own conventions. The \tsverb{Q} type gathers those features into one general form, in which a single letter and a list of options can take the place of the others. We introduce it here because most of the other types in \pkg{tabularray} are defined as shorthand for it, as \S\ref{inner:types} shows. + +\begin{codedescribe}[keys]{colspec, rowspec, width} +\begin{codesyntax} + \tsobj[code, no index]{\begin{tblr}}[\oarg{outer spec}]\{ + \quad\keyval{colspec}{\{\tsmeta{column types}\}}, + \quad\keyval{rowspec}{\{\tsmeta{row types}\}}, + \quad\keyval{width}{\arg{dim}}, + \quad\ldots + \} + \quad\ldots + \tsmacro{\end{tblr}}{} +\end{codesyntax} +\key{colspec} gives one type letter for each column, as in the preamble of \LaTeX's \env*[no index]{tabular}, and \key{rowspec} does the same for each row. \key{width} sets the width of a table with stretchable columns (Default: \tsobj[code, no index]{\linewidth}). The name \key{colspec} can be left out if it is the only key in the \arg{inner spec}, so \tsverb*{\begin{tblr}{|l|c|r|}} is a complete opening. \end{codedescribe} -\section{[Practice] The Q-type} % 5x4 positioning table \begin{codestore}[st = Q-positioning] -\begin{tblr}{ - colspec = {| X[j] | X[l] | X[c] | X[r] |}, - rowspec = {| h{5em} | t{5em} | m{5em} | b{5em} | f{5em} |} -} - {Justified head} & {Left\\ head} & {Centre\\ head} & {Right\\ head} \\ - {Justified top} & {Left\\ top} & {Centre\\ top} & {Right\\ top} \\ - {Justified middle} & {Left\\ middle} & {Centre\\ middle} & {Right\\ middle} \\ - {Justified bottom} & {Left\\ bottom} & {Centre\\ bottom} & {Right\\ bottom} \\ - {Justified\\ foot} & {Left\\ foot} & {Centre\\ foot} & {Right\\ foot} -\end{tblr} + \begin{tblr}{ + colspec = {| X[j] | X[l] | X[c] | X[r] |}, + rowspec = {| h{5em} | t{5em} | m{5em} | b{5em} | f{5em} |} + } + {Justified head} & {Left \\ head} & {Centre\\ head} & {Right\\ head} \\ + {Justified top} & {Left \\ top} & {Centre\\ top} & {Right\\ top} \\ + {Justified middle} & {Left \\ middle} & {Centre\\ middle} & {Right\\ middle} \\ + {Justified bottom} & {Left \\ bottom} & {Centre\\ bottom} & {Right\\ bottom} \\ + {Justified \\ foot} & {Left\\ foot} & {Centre\\ foot} & {Right\\ foot} + \end{tblr} \end{codestore} % explain -\begin{codedescribe}[code, update = 2026A]{Q[ ... ]} -Unlike column specifications known in a typical \LaTeX\ fashion, the \tsverb{Q}-type in \pkg{tabularray} is a generic, flexible placeholder type that can act as any column/row type, as well as accommodating an array of features including dimensions, spanning, colouring and so on. -% In fact, the \tsverb{Q} type can become a more generalised version of the \tsobj[oarg]{p, m, b} types in \env*{tabular,tabularx}. -The \tsverb{Q} type takes the following \emph{optional} arguments: -\begin{describelist*}{oarg} - \describe{column}{\arg{coltype}, Column type of the cell (default: \tsobj[keys]{j}, see below)} - \describe{row}{\arg{rowtype}, Row type of the cell (default: \tsobj[keys]{t}, see below)} - \describe{colour}{=\arg{colour name}, Background colour of the cell (default: none)} - - Other keyword arguments include: - \describe{co}{=\arg{int}, Number of columns to span (default: 1)} - \describe{wd}{=\arg{dim}, Width of the cell, cannot be used with \tsobj[oarg]{ht}. (default: natural width)} - \describe{ht}{=\arg{dim}, Height of the cell, cannot be used with \tsobj[oarg]{wd}. (default: natural height)} - \describe{si}{=\arg{kwargs}, pass arguments to } -\end{describelist*} - - -The \arg{column}, for example, can be any combination of: - -\begin{describelist}{keys} - \describe{j}{Justified column (default), alias for \tsobj[keys]{Q[j]}} - \describe{l}{Left-aligned column, alias for \tsobj[keys]{Q[l]}} - \describe{c}{Centre-aligned column, alias for \tsobj[keys]{Q[c]}} - \describe{r}{Right-aligned column, alias for \tsobj[keys]{Q[r]}} - \describe{X[\arg{coltype}]}{Stretchable column type with the specified \arg{coltype} above i.e. \tsmeta{l, c, r, j}, alias for \tsverb[keys]{Q[co = 1, 1]}} -\end{describelist} - -Likewise, the \arg{row} can entail the following: -\begin{describelist}{keys} - \describe{h\{\arg{dim}\}}{``head''-aligned} - \describe{t\{\arg{dim}\}}{Top-aligned (default)} +\begin{codedescribe}[code, new = 2021B]{Q[ ... ]} + Unlike column specifications known in a typical \LaTeX\ fashion, the \tsverb{Q}-type in \pkg{tabularray} is a generic, flexible placeholder type that can act as any column/row type, as well as accommodating an array of features including dimensions, colouring and so on. + The \tsverb{Q} type takes the following \emph{optional} arguments: + \begin{describelist*}{oarg} + \describe{halign}{Horizontal alignment letter (default: \val{j}, see below)} + \describe{valign}{Vertical alignment letter (default: \val{t}, see below)} + \end{describelist*} + + Other keyword arguments include: + \begin{describelist*}{keys} + \describe{co}{=\arg{num}, Stretch coefficient, used to weight the share of the available width given to the column relative to other stretchable columns (default: \val{0}, not stretchable; \val{1} for \tsverb{X}). Only affects columns} + \describe{wd}{=\arg{dim}, Width of the column, \tsverb{colspec} only (default: natural width)} + \describe{ht}{=\arg{dim}, Height of the row, \tsverb{rowspec} only (default: natural height)} + \describe{si}{=\arg{kwargs}, pass arguments to \pkg{siunitx}'s number formatting; used internally by the \tsverb{S}/\tsverb{s} column types. Needs \tsobj[code, no index]{\UseTblrLibrary}\tsverb{{siunitx}}, \tsverb{colspec} only} + \describe{bgcolor}{=\arg{colour name}, Background colour of the cell (default: none). \key{bg} is a shorter alias. A bare colour name, e.g.\ \vrb{Q[red]}, is understood as \vrb{Q[bgcolor=red]}} + \end{describelist*} + + + The \arg{halign} letter can be any of the following. Each also works as a standalone type, as does the stretchable \tsverb{X}: + + \begin{describelist}{keys, no index} + \describe{j}{Justified column (default), alias for \tsobj[keys, no index]{Q[j]}} + \describe{l}{Left-aligned column, alias for \tsobj[keys, no index]{Q[l]}} + \describe{c}{Centre-aligned column, alias for \tsobj[keys, no index]{Q[c]}} + \describe{r}{Right-aligned column, alias for \tsobj[keys, no index]{Q[r]}} + \describe{X[\arg{halign}]}{Stretchable column type with the specified \arg{halign} above, alias for \tsverb[keys]{Q[co=1, ...]}} + \end{describelist} + + Likewise, the \arg{valign} letter can be any of the following. With a \arg{dim} in braces, each also works as a standalone type: \vrb{t{5em}} is \vrb{{Q[t,ht=5em]}} in \key{rowspec} and \vrb{{Q[t,wd=5em]}} in \key{colspec}. + \begin{describelist}{keys, no index} + \describe{h\{\arg{dim}\}}{``Head''-aligned: the text sits at the top edge of the row} + \describe{t\{\arg{dim}\}}{Top-aligned on the first baseline (default)} \describe{m\{\arg{dim}\}}{Middle-aligned} - \describe{b\{\arg{dim}\}}{Bottom-aligned} - \describe{f\{\arg{dim}\}}{``foot''-aligned} -\end{describelist} + \describe{b\{\arg{dim}\}}{Bottom-aligned on the last baseline} + \describe{f\{\arg{dim}\}}{``Foot''-aligned: the text sits at the bottom edge of the row} + \end{describelist} + + Between the types, \key{colspec} and \key{rowspec} accept the following specifiers: + \begin{describelist}{keys, no index} + \describe{|}{Draws a rule. \vrb{|[dashed]} passes rule keys to it} + \describe{>\{...\}}{Inserts material before the text of every cell in the next column or row, like \key{preto}} + \describe{<\{...\}}{Inserts material after the text of every cell in the previous column or row, like \key{appto}} + \describe{!\{...\}}{Replaces the rule with the given text} + \describe{@\{...\}}{Does the same as \vrb{!}, and also removes the space on either side of it} + \describe{*\{3\}\{...\}}{Repeats the given types 3 times} + \end{describelist} +\end{codedescribe} + +The following table visualises the combinations of the above keys for the \arg{halign} and \arg{valign} arguments of the \tsverb{Q} type: +\begin{center} + \tsdemo*[tblr]{Q-positioning} +\end{center} + +\section{Spanning Cells}\label{impatient:spanning} +A cell may be made to span multiple rows and/or columns, and this can be expressed in one of two equivalent ways. As a table command, \tsobj[code, no index]{\SetCell} is placed immediately before the text of the cell it applies to, which keeps the span beside the content it affects. As a \key{cell} key supplied directly in the \arg{inner spec}, it addresses the cell by its row and column number, which leaves the table body free of formatting but has to be revised if rows or columns move. + +\begin{codedescribe}[code]{SetCell, SetCells} + \begin{codesyntax} + \tsobj[code, no index]{\SetCell}[\oarg{span spec}]\{\arg{style spec}\} \tsmeta{cell text} + \bigskip + \tsobj[code, no index]{\SetCells}[\oarg{span spec}]\{\arg{style spec}\} \tsmeta{cell text} + \end{codesyntax} + \tsobj[code, no index]{\SetCell} applies \arg{style spec}, and optionally \arg{span spec}, to the single cell that follows it. \tsobj[code, no index]{\SetCells} instead applies to \emph{every} cell of the \env{tblr}, and may be placed at the start of any cell. + \begin{describelist*}{keys} + \describe{r}{=\arg{int}, Number of rows to span (default: 1)} + \describe{c}{=\arg{int}, Number of columns to span (default: 1)} + \end{describelist*} + \begin{tsremark} + \arg{style spec} accepts the same keys as \key{column, row} (\S\ref{colrow:positioning}): \key{halign, valign} (and their aliases \val{l,c,r,j,t,m,b,h,f}), \key{wd}, \key{bgcolor}, \key{fgcolor} (and the aliases \key{bg, fg}), \key{font}, \key{mode} (and \key{\$,\$\$}), \key{cmd}, \key{preto}, \key{appto}.\footnotemark[4] + \end{tsremark} + \begin{tsremark} + A cell that is covered by another cell's row/column span must be left empty, i.e. the corresponding \tsobj[code, no index]{&} field is supplied with no content. + \end{tsremark} + \begin{tsremark} + \tsobj[code, no index]{\multicolumn} and \tsobj[code, no index]{\multirow} are not supported and raise an error. + \end{tsremark} +\end{codedescribe} +\footnotetext[4]{Unlike \key{column, row}, the per-cell \arg{style spec} does not accept \key{ht}: row height can only be set via \key{rows, row}.} + +\begin{codedescribe}[keys]{cell, cells} + \begin{codesyntax} + \tsobj[code, no index]{\begin{tblr}}[\oarg{outer spec}]\{ + \quad\tsobj[keys, no index]{cell}\{\tsmeta{row}\}\{\tsmeta{col}\} \tsobj[code, no index]{=} \arg{span spec}\arg{style spec}, + \quad\keyval{cells}{\arg{span spec}\arg{style spec}}, + \quad\ldots + \} + \quad\ldots + \tsmacro{\end{tblr}}{} + \end{codesyntax} + \tsobj[keys, no index]{cell}\{\tsmeta{row}\}\{\tsmeta{col}\} is equivalent to placing \tsobj[code, no index]{\SetCell} at the given \tsmeta{row}/\tsmeta{col}; \key{cells} is equivalent to \tsobj[code, no index]{\SetCells}. + \begin{tsremark} + \tsmeta{row} and \tsmeta{col} each accept a single index (\vrb{2}), a comma-separated list (\vrb{{1,3}}), a range (\vrb{2-4}), the keywords \vrb{odd, even}, or a wildcard \vrb{-} meaning every row/column. + \end{tsremark} + \begin{tsremark} + A list of two-dimensional indexes may be supplied instead, as \vrb{cell{{i}{j},{i'}{j'},...}}; a range of such tuples, e.g.\ \vrb{cell{{i}{j}-{i'}{j'}}}, selects diagonally. + \end{tsremark} +\end{codedescribe} + +% cell-spanning demo +\begin{codestore}[st = cell-spanning] + \begin{tblr}{ + colspec = {Q[c]Q[c]Q[c]Q[c]}, + hlines, vlines, + cell{1}{1} = {r=2}{c,bg=blue!20}, + cell{1}{2} = {c=3}{c,bg=yellow!20}, + cell{2}{2} = {c=3}{c,bg=green!20}, + } + Bani Âdam & A’zâ-ye yekdigarand & & \\ + & Ke dar âfarinesh ze yek gowharand & & \\ + Sam & Zal & Rostam & Sohrab + \end{tblr} +\end{codestore} + +\begin{center} + \tsdemo*[tblr]{cell-spanning} +\end{center} + +\begin{codedescribe}[keys]{hspan, vspan} + \begin{codesyntax} + \keyval{hspan}{default | even | minimal} + \keyval{vspan}{default | even} + \end{codesyntax} + \key{hspan} sets how a wide spanning cell shares its width among the columns it covers, and \key{vspan} how a tall one shares its height among the rows. \val{even} shares the extra space out evenly, and \val{minimal} wraps the text of the spanning cell to the widths of its columns. +\end{codedescribe} + +\section{Rules and Borders}\label{impatient:rules} +Rules can be declared as keys in the \arg{inner spec} or placed in the table body as commands, and one table can use both. Keys keep the design of the rules in one place, while commands remain close to the rows they separate. A border is a related but distinct concept: it is the position a rule occupies, together with the space on either side, so its keys apply whether or not any rule is drawn. \S\ref{inner:rules} and \S\ref{inner:borders} examine these options at length. + +\begin{codedescribe}[keys]{hlines, vlines, hline, vline} + \begin{codesyntax} + \tsobj[code, no index]{\begin{tblr}}[\oarg{outer spec}]\{ + \quad\keyval{hlines}{\{\tsmeta{style}\}}, + \quad\keyval{vlines}{\{\tsmeta{style}\}}, + \quad\keysel{hline}{i}[\{\tsmeta{style}\}], + \quad\keysel{vline}{j}[\{\tsmeta{style}\}], + \quad\ldots + \} + \quad\ldots + \tsmacro{\end{tblr}}{} + \end{codesyntax} + \key{hlines, vlines} draw every horizontal and vertical rule of the table, and are solid if given no value. \key{hline, vline} draw selected rules only: rule \val{1} is above row 1 or left of column 1, and \vrb{Z} is the last rule. All 4 accept the keys below. + \begin{describelist*}{keys} + \deschead{Style} + \describe{dash}{Dash pattern: \val{solid, dashed, dotted} (Default: \val{solid})} + \describe{wd}{Width of the rule (Default: \val{0.4pt})} + \describe{fgcolor}{Colour of the rule} + \describe{bgcolor}{Colour of the gaps in a dashed or dotted rule} + \describe{text}{Material that replaces the rule} + \deschead{Ends of a Rule} + \describe{leftpos}{Left end of a horizontal rule, from \val{-1} to \val{1} (Default: \val{1}, which touches every crossing rule)} + \describe{rightpos}{Right end of a horizontal rule, in the same way} + \describe{abovepos}{Top end of a vertical rule, from \val{-1} to \val{1} (Default: \val{0})} + \describe{belowpos}{Bottom end of a vertical rule, in the same way} + \describe{lr}{Sets \key{leftpos, rightpos} at once (\val{-0.8} if given no value). \key{l, r} set one end each} + \describe{endpos}{Applies \key{leftpos, rightpos} only to the 2 ends of the table} + \begin{tsremark} + \key{fg, bg} are shorter aliases for \key{fgcolor, bgcolor}. Values of \key{dash, wd, fgcolor} can be supplied without the key, e.g.\ \vrb{{hlines = {1pt, red, dashed}}}. + \end{tsremark} + \end{describelist*} +\end{codedescribe} + +\begin{codedescribe}[code]{hline, cline, SetHline, SetHlines, vline, rline, SetVline, SetVlines} + \begin{codesyntax} + \tsobj[code, no index]{\hline}[\oarg{style}] + \tsobj[code, no index]{\cline}[\oarg{style}]\{\tsmeta{columns}\} + \tsobj[code, no index]{\SetHline}[\oarg{index}]\{\tsmeta{columns}\}\{\tsmeta{style}\} + \tsobj[code, no index]{\SetHlines}[\oarg{index}]\{\tsmeta{columns}\}\{\tsmeta{style}\} + \end{codesyntax} + \tsobj[code, no index]{\hline, \cline} go between rows, and accept the style keys above in their optional argument. \tsobj[code, no index]{\SetHline} at the start of a row is the same as \key{hline} for that row, and \tsobj[code, no index]{\SetHlines} is the same as \key{hlines}. \tsobj[code, no index]{\vline, \rline, \SetVline, \SetVlines} are the vertical equivalents. +\end{codedescribe} + +\begin{codedescribe}[keys]{hborder, vborder} + \begin{codesyntax} + \keysel{hborder}{i}[\{\tsmeta{keys}\}] + \keysel{vborder}{j}[\{\tsmeta{keys}\}] + \end{codesyntax} + \key{hborder, vborder} set the properties of a border as a whole, in place of one rule within it. Border \val{1} is above row 1 or left of column 1. + \begin{describelist*}[24mm]{keys} + \describe{abovespace}{Space above an \key{hborder}, i.e.\ the \key{belowsep} of the row before it} + \describe{belowspace}{Space below an \key{hborder}, i.e.\ the \key{abovesep} of the row after it} + \describe{leftspace}{Space left of a \key{vborder}, i.e.\ the \key{rightsep} of the column before it} + \describe{rightspace}{Space right of a \key{vborder}, i.e.\ the \key{leftsep} of the column after it} + \describe{pagebreak}{Page break at an \key{hborder} of a long table: \val{yes, no, auto} (Default: \val{auto})} + \begin{tsremark} + Each space key has a \key[no index]{+} variant that adds to the current value. The commands \tsobj[code, no index]{\hborder, \vborder} set the same keys from the table body, and \tsobj[code, no index]{\pagebreak, \nopagebreak} are short forms of \vrb{pagebreak=yes} and \vrb{pagebreak=no}. + \end{tsremark} + \end{describelist*} \end{codedescribe} -The following table visualises the combinations of the above keys for the \arg{column} and \arg{row} arguments of the \tsverb{Q} type: +% rules and borders demo +\begin{codestore}[st = rules-borders] + \begin{tblr}{ + hline{1,Z} = {1pt}, + vline{2} = {dashed}, + hborder{2} = {belowspace=8pt}, + } + Rule & Exception \\ + \hline[dotted] + Law & Transgression + \end{tblr} +\end{codestore} + \begin{center} -\tsdemo*[tblr]{Q-positioning} + \tsdemo*[tblr]{rules-borders} \end{center} -\clearpage \ No newline at end of file + +\section{Table-wide Options}\label{impatient:table} +A few properties belong to the table as a whole and cannot be attributed to any column or row. Their keys are written directly in the \arg{inner spec}, and \S\ref{inner:table} examines them at length. + +\begin{codedescribe}[keys]{stretch, rulesep, baseline, delimiter, rowhead, rowfoot, name} + \begin{codesyntax} + \tsobj[code, no index]{\begin{tblr}}[\oarg{outer spec}]\{ + \quad\keyval{stretch}{\arg{num}}, + \quad\keyval{rowhead}{\arg{int}}, + \quad\ldots + \} + \quad\ldots + \tsmacro{\end{tblr}}{} + \end{codesyntax} + \begin{describelist*}{keys} + \describe{stretch}{Scale of the strut added to every cell, which sets the least height of a row. Replaces \tsobj[code, no index]{\arraystretch} (Default: \val{1})} + \describe{rulesep}{Space between 2 rules drawn in the same place. Replaces \tsobj[code, no index]{\doublerulesep} (Default: \val{2pt})} + \describe{baseline}{Part of the table that lines up with the surrounding text: \val{t, T, m, M, b, B}, or a row number (Default: \val{m})} + \describe{delimiter}{Stretching delimiters, e.g.\ \vrb{{delimiter = {left = (, right = )}}}} + \describe{rowhead}{Number of first rows that repeat on every page of a long table (Default: \val{0})} + \describe{rowfoot}{Number of last rows that repeat on every page of a long table (Default: \val{0})} + \describe{name}{Name of the table, which the \pkg{tikz} library uses to address its nodes} + \end{describelist*} +\end{codedescribe} + +\section{Specifications of the Outer Components}\label{impatient:outer} +The \oarg{outer spec} is optional, and most of its keys build the head and foot around a table, such as its caption and notes. A \env{tblr} has neither, so those keys only change the output of a \env{talltblr} or a \env{longtblr}. Each group below leads to a section that shows the keys in use. + +\begin{codedescribe}{} + \begin{codesyntax} + \tsobj[code, no index]{\begin{talltblr}}[ + \quad\keyval{caption}{\arg{text}}, + \quad\keyval{label}{\arg{name}}, + \quad\keysel{note}{tag}[\arg{text}], + \quad\ldots + ]\{\arg{inner spec}\} + \quad\ldots + \tsmacro{\end{talltblr}}{} + \end{codesyntax} + \begin{describelist*}{keys} + \deschead{Table Type (\S\ref{outer:types})} + \describe{long}{Makes a \env{tblr} a long table, the same as writing \env{longtblr}} + \describe{tall}{Makes a \env{tblr} a tall table, the same as writing \env{talltblr}} + \deschead{Placement (\S\ref{outer:placement})} + \describe{halign}{Horizontal position of a long table: \val{l, c, r} (Default: \val{c})} + \describe{baseline}{Part of the table that lines up with the surrounding text, as in \S\ref{impatient:table}} + \deschead{Captions and Labels (\S\ref{outer:captions})} + \describe{caption}{Text of the caption above the table} + \describe{label}{Label for \tsobj[code, no index]{\ref}. With \val{none}, the table is left unnumbered} + \describe{entry}{Short caption for the List of Tables. With \val{none}, the table is left out of the list} + \begin{tsremark} + \key{halign, baseline} can be written without the key name, e.g.\ \vrb{[r]} for \vrb{[halign=r]}. + \end{tsremark} + \end{describelist*} +\end{codedescribe} + +\begin{codedescribe}{} + \begin{describelist*}{keys} + \deschead{Notes and Remarks (\S\ref{outer:notes})} + \describe{note}{\keysel{note}{tag}: text in the foot, tied to a cell by \tsobj[code, no index]{\TblrNote}\{\tsmeta{tag}\}} + \describe{remark}{\keysel{remark}{tag}: text in the foot, about the table as a whole} + \describe{more}{\keysel{more}{name}: extra text for a template to pick up} + \deschead{Spacing (\S\ref{outer:spacing})} + \describe{headsep}{Space between the head and the table body (Default: \val{6pt})} + \describe{footsep}{Space between the table body and the foot (Default: \val{6pt})} + \describe{presep}{Space between a long table and the text above it (Default: \tsobj[code, no index]{1.5\bigskipamount})} + \describe{postsep}{Space between a long table and the text below it (Default: \tsobj[code, no index]{1.5\bigskipamount})} + \deschead{Themes and Macros (\S\ref{outer:themes}, \S\ref{outer:expand})} + \describe{theme}{Name of a set of template and style settings defined with \tsobj[code, no index]{\NewTblrTheme}} + \describe{expand}{Macros to expand before the table body is split into cells, which any macro containing \tsverb{&} or \tsverb{\\} needs} + \describe{expand+}{Macros to add to the current list of \key{expand}} + \end{describelist*} +\end{codedescribe} + +% notes demo +\begin{codestore}[st = outer-notes] + \begin{talltblr}[ + caption = {A table with notes}, + note{a} = {Impossible.}, + note{b} = {Enjoy.}, + remark{Source} = {Lacan, \emph{Le sinthome}.}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 8cm, + } + Real\TblrNote{a} & Symbolic \\ + Imaginary & Sinthome\TblrNote{b} + \end{talltblr} +\end{codestore} + +\begin{center} + \tsdemo*[tblr]{outer-notes} +\end{center} + +\section{Libraries}\label{impatient:libraries} +Support for other packages is kept out of the core of \pkg{tabularray}, so a feature such as the rules of \pkg{booktabs} has to be requested by name. Several libraries act on every table once loaded, which makes it prudent to load only those a document uses. + +\begin{codedescribe}[code]{UseTblrLibrary} + \begin{codesyntax} + \tsobj[code, no index]{\UseTblrLibrary}\{\arg{library list}\} + \end{codesyntax} + \tsobj[code, no index]{\UseTblrLibrary} loads one or more libraries, given as a comma-separated list, and belongs in the preamble. The most common ones are below, and \S\ref{lib:loading} lists them all. + \begin{describelist*}[24mm]{pkg, no index} + \describe{amsmath}{Math environments built on \env[no index]{tblr}, such as \env[no index]{+array} and \env[no index]{+bmatrix}} + \describe{booktabs}{The rules \tsobj[code, no index]{\toprule, \midrule, \cmidrule, \bottomrule}, and the environment \env[no index]{booktabs}} + \describe{diagbox}{Cells divided by diagonal lines, with \tsobj[code, no index]{\diagbox}} + \describe{functional}{Functions in specifications, and the keys \key[no index]{evaluate, process}} + \describe{siunitx}{The column types \tsverb{S} and \tsverb{s}, for numbers and units} + \describe{varwidth}{The key \key[no index]{measure}, for vertical material in cells} + \end{describelist*} +\end{codedescribe} + +\section{Reusing a Design}\label{impatient:reuse} +Repeating a specification across a document is tedious and prone to error, so \pkg{tabularray} allows it to be declared once. The commands below change the defaults of an environment, or define a new environment with defaults of its own. + +\begin{codedescribe}[code]{SetTblrInner, SetTblrOuter, NewTblrEnviron} + \begin{codesyntax} + \tsobj[code, no index]{\SetTblrInner}[\oarg{environments}]\{\arg{inner spec}\} + \tsobj[code, no index]{\SetTblrOuter}[\oarg{environments}]\{\arg{outer spec}\} + \tsobj[code, no index]{\NewTblrEnviron}\{\arg{name}\} + \end{codesyntax} + \tsobj[code, no index]{\SetTblrInner, \SetTblrOuter} add to the default specifications of every table created afterwards. Each environment has its own defaults, so they apply to \env{tblr} unless \oarg{environments} names others: \tsverb*{\SetTblrInner[tblr, longtblr]{rowsep=0pt}} leaves a \env{talltblr} unchanged. \tsobj[code, no index]{\NewTblrEnviron} defines a new environment, which takes the same arguments as \env{tblr}. + \begin{tsremark} + New column and row types are defined with \tsobj[code, no index]{\NewTblrColumnType} and its relatives (\S\ref{inner:types}), and new themes with \tsobj[code, no index]{\NewTblrTheme} (\S\ref{outer:themes}). + \end{tsremark} +\end{codedescribe} + +% new environment demo +\begin{codestore}[st = reuse-design] + \NewTblrEnviron{borromean} + \SetTblrInner[borromean]{hlines, vlines, columns = {c}} + \SetTblrOuter[borromean]{baseline=T} + Base\begin{borromean}{} + Real & Symbolic \\ + Imaginary & Sinthome + \end{borromean}Base +\end{codestore} + +\begin{center} + \tsdemo*[tblr]{reuse-design} +\end{center} \ No newline at end of file diff --git a/doc/02-inner.tex b/doc/02-inner.tex index 3084e60..6d080d5 100644 --- a/doc/02-inner.tex +++ b/doc/02-inner.tex @@ -1,87 +1,1382 @@ \chapter{Specifications of the Inner Components with Examples} -As highlighted briefly in \ref{impatient:inner}, the \vrb{inner} specification refers to any and all specification that is directly related to the table itself, including column and row specifications. These are supplied within the \arg{inner spec} argument in a key--value format. +This chapter examines the \vrb{inner} specification, introduced briefly in \S\ref{impatient:inner}, which covers everything directly related to the table itself, including its columns and rows. It is supplied within the \arg{inner spec} argument in a key--value format. -In this chapter, we show applied examples of the inner specifications. Note that \pkg{tabularray} provides a wide range of options to achieve the same thing---then it is up to the user to choose the most intuitive and efficient way for them to achieve the desired result. +A defining feature of this interface is its redundancy: \pkg{tabularray} commonly offers several routes to the same output, such as a key in the specification and a command in the table body. +We thus aim to showcase comprehensive (but not exhaustive) examples of using \pkg{tabularray}, but not prescribe to a correct method of typesetting, since the most intuitive and efficient choice depends on the table---and most importantly: on you and your preferences. +In short, the examples hereinafter isolate one option at a time so that its effect can be observed directly. +Please read them as an overview of each option and its applications, not as a full account of how the options interact. -While it is our intention to provide a comprehensive guide to showcase the inner specifications, the examples delineated here are thus not intended to be exhaustive, but rather to provide a general overview of the inner specifications and their applications. +\section{Column and Row Options}\label{inner:colrow} +Columns and rows are the principal units of a specification, and most of the appearance of a table is set through them. Because options apply by selection and not by position in the table body, a single key can style many cells and the body stays free of formatting. Selection by index does depend on the shape of the table, however: inserting a row renumbers those after it, which is one reason the selectors of \S\ref{inner:selectors} can also count from the end. -\section{Column-wise Options} \begin{codedescribe}[ - marg, - new=2021F, - update=2021G, - update=2021L -]{columns} + key, + new=2021F, + update=2021L + ]{columns} \begin{codesyntax} - \tsobj[code, no index]{\begin{tblr}}\tsobj[oarg]{outer spec}\{ - \quad\keyval{columns}{kwargs} - \quad\ldots - \} - \quad\ldots - \tsmacro{\end{tblr}}{} + \tsobj[code, no index]{\begin{tblr}}[\oarg{outer spec}]\{ + \quad\keyval{columns}{kwargs} + \quad\ldots + \} + \quad\ldots + \tsmacro{\end{tblr}}{} \end{codesyntax} -\key{columns} is the most intuitive key, and a familiar concept for those who have experience with \LaTeX's \env[no index]{tabular}. It generally represents the global column-wise specification for all columns in a given \env{tblr}. + \key{columns} is the most intuitive key, and a familiar concept for those who have experience with \LaTeX's \env*[no index]{tabular}. It generally represents the global column-wise specification for all columns in a given \env{tblr}. It accepts every key in this section, except for those marked as \vrb{row} only. + + \begin{codestore}[st=columns:columns] + \begin{tblr}{hlines, vlines} + Real & Symbolic \\ + Imaginary & Sinthome + \end{tblr}\quad + \begin{tblr}{ + hlines, vlines, + columns = {c, bg=yellow!30} + } + Real & Symbolic \\ + Imaginary & Sinthome + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:columns} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021F + ]{column} + \begin{codesyntax} + \keysel{column}{j}[\{\tsmeta{keys}\}] + \end{codesyntax} + \key{column} applies the same keys as \key{columns}, but only to the columns selected by \tsmeta{j} (see \S\ref{inner:selectors}). + + \begin{codestore}[st=columns:column] + \begin{tblr}{ + hlines, vlines, + column{2} = {r, bg=yellow!30} + } + Desire & Drive \\ + Fantasy & Jouissance + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:column} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021F, + update=2021L + ]{rows} + \begin{codesyntax} + \keyval{rows}{\{\tsmeta{keys}\}} + \end{codesyntax} + \key{rows} is the row-wise counterpart of \key{columns}, and applies keys to every row of the table. It accepts every key in this section, except for those marked as \vrb{column} only. + + \begin{codestore}[st=columns:rows] + \begin{tblr}{hlines, vlines} + Real & Symbolic \\ + Imaginary & Sinthome + \end{tblr}\quad + \begin{tblr}{ + hlines, vlines, + rows = {ht=8mm, bg=yellow!30} + } + Real & Symbolic \\ + Imaginary & Sinthome + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:rows} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021F + ]{row} + \begin{codesyntax} + \keysel{row}{i}[\{\tsmeta{keys}\}] + \end{codesyntax} + \key{row} applies the same keys as \key{rows}, but only to the rows selected by \tsmeta{i} (see \S\ref{inner:selectors}). + + \begin{codestore}[st=columns:row] + \begin{tblr}{ + hlines, vlines, + row{1} = {font=\bfseries, bg=yellow!30} + } + Real & Symbolic \\ + Imaginary & Sinthome + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:row} + \end{center} +\end{codedescribe} + +\subsection{Selecting Columns and Rows}\label{inner:selectors} +\begin{codedescribe}[ + value, + new=2021F, + update=2021P, + update=2022A, + update=2025A + ]{odd, even, every, U...Z} + Keys that address part of a table, such as \key{column}, \key{row}, \key{cell}, \key{hline} and \key{vline}, select what they apply to with any of the following forms. These may be combined in a comma-separated list, e.g.\ \vrb{{row{1,3-4,Z}}}. + \begin{describelist*}{values} + \describe{2}{A single index} + \describe{2-4}{A range of indexes} + \describe{-}{Every row or column} + \describe{odd}{Every odd index. \vrb{odd[5]} starts from index 5} + \describe{even}{Every even index. \vrb{even[4]} starts from index 4} + \describe{every}{\vrb{every}[\tsmeta{step}]\{\tsmeta{start}\}\{\tsmeta{end}\} selects the indexes from \tsmeta{start} to \tsmeta{end}, which may be negative to count from the end} + % TODO: document Z[] here once it works again (broken by cd75229, #638?) + \describe{U...Z}{The last 6 indexes: \vrb{Z} is the last, \vrb{Y} the second last, and so on} + \end{describelist*} + + \begin{codestore}[st=columns:selectors] + \begin{tblr}{ + hlines, vlines, + cell{1}{even} = {bg=yellow!30}, + cell{2}{odd[3]} = {bg=green!30}, + cell{3}{every[3]{1}{-1}} = {bg=cyan!30}, + cell{4}{2-Y} = {bg=blue!20}, + } + 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ + 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ + 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ + 1 & 2 & 3 & 4 & 5 & 6 & 7 + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:selectors} + \end{center} +\end{codedescribe} + +\subsection{Positioning and Dimensions} +\begin{codedescribe}[ + key, + new=2021L + ]{halign} + \begin{codesyntax} + \keyval{halign}{l | c | r | j} + \end{codesyntax} + The \key{halign} key represents the horizontal alignment of the cell content. It accepts four values: \val{j, l, c, r}, which represent justified, left-aligned, centred and right-aligned content, respectively. The default value is \val{j}. Values of this key can be supplied without the key. +\end{codedescribe} + +\begin{codedescribe}[ + value, + new=2021A, + update=2021L + ]{l,c,r} + \val{l,c,r} represent left-aligned, centred and right-aligned cell content, respectively, and behave the same as those of \LaTeX's \env*[no index]{tabular}. All of these keys can be supplied without \key{halign}: \vrb{columns={l}} is equivalent to \vrb{columns={halign=l}}. + + \begin{codestore}[st=columns:lcr] + \begin{tblr}{ + hlines, vlines, + columns = {24em}, + row{1} = {l}, + row{2} = {c}, + row{3,4} = {r}, + } + Asrâr-e azal râ na to dâni-o na man \\ + Win harf-e mu’amma na to khâni-o na man \\ + Hast az pas-e pare guftegu-ye man-o-to \\ + Chun parde baroftad na to mâni-o na man + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:lcr} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + value, + new=2021N + ]{j} + \val{j} represents justified cell content. This is the default value for \key{halign}, and it can be supplied without the key, such that \vrb{j} is equivalent to \keyval{halign}{j}. Observe the ugly justification of Khayyam's beautiful quatrain. + + \begin{codestore}[st=columns:j] + \begin{tblr}{ + hlines, vlines, + columns = {8em} % `j' already implied by default + } + Asrâr-e azal râ na to dâni-o na man \\ + Win harf-e mu’amma na to khâni-o na man \\ + Hast az pas-e pare guftegu-ye man-o-to \\ + Chun parde baroftad na to mâni-o na man + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:j} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{valign} + \begin{codesyntax} + \keyval{valign}{t | p | m | b | h | f} + \end{codesyntax} + The \key{valign} key represents the vertical alignment of the cell content. It accepts the values \val{t, p, m, b, h, f}, which represent top, paragraph (an alias of \val{t}), middle, bottom, head and foot alignment, respectively. The default value is \val{t}. Values of this key can be supplied without the key. +\end{codedescribe} + +\begin{codedescribe}[ + value, + new=2021B, + update=2021L + ]{t,p,m,b} + \val{t,p,m,b} represent top, paragraph, middle and bottom-aligned cell content, respectively; \val{p} is simply an alias of \val{t}. All of these keys can be supplied without \key{valign}: \vrb{columns={m}} is equivalent to \vrb{columns={valign=m}}. + + \begin{codestore}[st=columns:tmb] + \begin{tblr}{ + colspec = {|Q[t]|Q[m]|Q[b]|}, + rowspec = {|Q[5em]|}, + hlines, vlines, + } + {Top \\line1\\line2} & {Mid\\line1\\line2} & {Bot\\line1\\line2} + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:tmb} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + value, + new=2021G, + update=2021L + ]{h,f} + \val{h,f} represent head- and foot-aligned cell content, respectively: \val{h} places the text at the top edge of the row and \val{f} at the bottom edge, whereas \val{t,b} align on the first and last baselines. The difference shows when another cell in the row is taller, as with the middle cell below. Values of this key can be supplied without \key{valign}. + + \begin{codestore}[st=columns:hf] + \begin{tblr}{ + colspec = {Q[h,4em]Q[t,4em]Q[m,4em]Q[b,4em]Q[f,4em]}, + hlines, + } + {row \\head} & {top\\line} & {11\\22\\mid\\44\\55} & {line\\bottom} & {row\\foot} + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:hf} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021B, + update=2021L + ]{wd} + \begin{codesyntax} + \keyval{wd}{\arg{dim}} + \end{codesyntax} + \key{wd} sets the width of a column (\vrb{column} only); the dimension may be given as a fixed length or as a fraction of \tsobj[code, no index]{\linewidth} via the usual \LaTeX\ dimension syntax. It can be supplied without the key, and text that does not fit wraps within the given width. + + \begin{codestore}[st=columns:wd] + \begin{tblr}{hlines, vlines} + Žižek & The most dangerous unfreedom is the unfreedom + that we experience as freedom + \end{tblr} + + \begin{tblr}{ + hlines, vlines, + column{2} = {wd=3cm} + } + Žižek & The most dangerous unfreedom is the unfreedom + that we experience as freedom + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:wd} + \end{center} \end{codedescribe} \begin{codedescribe}[ - key, - new=2021L -]{halign} -\begin{codesyntax} -\end{codesyntax} - The \key{halign} key represents the horizontal alignment of the cell content. It accepts four values: \val{j, l, c, r}, which represent justified, left-aligned, centered and right-aligned content, respectively. The default value is \val{j}. + key, + new=2021F, + update=2021L + ]{ht} + \begin{codesyntax} + \keyval{ht}{\arg{dim}} + \end{codesyntax} + \key{ht} sets the height of a row (\vrb{row} only). It can be supplied without the key. + + \begin{codestore}[st=columns:ht] + \begin{tblr}{ + hlines, vlines, + row{2} = {ht=1cm} + } + Real & Symbolic \\ + Imaginary & Sinthome \\ + Subject & Other + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:ht} + \end{center} +\end{codedescribe} + +\subsection{Colour and Font} +\begin{codedescribe}[ + key, + new=2021E, + update=2021F, + update=2021L, + update=2026A + ]{bgcolor, bg} + \begin{codesyntax} + \keyval{bgcolor}{\arg{colour}} + \end{codesyntax} + \key{bgcolor} sets the background colour of a column, row, or cell, and accepts any colour name known to \pkg{xcolor}. \key{bg} is a shorter alias, e.g.\ \vrb{bg=red} is equivalent to \vrb{bgcolor=red}. A colour name can also be supplied without the key. \begin{tsremark} - Values of this key can be supplied without the key. + \pkg{tabularray} loads \pkg{xcolor} itself as of 2026A, but no longer loads \pkg{ninecolors}. Names such as \vrb{blue7} now need \tsverb*{\usepackage{ninecolors}}. \end{tsremark} \end{codedescribe} \begin{codedescribe}[ - value, - new=2021L -]{l,c,r} - \val{l,c,r} represent left-aligned, centred and right-aligned cell content, respectively, and behave the same as that of \LaTeX's \env[no index]{tabular}. + key, + new=2021K, + update=2021L, + update=2021P, + update=2026A + ]{fgcolor, fg} + \begin{codesyntax} + \keyval{fgcolor}{\arg{colour}} + \end{codesyntax} + \key{fgcolor} sets the colour of the text of a column, row, or cell. \key{fg} is a shorter alias, e.g.\ \vrb{fg=white} is equivalent to \vrb{fgcolor=white}. The 2 columns below use different names to the same effect. + + \begin{codestore}[st=columns:bgfgcolor] + \begin{tblr}{ + hlines, vlines, + column{1} = {bgcolor=yellow!30, fgcolor=blue!60!black}, + column{2} = {bg=yellow!30, fg=blue!60!black}, + } + Shops & Full \\ + Food & Abundant \\ + Red ink & Unavailable + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:bgfgcolor} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021K, + update=2021L + ]{font} + \begin{codesyntax} + \keyval{font}{\arg{font commands}} + \end{codesyntax} + \key{font} sets the font of the column/row/cell text by executing the given font-switching commands (e.g.\ \tsobj[code, no index]{\bfseries}, \tsobj[code, no index]{\itshape\Large}) before the cell text, followed by \tsobj[code, no index]{\selectfont}. + + \begin{codestore}[st=columns:font] + \begin{tblr}{ + hlines, vlines, + row{1} = {font=\bfseries}, + column{2} = {font=\itshape\Large}, + } + Libertà & Libertà \\ + Libertà & Libertà + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:font} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021P + ]{mode, \$, \$\$} + \begin{codesyntax} + \keyval{mode}{text | math | imath | dmath} + \end{codesyntax} + \key{mode} sets the mode in which the cell text is typeset: \val{text}, \val{math}, \val{imath} or \val{dmath}. The default is \val{text}, or \val{math} when the table itself is in math mode. \val{math} sets no math style of its own, while \val{imath} forces \tsobj[code, no index]{\textstyle} and \val{dmath} forces \tsobj[code, no index]{\displaystyle}. \key{\$} is a shorter alias for \keyval{mode}{math}, and \key{\$\$} for \keyval{mode}{dmath}. + + In the table below, the second column takes the default of \val{math} because the table is in math mode. + + \begin{codestore}[st=columns:mode] + $\begin{tblr}{ + hlines, + column{1} = {mode=text}, + column{3} = {mode=dmath}, + } + Non-All & \frac12 & \frac12 \\ + Surplus & \frac54 & \frac54 + \end{tblr}$\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:mode} + \end{center} \begin{tsremark} - All of these keys can be supplied without the \key{halign}. \vrb{columns={l}} is equivalent to \vrb{columns={halign=l}}. + Multiline math, such as \tsverb*{{\alpha\\\beta}}, cannot be written directly in a math-mode cell. \end{tsremark} +\end{codedescribe} - \begin{codestore}[st=columns:lcr] +\subsection{Utilities} +\begin{codedescribe}[ + key, + new=2021L, + update=2021P + ]{cmd} + \begin{codesyntax} + \keyval{cmd}{\arg{control sequence}} + \end{codesyntax} + \key{cmd} names a control sequence of one argument to execute on the text of every affected cell, e.g.\ \tsverb**[verb]{cmd=\textbf} applies \tsobj[code, no index]{\textbf} to the cell content. + + \begin{codestore}[st=columns:cmd] \begin{tblr}{ - columns = {l} - } - Asrâr-e azal râ na to dâni-o na man\\ - Win harf-e mu’amma na to khâni-o na man\\ - Hast az pas-e pare guftegu-ye man-o-to\\ - Chun parde baroftad na to mâni-o na man + column{1} = {cmd=\textbf}, + column{2} = {cmd=\fbox}, + } + Desire & Lack \\ + Drive & Loop + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:cmd} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021K + ]{preto, appto} + \begin{codesyntax} + \keyval{preto}{\arg{material}} + \keyval{appto}{\arg{material}} + \end{codesyntax} + \key{preto} and \key{appto} insert material immediately before and after the text of every affected cell, respectively. See \S\ref{colrow:colour} for how \key{preto, appto} interact when set on both \key{columns} and \key{rows}, and how \key{preto} relates to \key{font}. + + \begin{codestore}[st=columns:pretoappto] + \begin{tblr}{ + hlines, vlines, + column{2} = {preto={[}, appto={]}}, + } + Absolute & Recoil \\ + Looking & Awry + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:pretoappto} + \end{center} +\end{codedescribe} + +\subsection{Spacing} +\begin{codedescribe}[ + key, + new=2021G, + update=2021L, + update=2026A + ]{rowsep, rowsep+, abovesep, abovesep+, belowsep, belowsep+} + \begin{codesyntax} + \keyval{abovesep}{\arg{dim}} + \keyval{belowsep}{\arg{dim}} + \keyval{rowsep}{\arg{dim}} + \end{codesyntax} + \key{abovesep, belowsep} set the vertical space above/below a row (\vrb{row} only; default \val{2pt} each); \key{rowsep} is a shorter alias that sets both at once. The \key[no index]{+} variants add to, rather than replace, the current value---useful for adjusting the default without having to repeat it. A negative value that leaves a row with no height gives a warning. + + \key{rowsep, abovesep, belowsep} can also be written directly in the \arg{inner spec} to apply to every row. The \key[no index]{+} variants cannot. + + \begin{codestore}[st=columns:rowsep] + \begin{tblr}{hlines, vlines} + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{hlines, vlines, rowsep=6pt} + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{ + hlines, vlines, + row{1} = {belowsep+=6pt} + } + Real & Lack \\ + Void & Drive \end{tblr}\end{codestore} \begin{center} - \tsdemo*[tblr]{columns:lcr} + \tsdemo*[tblr]{columns:rowsep} \end{center} \end{codedescribe} \begin{codedescribe}[ - value, - new=2021N -]{j} - \val{j} represents justified cell content. This is the default value for \key{halign}. + key, + new=2021G, + update=2021L, + update=2026A + ]{colsep, colsep+, leftsep, leftsep+, rightsep, rightsep+} + \begin{codesyntax} + \keyval{leftsep}{\arg{dim}} + \keyval{rightsep}{\arg{dim}} + \keyval{colsep}{\arg{dim}} + \end{codesyntax} + \key{leftsep, rightsep} set the horizontal space before/after a column (\vrb{column} only; default \val{6pt} each); \key{colsep} is a shorter alias that sets both at once. As with \key{rowsep}, the \key[no index]{+} variants add to the current value, a negative value that leaves a column with no width gives a warning, and all but the \key[no index]{+} variants can be written directly in the \arg{inner spec}. + + \begin{codestore}[st=columns:sepplus] + \begin{tblr}{ + colspec = {|X[l]|X[l]|}, + hlines, vlines, + column{2} = {leftsep+=1em}, + } + Default leftsep & leftsep + 1em + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:sepplus} + \end{center} +\end{codedescribe} + +\subsection{Table Commands} +\begin{codedescribe}[ + code, + new=2021F + ]{SetRow, SetRows, SetColumn, SetColumns} + \begin{codesyntax} + \tsobj[code, no index]{\SetRow}\{\tsmeta{keys}\} \tsmeta{cell text} + \end{codesyntax} + These commands set the same keys from inside the table body, at the start of a cell. \tsobj[code, no index]{\SetRow} in row \tsmeta{i} is the same as \keysel{row}{i}[\{\tsmeta{keys}\}], \tsobj[code, no index]{\SetColumn} in column \tsmeta{j} is the same as \keysel{column}{j}[\{\tsmeta{keys}\}], and \tsobj[code, no index]{\SetRows, \SetColumns} are the same as \key{rows, columns}. + + \begin{codestore}[st=columns:setrow] + \begin{tblr}{llll} + \hline + \SetRow{bg=blue!20} Id & \SetColumn{r} Ego & Superego & Drive \\ + \hline + \SetRow{bg=yellow!30, c} Need & Demand & Desire & Lack \\ + \hline + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{columns:setrow} + \end{center} +\end{codedescribe} + +\section{Column and Row Types}\label{inner:types} +A type condenses the settings of a column or row into a single letter, which gives a specification the compactness of a \LaTeX{} preamble. That compactness has limits. A long string of letters conveys less than the equivalent keys, and it has to keep pace with the number of columns. The types below range from shorthand letters to the explicit \tsverb{Q}, and a table can combine them with the keys of \S\ref{inner:colrow}. + +\begin{codedescribe}[ + key, + new=2021B, + update=2021F + ]{colspec, rowspec} + \begin{codesyntax} + \keyval{colspec}{\{\tsmeta{column types}\}} + \keyval{rowspec}{\{\tsmeta{row types}\}} + \end{codesyntax} + \key{colspec} gives one type letter for each column, as in the preamble of \LaTeX's \env*[no index]{tabular}, and \key{rowspec} does the same for each row. The name \key{colspec} can be left out if it is the only key in the \arg{inner spec}, so the first two tables below are the same. + + \begin{codestore}[st=types:colspec] + \begin{tblr}{colspec = {|l|c|r|}} + Id & Ego & Superego + \end{tblr}\quad + \begin{tblr}{|l|c|r|} + Id & Ego & Superego + \end{tblr}\quad + \begin{tblr}{ + colspec = {lcr}, + rowspec = {|Q|Q|}, + } + Id & Ego & Superego \\ + Need & Demand & Desire + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:colspec} + \end{center} \begin{tsremark} - Values of this key can be supplied without the key, such that \vrb{j} is equivalent to \keyval{halign}{j}. + With the \pkg{functional} library loaded, a \key{colspec} containing \vrb{=}, such as \vrb{Q[bg=red]}, must keep its name. \end{tsremark} +\end{codedescribe} - \begin{codestore}[st=columns:j] +\begin{codedescribe}[ + code, + new=2021B + ]{Q[ ... ]} + \begin{codesyntax} + \tsverb{Q[}\tsmeta{keys}\tsverb{]} + \end{codesyntax} + \tsverb{Q} is the flexible, do-everything placeholder type introduced in \S\ref{impatient:qtype}. In \key{colspec} it accepts the keys of \key{column}, and in \key{rowspec} those of \key{row}, so a column can be styled where it is declared. + + \begin{codestore}[st=types:q] + \begin{tblr}{ + colspec = {|Q[l,t]|Q[c,m,bg=yellow!30]|Q[r,b,fg=blue]|} + } + \hline + {Top Baseline \\Left Left} & Middle Centre & {Right Right\\Bottom Baseline} \\ + \hline + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:q} + \end{center} + \begin{tsremark} + \tsverb{Q}, \tsverb{|} (for rules), \tsverb{<} and \tsverb{>} are the only primitive types in \pkg{tabularray}. Every other column/row type, including \tsverb{l, c, r, j, X} and the dimensioned types below, is defined in terms of these. \tsverb{Q} was named \tsverb{Y} in 2021A. + \end{tsremark} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021B + ]{co} + \begin{codesyntax} + \keyval{co}{\arg{num}} + \end{codesyntax} + \key{co} sets the stretch coefficient of an \tsverb{X}-type column, weighting the share of the available table width it receives relative to other \tsverb{X}-type columns in the same table (default: \val{1}). It can be supplied without the key, e.g.\ \vrb{X[2]}. A negative coefficient is also allowed: its absolute value sets the weight, but the column stops at its natural width and the spare width goes to the other columns. If every stretchable column has stopped at its natural width, the spare width is shared in proportion to those widths. + + In the second table below, the column with \vrb{X[-1]} stops at its natural width. In the third, the text is long enough to reach the weights, so \vrb{X[-2]} takes twice the width of \vrb{X[-1]}. + + \begin{codestore}[st=types:co] + \begin{tblr}{colspec = {|X[1]|X[2]|}, width = 10cm} + One share & Two shares + \end{tblr} + + \begin{tblr}{colspec = {|X[1]|X[-1]|}, width = 10cm} + The rest & Natural + \end{tblr} + + \begin{tblr}{colspec = {|X[-2]|X[-1]|}, width = 10cm} + There was the Door to which I found no Key; + There was the Veil through which I might not see: & + Some little talk awhile of Me and Thee + There was---and then no more of Thee and Me. + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:co} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + value, + new=2021A, + update=2021F, + update=2021N + ]{l,c,r,j} + As bare column/row types (i.e.\ usable directly in \key{colspec, rowspec} without \tsverb{Q[...]}), \val{l, c, r, j} are shorthand for \vrb{Q[l]}, \vrb{Q[c]}, \vrb{Q[r]} and \vrb{Q[j]}. In \key{rowspec} they align every cell of the row. + + \begin{codestore}[st=types:lcrj] + \begin{tblr}{ + colspec = {|l|c|r|}, + columns = {wd=2cm}, + } + Id & Ego & Superego \\ + Need & Demand & Desire + \end{tblr}\quad + \begin{tblr}{ + rowspec = {|c|r|}, + columns = {wd=2cm}, + } + Id & Ego & Superego \\ + Need & Demand & Desire + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:lcrj} + \end{center} + \begin{tsremark} + These are the same letters used as \key{halign} values (\S\ref{colrow:positioning}): \vrb{colspec={l}} and \vrb{columns={l}} both ultimately set \keyval{halign}{l}. + \end{tsremark} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021C + ]{X[ ... ]} + \begin{codesyntax} + \tsverb{X[}\tsmeta{keys}\tsverb{]} + \end{codesyntax} + \tsverb{X} is a stretchable column type defined as \vrb{{Q[co=1,...]}}: it expands to fill the available table width, sharing that width with other \tsverb{X} columns according to their \key{co} coefficients. Readers of the \pkg{tabularx} and \pkg{tabu} packages will recognise it. + + \begin{codestore}[st=types:x] + \begin{tblr}{ + colspec = {|l|X[c]|X[r]|}, + width = 10cm, + } + Natural & Stretched & Stretched + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:x} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021B + ]{width} + \begin{codesyntax} + \keyval{width}{\arg{dim}} + \end{codesyntax} + \key{width} sets the width of a table with stretchable columns. If it is unset, such a table is as wide as \tsobj[code, no index]{\linewidth}. It has no effect on a table without stretchable columns. + + \begin{codestore}[st=types:width] + \begin{tblr}{colspec = {|X|X|}, width = 6cm} + Hay & Water + \end{tblr} + + \begin{tblr}{colspec = {|X|X|}, width = 10cm} + Hay & Water + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:width} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + no index, + new=2021B, + update=2021F, + update=2021G + ]{h{...}, t{...}, m{...}, b{...}, f{...}} + \begin{codesyntax} + \tsverb{t}\{\tsmeta{dim}\} + \end{codesyntax} + These dimensioned types combine a \key{valign} value with a size in one letter. In \key{rowspec} the dimension sets the row height, so \vrb{t{5em}} is \vrb{{Q[t,ht=5em]}}; in \key{colspec} it sets the column width, so \vrb{t{5em}} is \vrb{{Q[t,wd=5em]}}. \vrb{p{...}} also exists, as an alias of \vrb{t{...}}. + + \begin{codestore}[st=types:dim] + \begin{tblr}{|t{15mm}|m{15mm}|b{20mm}|} + Real & Lack & {Surplus \\Enjoyment} + \end{tblr}\quad + \begin{tblr}{rowspec = {|t{10mm}|m{10mm}|b{10mm}|}} + Real & Lack & {Surplus \\Enjoyment} \\ + Void & Gap & {Sublime \\Object} \\ + Id & Ego & {Ticklish \\Subject} + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:dim} + \end{center} + \begin{tsremark} + New types are defined with \tsobj[code, no index]{\NewTblrColumnType}, \tsobj[code, no index]{\NewTblrRowType} and \tsobj[code, no index]{\NewTblrColumnRowType}. + \end{tsremark} +\end{codedescribe} + +\begin{codedescribe}[ + code, + no index, + new=2021B + ]{|, >, <, !, @, *} + These specifiers go between the types in \key{colspec} and \key{rowspec}. + \begin{describelist*}{values} + \describe{|}{Draws a rule. \vrb{|[dashed]} passes rule keys to it (\S\ref{inner:rules})} + \describe{>}{\vrb{>{...}} inserts material before the text of every cell in the next column or row, like \key{preto}. \vrb{>[1em]{...}} also sets its \key{leftsep} or \key{abovesep}} + \describe{<}{\vrb{<{...}} inserts material after the text of every cell in the previous column or row, like \key{appto}. \vrb{<[1em]{...}} also sets its \key{rightsep} or \key{belowsep}} + \describe{!}{\vrb{!{...}} replaces the rule with the given text} + \describe{@}{\vrb{@{...}} does the same as \vrb{!{...}}, and also removes the space on either side of it} + \describe{*}{\vrb{*{3}{c|}} repeats the given types 3 times} + \end{describelist*} + + \begin{codestore}[st=types:specifiers] + \begin{tblr}{ + colspec = {|*{2}{c|}>{(}r<{)}!{:}l@{ -- }l|} + } + Need & Demand & Desire & Lack & Drive + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:specifiers} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{si} + \begin{codesyntax} + \keyval{si}{\{\tsmeta{siunitx options}\}} + \end{codesyntax} + \key{si} passes keyword arguments through to \pkg{siunitx}'s number formatting (e.g.\ \vrb{si={table-format=2.3}}), which aligns the numbers in a column on their decimal markers. It is available after \tsobj[code, no index]{\UseTblrLibrary}\tsverb{{siunitx}} (\S\ref{lib:siunitx}) and applies to columns only. It underlies the \tsverb{S}/\tsverb{s} column types, which are themselves defined as \vrb{{Q[si={...},c]}} and \tsverb*[verb]{Q[si={...},c,cmd=\TblrUnit]} respectively. + + \begin{codestore}[st=types:si] + \begin{tblr}{hlines, column{1} = {c}} + 1.5 \\ 12.25 \\ 100 + \end{tblr}\quad + \begin{tblr}{ + hlines, + colspec = {Q[si={table-format=3.2},c]} + } + 1.5 \\ 12.25 \\ 100 + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{types:si} + \end{center} +\end{codedescribe} + +\section{Spanning Cells}\label{inner:spanning} +A spanning cell poses a problem that an ordinary cell does not: its size has to be reconciled with the columns and rows it covers. \pkg{tabularray} performs this reconciliation itself, and the keys of this section control how it shares out any surplus. A single interface for both directions also replaces the separate \tsobj[code, no index]{\multicolumn} and \tsobj[code, no index]{\multirow} of traditional tables, so documents that rely on those commands need converting. + +\begin{codedescribe}[ + code, + new=2021C, + update=2021L + ]{SetCell} + \begin{codesyntax} + \tsobj[code, no index]{\SetCell}[\oarg{span spec}]\{\arg{style spec}\} \tsmeta{cell text} + \end{codesyntax} + \tsobj[code, no index]{\SetCell} styles the cell it is placed in, and goes at the very start of the cell text. It accepts the keys listed in \S\ref{impatient:spanning}. + + \begin{codestore}[st=span:setcell] + \begin{tblr}{llll} + \hline + Real & \SetCell{bg=blue!70, fg=white} Symbolic & Void \\ + \hline + Desire & \SetCell{r, font=\scshape} Lack & Loop \\ + \hline + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{span:setcell} + \end{center} + \begin{tsremark} + \tsobj[code, no index]{\multicolumn} and \tsobj[code, no index]{\multirow} are not supported and raise an error. Old documents can be rolled back with \tsverb*{\usepackage{tabularray}[=v2021]}. + \end{tsremark} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021C, + update=2021D + ]{r, c (span spec)} + \begin{codesyntax} + \tsobj[code, no index]{\SetCell}[\keyval{r}{\arg{int}}, \keyval{c}{\arg{int}}]\{\arg{style spec}\} \tsmeta{cell text} + \end{codesyntax} + \key{r, c} set the number of rows and columns the cell spans. Their values are in the optional argument of \tsobj[code, no index]{\SetCell}, or the first pair of braces of \key{cell}. The cells a span covers stay in the source, and are left empty. + + \begin{codestore}[st=span:rc] + \begin{tblr}{hlines, vlines, cells = {c}} + Subject & \SetCell[c=2]{} Big Other & \\ + \SetCell[r=2]{} Desire & Real & Symbolic \\ + & Imaginary & Sinthome + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{span:rc} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + verb, + new=2026A + ]{out-of-bound span cropping} + A \key{r} or \key{c} span that would extend past the last row/column of the table is cropped to fit, with a warning identifying the offending cell and the value it was cropped to. Earlier releases stopped with errors such as ``Missing number, treated as zero'', which did not identify the cell. Below, \vrb{c=5} is cropped to \vrb{c=2}. + + \begin{codestore}[st=span:crop] + \begin{tblr}{ + hlines, vlines, + cell{1}{1} = {c=5}{c, bg=yellow!30}, + } + Kay Kavus & \\ + Eagles & Throne + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{span:crop} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021F, + update=2021L + ]{SetCells} + \begin{codesyntax} + \tsobj[code, no index]{\SetCells}[\oarg{span spec}]\{\arg{style spec}\} \tsmeta{cell text} + \end{codesyntax} + \tsobj[code, no index]{\SetCells} applies a style spec to every cell of the table at once, and may be placed at the start of any cell. + + \begin{codestore}[st=span:setcells] + \begin{tblr}{hlines, vlines} + \SetCells{c, bg=yellow!30} Real & Symbolic \\ + Imaginary & Sinthome + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{span:setcells} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021F, + update=2021L, + update=2025A + ]{cell, cells} + \begin{codesyntax} + \keysel{cell}{i}\{\tsmeta{j}\} \tsobj[code, no index]{=} \arg{span spec}\arg{style spec} + \keyval{cells}{\arg{span spec}\arg{style spec}} + \end{codesyntax} + \tsobj[keys, no index]{cell}\{\tsmeta{i}\}\{\tsmeta{j}\} and \key{cells} are the inner-spec equivalents of \tsobj[code, no index]{\SetCell} and \tsobj[code, no index]{\SetCells} respectively. \tsmeta{i} and \tsmeta{j} select rows and columns as described in \S\ref{inner:selectors}. A list of two-dimensional indexes selects individual cells, e.g.\ \vrb{cell{{1}{2},{3}{4}}}, and a range of such tuples selects diagonally, e.g.\ \vrb{cell{{1}{1}-{4}{4}}}. + + \begin{codestore}[st=span:cell] \begin{tblr}{ hlines, vlines, - columns = {8em} % `j' already implied by default - } - Asrâr-e azal râ na to dâni-o na man\\ - Win harf-e mu’amma na to khâni-o na man\\ - Hast az pas-e pare guftegu-ye man-o-to\\ - Chun parde baroftad na to mâni-o na man + cells = {c}, + cell{1}{odd} = {bg=yellow!30}, + cell{2}{2} = {r=2, c=2}{bg=blue!20}, + cell{{4}{1},{4}{4}} = {bg=green!30}, + } + 1 & 2 & 3 & 4 \\ + 1 & 2 & & 4 \\ + 1 & & & 4 \\ + 1 & 2 & 3 & 4 + \end{tblr}\quad + \begin{tblr}{ + hlines, vlines, + cell{{1}{1}-{4}{4}} = {bg=cyan!30}, + } + 1 & 2 & 3 & 4 \\ + 1 & 2 & 3 & 4 \\ + 1 & 2 & 3 & 4 \\ + 1 & 2 & 3 & 4 + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{span:cell} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021H + ]{hspan} + \begin{codesyntax} + \keyval{hspan}{default | even | minimal} + \end{codesyntax} + \key{hspan} sets how a wide spanning cell shares its width among the columns it covers. \val{default} and \val{even} compute the column widths from the span: \val{default} gives the extra width to the later columns, and \val{even} shares it out evenly. \val{minimal} computes the span from the column widths instead, so the text of the spanning cell wraps. + + \begin{codestore}[st=span:hspan] + \begin{tblr}{ + hlines, vlines, hspan=default, + cell{2}{1} = {c=2}{l}, + } + Alâ yâ & ayyohâ s-sâqi & ader ka’san va nâvel-hâ \\ + Ke ’eshq âsân nemud avval & & vali oftâd moshkel-hâ + \end{tblr} + + \begin{tblr}{ + hlines, vlines, hspan=even, + cell{2}{1} = {c=2}{l}, + } + Alâ yâ & ayyohâ s-sâqi & ader ka’san va nâvel-hâ \\ + Ke ’eshq âsân nemud avval & & vali oftâd moshkel-hâ + \end{tblr} + + \begin{tblr}{ + hlines, vlines, hspan=minimal, + cell{2}{1} = {c=2}{l}, + } + Alâ yâ & ayyohâ s-sâqi & ader ka’san va nâvel-hâ \\ + Ke ’eshq âsân nemud avval & & vali oftâd moshkel-hâ + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{span:hspan} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{vspan} + \begin{codesyntax} + \keyval{vspan}{default | even} + \end{codesyntax} + \key{vspan} sets how a tall spanning cell shares its height among the rows it covers. \val{default} gives the extra height to the last row of the span, and \val{even} shares it out evenly. + + \begin{codestore}[st=span:vspan] + \begin{tblr}{ + hlines, vlines, vspan=default, + column{2} = {3cm}, + cell{1}{2} = {r=3}{l}, + } + Hoopoe & Si morgh, thirty birds, set out to find the Simorgh + and find themselves \\ + Owl & \\ + Duck & \\ + \end{tblr}\quad + \begin{tblr}{ + hlines, vlines, vspan=even, + column{2} = {3cm}, + cell{1}{2} = {r=3}{l}, + } + Hoopoe & Si morgh, thirty birds, set out to find the Simorgh + and find themselves \\ + Owl & \\ + Duck & \\ + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{span:vspan} + \end{center} +\end{codedescribe} + +\section{Rules}\label{inner:rules} +Rules can be declared in the specification or placed in the table body, and the two serve different ends. Commands in the body follow the model of \env[no index]{tabular} and remain close to the rows they separate. Keys in the specification keep the design of the rules in one place, and a form such as \vrb{{hline{1,Z}}} continues to work as rows are added. + +\begin{codedescribe}[ + key, + new=2021F + ]{hlines, vlines} + \begin{codesyntax} + \key[no index]{hlines} + \keyval{hlines}{\{\tsmeta{style}\}} + \keyval{hlines}{\{\tsmeta{columns}\}\{\tsmeta{style}\}} + \keyval{hlines}{\{\tsmeta{index}\}\{\tsmeta{columns}\}\{\tsmeta{style}\}} + \end{codesyntax} + \key{hlines, vlines} draw every horizontal and vertical rule of the table. With no value, the rules are solid. A value in one pair of braces styles them. An extra pair before it selects which segments are drawn: columns for \key{hlines}, and rows for \key{vlines}. A third pair selects which rule to style when several are drawn in the same place, starting from \val{1}, and these must be used in order. + + \begin{codestore}[st=rules:hlines] + \begin{tblr}{hlines, vlines} + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{ + hlines = {1pt}, vlines = {red, dashed} + } + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{ + hlines = {2}{dashed}, + vlines = {1}{solid}, + } + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{ + hlines = {1}{-}{solid}, + hlines = {2}{-}{dashed}, + } + Real & Lack \\ + Void & Drive + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{rules:hlines} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021F + ]{hline, vline} + \begin{codesyntax} + \keysel{hline}{i}[\{\tsmeta{style}\}] + \keysel{vline}{j}[\{\tsmeta{style}\}] + \end{codesyntax} + \key{hline, vline} draw selected rules only, and take the same values as \key{hlines, vlines}. Rule \val{1} is above row 1 or left of column 1, and \vrb{Z} is the last rule, so \vrb{{hline{1,Z}}} draws the top and bottom rules of a table of any length. + + \begin{codestore}[st=rules:hline] + \begin{tblr}{ + hline{1,Z} = {1pt}, + hline{2,4} = {dashed}, + vline{2} = {2-3}{dotted}, + } + Answer & Meaning \\ + Yes & Perhaps \\ + Perhaps & No \\ + No & Not a diplomat \end{tblr}\end{codestore} \begin{center} - \tsdemo*[tblr]{columns:j} + \tsdemo*[tblr]{rules:hline} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021F, + update=2026A + ]{dash, wd, fgcolor, bgcolor} + \begin{codesyntax} + \keyval{dash}{solid | dashed | dotted} + \keyval{wd}{\arg{dim}} + \keyval{fgcolor}{\arg{colour}} + \keyval{bgcolor}{\arg{colour}} + \end{codesyntax} + These keys set the style of a rule: its dash pattern, its width (default: \val{0.4pt}), its colour, and the colour of the gaps in a dashed or dotted rule. \key{fg, bg} are shorter aliases for \key{fgcolor, bgcolor}. Values of \key{dash, wd, fgcolor} can be supplied without the key. + + \begin{codestore}[st=rules:style] + \begin{tblr}{ + hline{1} = {solid}, + hline{2} = {dashed}, + hline{3} = {dotted}, + hline{4} = {2pt, red}, + vline{2} = {2pt, dashed, fg=blue, bg=yellow}, + } + Real & Symbolic \\ + Imaginary & Sinthome \\ + Subject & Other + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{rules:style} \end{center} \begin{tsremark} - Observe the ugly justification of Khayyam's beautiful quatrain. + New dash patterns are defined with \tsobj[code, no index]{\NewTblrDashStyle}. \end{tsremark} \end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021F + ]{text} + \begin{codesyntax} + \keyval{text}{\arg{material}} + \end{codesyntax} + \key{text} replaces a rule with the given material, as the \vrb{!} specifier does in \key{colspec}. The material takes up width, unless it is wrapped in a command such as \tsobj[code, no index]{\clap}. + + \begin{codestore}[st=rules:text] + \begin{tblr}{ + hlines, vlines, + vline{2} = {1}{text=\clap{$\rightarrow$}}, + vline{2} = {2}{text=\clap{//}}, + } + Agent & Other \\ + Truth & Production + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{rules:text} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021N + ]{leftpos, rightpos, l, r, lr, endpos, abovepos, belowpos} + \begin{codesyntax} + \keyval{leftpos}{\arg{num}} + \keyval{rightpos}{\arg{num}} + \keyval{abovepos}{\arg{num}} + \keyval{belowpos}{\arg{num}} + \end{codesyntax} + These keys trim or extend the ends of a rule, and accept decimal numbers from \val{-1} to \val{1}. For \key{leftpos, rightpos} on an \key{hline}, \val{1} touches every crossing \key{vline} (the default), \val{0} touches the first one only, and \val{-1} is trimmed by \key{colsep}. \key{abovepos, belowpos} on a \key{vline} work the same way against crossing rules and \key{rowsep}, but default to \val{0}. + + \key{l, r} are short forms of \key{leftpos, rightpos}, and \key{lr} sets both at once. All 3 default to \val{-0.8} when given no value. \key{endpos} applies \key{leftpos, rightpos} only to the two ends of the table. + + \begin{codestore}[st=rules:pos] + \begin{tblr}{ + hline{1,4} = {1pt}, + hline{2} = {leftpos=-1, rightpos=-1}, + hline{3} = {leftpos=-1, rightpos=-1, endpos}, + vline{1,4} = {abovepos=1, belowpos=1}, + } + The Moving & Finger & writes \\ + Nor Piety & nor & Wit \\ + To cancel & half & a Line + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{rules:pos} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021K + ]{rulesep} + \begin{codesyntax} + \keyval{rulesep}{\arg{dim}} + \end{codesyntax} + \key{rulesep} sets the space between two rules drawn in the same place (default: \val{2pt}). It replaces \LaTeX's \tsobj[code, no index]{\doublerulesep}. + + \begin{codestore}[st=rules:rulesep] + \begin{tblr}{colspec = {||ll||}, rowspec = {|QQ|}} + Minimal & Difference \\ + Parallax & Gap + \end{tblr}\quad + \begin{tblr}{ + colspec = {||ll||}, rowspec = {|QQ|}, + rulesep = 4pt, + } + Minimal & Difference \\ + Parallax & Gap + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{rules:rulesep} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021A, + update=2021D, + update=2021E, + update=2021F + ]{hline, cline, SetHline, SetHlines, vline, rline, SetVline, SetVlines} + \begin{codesyntax} + \tsobj[code, no index]{\hline}[\oarg{style}] + \tsobj[code, no index]{\cline}[\oarg{style}]\{\tsmeta{columns}\} + \tsobj[code, no index]{\SetHline}[\oarg{index}]\{\tsmeta{columns}\}\{\tsmeta{style}\} + \tsobj[code, no index]{\SetHlines}[\oarg{index}]\{\tsmeta{columns}\}\{\tsmeta{style}\} + \end{codesyntax} + These commands draw rules from inside the table body. \tsobj[code, no index]{\hline, \cline} go between rows, and accept the style keys above in their optional argument. \tsobj[code, no index]{\SetHline} at the start of row \tsmeta{i} is the same as \keysel{hline}{i}[\{\tsmeta{index}\}\{\tsmeta{columns}\}\{\tsmeta{style}\}], and \tsobj[code, no index]{\SetHlines} is the same as \key{hlines}. \tsobj[code, no index]{\vline, \rline, \SetVline, \SetVlines} are the vertical equivalents. + + \begin{codestore}[st=rules:commands] + \begin{tblr}{llll} + \hline + Master & University & Hysteric & Analyst \\ + \hline[dashed] + Agent & Other & Truth & Production \\ + \cline[dotted]{2-3} + Real & Symbolic & Imaginary & Sinthome \\ + \SetHline{1,4}{2pt, blue} + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{rules:commands} + \end{center} +\end{codedescribe} + +\section{Borders}\label{inner:borders} +A rule and a border are distinct concepts. A rule is a line drawn in a table, while a border is the position it occupies, together with the space on either side. The distinction allows the spacing between rows or columns to be adjusted whether or not any rule is present, and it gives properties of that position, such as a page break, a natural place in the interface. + +\begin{codedescribe}[ + key, + new=2022A + ]{hborder, vborder} + \begin{codesyntax} + \keysel{hborder}{i}[\{\tsmeta{keys}\}] + \keysel{vborder}{j}[\{\tsmeta{keys}\}] + \end{codesyntax} + \key{hborder, vborder} hold specifications for a border as a whole, rather than one rule in it. Border \val{1} is above row 1 or left of column 1. The same keys are available from inside the table body as \tsobj[code, no index]{\hborder} and \tsobj[code, no index]{\vborder}, at the start of the row or column that follows the border. +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2022A + ]{abovespace, abovespace+, belowspace, belowspace+, leftspace, leftspace+, rightspace, rightspace+} + \begin{codesyntax} + \keyval{abovespace}{\arg{dim}} + \keyval{leftspace}{\arg{dim}} + \end{codesyntax} + These keys set the space either side of a border. On \key{hborder}, \key{abovespace} sets the \key{belowsep} of the row before the border and \key{belowspace} sets the \key{abovesep} of the row after it. On \key{vborder}, \key{leftspace} sets the \key{rightsep} of the column before the border and \key{rightspace} sets the \key{leftsep} of the column after it. The \key[no index]{+} variants add to the current value. + + \begin{codestore}[st=borders:space] + \begin{tblr}{hlines, vlines} + Beshno in ney & Chon shekâyat mikonad \\ + Az jodâyi-hâ & Hekâyat mikonad + \end{tblr} + + \begin{tblr}{ + hlines, vlines, + hborder{2} = {abovespace=8pt}, + vborder{2} = {rightspace+=1em}, + } + Beshno in ney & Chon shekâyat mikonad \\ + Az jodâyi-hâ & Hekâyat mikonad + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{borders:space} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2022A + ]{pagebreak} + \begin{codesyntax} + \keyval{pagebreak}{yes | no | auto} + \end{codesyntax} + \key{pagebreak} controls a page break at an \key{hborder} of a long table (default: \val{auto}), with \val{yes} assumed when no value is given. The example for \key{rowhead} in \S\ref{inner:table} forces one with \key{pagebreak}. +\end{codedescribe} + +\section{Table-wide Options}\label{inner:table} +Not every property of a table can be attributed to a column or row. The options in this section act on the table as a whole, and they reward a little caution accordingly, since one key such as \key[no index]{stretch} alters every row at once. + +\begin{codedescribe}[ + key, + new=2021G + ]{stretch} + \begin{codesyntax} + \keyval{stretch}{\arg{num}} + \end{codesyntax} + \key{stretch} scales the strut added to every cell, which sets the least height a row can have (default: \val{1}). It replaces \LaTeX's \tsobj[code, no index]{\arraystretch}. With \val{0} there is no strut, so an exact row height can be set with \key{ht} to centre numbers vertically. + + \begin{codestore}[st=table:stretch] + \begin{tblr}{hlines} + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{hlines, stretch=1.5} + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{hlines, stretch=0} + Real & Lack \\ + Void & Drive + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{table:stretch} + \end{center} + \begin{tsremark} + A negative value such as \vrb{stretch=-1} removes struts as well, and also removes the extra space above and below lists in cells (\issue{99}). Tables with \vrb{rowsep=0pt} may not work well with it. + \end{tsremark} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021G, + update=2022A + ]{baseline} + \begin{codesyntax} + \keyval{baseline}{t | T | m | M | b | B | \arg{int}} + \end{codesyntax} + \key{baseline} sets which part of the table lines up with the surrounding text (default: \val{m}). + \begin{describelist*}{values} + \describe{t, b}{The top or bottom edge of the table} + \describe{T, B}{The first or last row} + \describe{m}{The vertical middle of the table} + \describe{M}{The middle row, or the middle border if the row count is even} + \describe{\tsmeta{int}}{Row \tsmeta{int}} + \end{describelist*} + + \begin{codestore}[st=table:baseline] + Base\begin{tblr}{hlines, baseline=t} + Law \\ Religion \\ Ideology + \end{tblr}Base\begin{tblr}{hlines, baseline=T} + Law \\ Religion \\ Ideology + \end{tblr}Base\begin{tblr}{hlines, baseline=B} + Law \\ Religion \\ Ideology + \end{tblr}Base\begin{tblr}{hlines, baseline=2} + Law \\ Religion \\ Ideology + \end{tblr}Base\end{codestore} + \begin{center} + \tsdemo*[tblr]{table:baseline} + \end{center} + \begin{tsremark} + \key{baseline} is also accepted as a bare key in \key{row} and \key{hborder}, to align on that row or border: \vrb{row{3} = {baseline}}. It is an outer key too (\S\ref{outer:placement}). + \end{tsremark} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2022D + ]{delimiter} + \begin{codesyntax} + \keyval{delimiter}{{\{left = \tsmeta{delimiter}, right = \tsmeta{delimiter}\}}} + \end{codesyntax} + \key{delimiter} wraps the whole table in a pair of stretching delimiters, as \tsobj[code, no index]{\left} and \tsobj[code, no index]{\right} do. A full stop leaves that side empty. + + \begin{codestore}[st=table:delimiter] + \begin{tblr}{delimiter = {left = (, right = )}} + Real & Lack \\ + Void & Drive + \end{tblr}\quad + \begin{tblr}{delimiter = {left = \lbrace, right = .}} + Real & Lack \\ + Void & Drive + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{table:delimiter} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2025A + ]{name} + \begin{codesyntax} + \keyval{name}{\arg{text}} + \end{codesyntax} + \key{name} gives the table a name, and has no visible effect of its own. The \pkg{tikz} library uses it to prefix its node names with \vrb{tblr}\tsmeta{name}\vrb{-}, so that drawings can address the nodes of a particular table (\S\ref{lib:tikz}). +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{rowhead, rowfoot} + \begin{codesyntax} + \keyval{rowhead}{\arg{int}} + \keyval{rowfoot}{\arg{int}} + \end{codesyntax} + \key{rowhead} and \key{rowfoot} set how many of the first and last rows of a long table repeat on every page (default: \val{0}). They have no effect on a table that fits on one page. The table below breaks at the page boundary forced by \key{pagebreak}, and its first and last rows appear on both pages. +\end{codedescribe} + +\begin{codestore}[st=table:rowhead] + \begin{longtblr}[ + caption = {Rows repeated across a page break}, + ]{ + hlines, vlines, + colspec = {X[l]X[l]}, width = 10cm, + rowhead = 1, rowfoot = 1, + row{1} = {font=\bfseries}, + row{Z} = {font=\itshape}, + hborder{3} = {pagebreak}, + } + All great facts & Appear twice \\ + The first time & As tragedy \\ + The second time & As farce \\ + Zeno & My last cigarette + \end{longtblr}\end{codestore} +\tscode*[tblr]{table:rowhead} +\tsexec{table:rowhead} diff --git a/doc/03-outer.tex b/doc/03-outer.tex new file mode 100644 index 0000000..ebe2a27 --- /dev/null +++ b/doc/03-outer.tex @@ -0,0 +1,369 @@ +\chapter{Specifications of the Outer Components with Examples} +This chapter examines the \vrb{outer} specification, introduced briefly in \S\ref{impatient:concept}, which covers the elements of typesetting that belong to the environment in which a table is placed. It is supplied within the \oarg{outer spec} as an optional argument, also in a key--value format. + +The effect of these keys depends heavily on the type of table. Most of them build the head and foot around a table, such as its caption and notes, yet a \env{tblr} has no head or foot, so they only change the output of a \env{talltblr} or a \env{longtblr}. It follows that the outer specification is best approached as a question of what a table has to do in a document, and only then of how it should look. We show applied examples of each key below. + +\section{Table Types}\label{outer:types} +The 3 environments represent different commitments. A \env{tblr} behaves like any other box in the text, at the price of having no head or foot. A \env{talltblr} adds these and remains a box, so it still cannot break across pages. A \env{longtblr} gives up the box in order to do so. + +\begin{codedescribe}[ + key, + new=2021J, + update=2021M +]{long, tall} +\begin{codesyntax} +\tsobj[code, no index]{\begin{tblr}}[\key[no index]{long}]\{\arg{inner spec}\} +\tsobj[code, no index]{\begin{tblr}}[\key[no index]{tall}]\{\arg{inner spec}\} +\end{codesyntax} +\key{long} and \key{tall} change a \env{tblr} into a long or tall table, which is the same as writing \env{longtblr} or \env{talltblr}. In the example below, the first table has no head, so its caption does not appear. + +\begin{codestore}[st=outer:tall] + \begin{tblr}[caption = {Can you pass the salt?}]{hlines} + Of course & I can + \end{tblr}\quad + \begin{tblr}[ + tall, caption = {Can you pass the salt?}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 8cm, + } + Of course & I can + \end{tblr}\end{codestore} +\begin{center} + \tsdemo*[tblr]{outer:tall} +\end{center} +\end{codedescribe} + +\section{Placement}\label{outer:placement} +Placement raises 2 separate questions, and the table type determines which of them applies. A long table occupies its own lines, so the question is where it falls across the page. Other tables share a line with the surrounding text, so the question becomes how they align with it. + +\begin{codedescribe}[ + key, + new=2021L + ]{halign, l, c, r} + \begin{codesyntax} + \keyval{halign}{l | c | r} + \end{codesyntax} + \key{halign} sets the horizontal position of a long table on the page (default: \val{c}). The key name can be left out, so \vrb{[r]} is the same as \vrb{[halign=r]}. It has no effect on a \env{tblr} or a \env{talltblr}, which are placed in the text like any other box. +\end{codedescribe} + +\begin{codestore}[st=outer:halign] + \begin{longtblr}[ + l, caption = {France, on the left}, + ]{hlines, colspec = {X[c]}, width = 6cm} + Revolutionary hastiness + \end{longtblr} + \begin{longtblr}[ + caption = {England, by default}, + ]{hlines, colspec = {X[c]}, width = 6cm} + Utilitarian pragmatism + \end{longtblr} + \begin{longtblr}[ + r, caption = {Germany, on the right}, + ]{hlines, colspec = {X[c]}, width = 6cm} + Reflective thoroughness + \end{longtblr}\end{codestore} +\tscode*[tblr]{outer:halign} +\tsexec{outer:halign} + +\begin{codedescribe}[ + key, + new=2021G, + update=2022A + ]{baseline, t, T, m, M, b, B} + \begin{codesyntax} + \keyval{baseline}{t | T | m | M | b | B | \arg{int}} + \end{codesyntax} + \key{baseline} sets which part of the table lines up with the surrounding text, with the values described in \S\ref{inner:table}. It works as an inner key too, but only as an outer key can its name be left out. + + \begin{codestore}[st=outer:baseline] + Base\begin{tblr}[t]{hlines} + Real \\ Symbolic \\ Imaginary + \end{tblr}Base\begin{tblr}[m]{hlines} + Real \\ Symbolic \\ Imaginary + \end{tblr}Base\begin{tblr}[B]{hlines} + Real \\ Symbolic \\ Imaginary + \end{tblr}Base\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:baseline} + \end{center} + \begin{tsremark} + The outer key \key[no index]{valign} is an obsolete alias of \key{baseline}. + \end{tsremark} +\end{codedescribe} + +\section{Captions and Labels}\label{outer:captions} +A caption serves several purposes at once: it explains the table on the page, supplies the entry in a List of Tables, and gives a cross-reference something to point to. These purposes can pull against one another, as wording that suits the page may be too long for a list. \pkg{tabularray} therefore separates them into distinct keys, each of which can be set or withheld independently. + +\begin{codedescribe}[ + key, + new=2021L + ]{caption} + \begin{codesyntax} + \keyval{caption}{\arg{text}} + \end{codesyntax} + \key{caption} sets the text of the caption above the table. A \env{talltblr} wraps its caption to the width of the table. + + \begin{codestore}[st=outer:caption] + \begin{talltblr}[ + caption = {A caption, wrapped to the width of this narrow table}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 5cm, + } + Real & Symbolic + \end{talltblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:caption} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{label} + \begin{codesyntax} + \keyval{label}{\arg{name} | none} + \end{codesyntax} + \key{label} sets a label for cross-referencing the table with \tsobj[code, no index]{\ref}. With \val{none}, the table is left unnumbered: the \vrb{table} counter does not step, and the tag and separator before the caption text are dropped. + + \begin{codestore}[st=outer:label] + \begin{talltblr}[ + caption = {Coffee without cream}, + label = {outer:labelled}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 6cm, + } + Plain & Coffee + \end{talltblr}\quad + \begin{talltblr}[ + caption = {Coffee without milk}, + label = none, + ]{ + hlines, colspec = {X[c]X[c]}, width = 6cm, + } + Plain & Coffee + \end{talltblr} + + See Table~\ref{outer:labelled}.\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:label} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{entry} + \begin{codesyntax} + \keyval{entry}{\arg{text} | none} + \end{codesyntax} + \key{entry} sets a short caption for the List of Tables, and leaves the caption above the table as it is. With \val{none}, the table is left out of the list. \vrb{{caption=text, entry=none}} is similar to \tsverb*{\caption[]{text}}, and \vrb{{caption=text, entry=none, label=none}} to \tsverb*{\caption*{text}}. + + \begin{codestore}[st=outer:entry] + \begin{talltblr}[ + caption = {The long caption, which is typeset above the table}, + entry = {The short caption, for the List of Tables}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 10cm, + } + Real & Symbolic + \end{talltblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:entry} + \end{center} +\end{codedescribe} + +\section{Notes and Remarks}\label{outer:notes} +Commentary on a table is often too long for its cells, and moving it into the surrounding text separates it from the data it qualifies. Notes and remarks offer a middle course by placing such text in the foot of the table. The difference between them is one of scope. + +\begin{codedescribe}[ + key, + new=2021L + ]{note, remark} + \begin{codesyntax} + \keysel{note}{tag}[\arg{text}] + \keysel{remark}{tag}[\arg{text}] + \end{codesyntax} + \key{note, remark} add text below the table. A note is tied to a place in the table by \tsobj[code, no index]{\TblrNote}\{\tsmeta{tag}\} in a cell, and a remark applies to the table as a whole. The foot lists every note first, then every remark, each with its \tsmeta{tag}. + + \begin{codestore}[st=outer:note] + \begin{talltblr}[ + caption = {The family of Rostam}, + note{a} = {Raised by the Simorgh.}, + note{b} = {A horse.}, + remark{Note} = {Not a happy family.}, + remark{Source} = {Ferdowsi, \emph{Shahnameh}.}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 8cm, + } + Zal\TblrNote{a} & Rostam \\ + Sohrab & Rakhsh\TblrNote{b} + \end{talltblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:note} + \end{center} + \begin{tsremark} + \tsobj[code, no index]{\TblrNote} sets its tag with \tsobj[code, no index]{\TblrOverlap}, an alias of \tsobj[code, no index]{\rlap}, so that the tag takes up no width. A tag can then run into a neighbouring cell. To make tags take up width, redefine \tsobj[code, no index]{\TblrOverlap} to typeset its argument as it is (\issue{198}). + \end{tsremark} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{more} + \begin{codesyntax} + \keysel{more}{name}[\arg{text}] + \end{codesyntax} + \key{more} stores extra text under \tsmeta{name} for a template to pick up with \tsobj[code, no index]{\InsertTblrMore}\{\tsmeta{name}\}. It has no effect on the output until a template does so, as the theme below does. + + \begin{codestore}[st=outer:more] + \NewTblrTheme{checked}{ + \DeclareTblrTemplate{lastfoot}{default}{ + Last checked: \InsertTblrMore{checked} + } + } + \begin{talltblr}[ + theme = checked, + more{checked} = {October 2026}, + caption = {A table with extra text in its foot}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 8cm, + } + Real & Symbolic + \end{talltblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:more} + \end{center} +\end{codedescribe} + +\section{Spacing}\label{outer:spacing} +A table with a head or foot involves 2 kinds of vertical space, which serve contrary ends. The space inside the table binds the caption and notes to the body, while the space outside sets the table apart from the text. Separate keys allow each to be tuned without disturbing the other. + +\begin{codedescribe}[ + key, + new=2021L + ]{headsep, footsep} + \begin{codesyntax} + \keyval{headsep}{\arg{dim}} + \keyval{footsep}{\arg{dim}} + \end{codesyntax} + \key{headsep} and \key{footsep} set the vertical space between the table body and its head and foot (default: \val{6pt} each). + + \begin{codestore}[st=outer:headsep] + \begin{talltblr}[ + caption = {The default spacing}, + note{a} = {Impossible.}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 6cm, + } + Real\TblrNote{a} & Symbolic + \end{talltblr}\quad + \begin{talltblr}[ + caption = {A wider spacing}, + note{a} = {Impossible.}, + headsep = 18pt, footsep = 18pt, + ]{ + hlines, colspec = {X[c]X[c]}, width = 6cm, + } + Real\TblrNote{a} & Symbolic + \end{talltblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:headsep} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2021L + ]{presep, postsep} + \begin{codesyntax} + \keyval{presep}{\arg{dim}} + \keyval{postsep}{\arg{dim}} + \end{codesyntax} + \key{presep} and \key{postsep} set the vertical space between a long table and the text above and below it (default: \tsobj[code, no index]{1.5\bigskipamount} each). They only apply to a long table. +\end{codedescribe} + +\begin{codestore}[st=outer:presep] + Text above the table. + \begin{longtblr}[ + presep = 2pt, + postsep = 3cm, + caption = {Close to the text above}, + ]{hlines, colspec = {X[c]X[c]}, width = 8cm} + Real & Symbolic + \end{longtblr} + Text below the table.\end{codestore} +\tscode*[tblr]{outer:presep} +\tsexec{outer:presep} + +\section{Themes}\label{outer:themes} +Repeating the same settings across tables invites inconsistency, and a theme addresses this by defining a design once and applying it by name. This gives a document a single point of revision. It also adds a layer of indirection, since the appearance of a table can no longer be read from its own specification. + +\begin{codedescribe}[ + key, + new=2021L + ]{theme} + \begin{codesyntax} + \keyval{theme}{\arg{name}} + \end{codesyntax} + \key{theme} applies a set of template and style settings defined with \tsobj[code, no index]{\NewTblrTheme}, so that tables can share one look. The settings only reach the table that names the theme. + + \begin{codestore}[st=outer:theme] + \NewTblrTheme{fancy}{ + \SetTblrStyle{caption-tag}{fg=red, font=\bfseries} + \SetTblrStyle{note}{fg=blue} + } + \begin{talltblr}[ + theme = fancy, + caption = {A table with a theme}, + note{a} = {Impossible.}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 6cm, + } + Real\TblrNote{a} & Symbolic + \end{talltblr}\quad + \begin{talltblr}[ + caption = {A table without one}, + note{a} = {Impossible.}, + ]{ + hlines, colspec = {X[c]X[c]}, width = 6cm, + } + Real\TblrNote{a} & Symbolic + \end{talltblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:theme} + \end{center} +\end{codedescribe} + +\section{Expanding Macros}\label{outer:expand} +Macros are the ordinary means of reuse in \LaTeX{}, yet the way \pkg{tabularray} reads a table limits their use in the table body. The package divides the body into cells before it typesets anything, so a separator inside a macro goes undetected. This keeps every cell addressable by the specification, but it obliges the author to name the macros that should be opened first. + +\begin{codedescribe}[ + key, + new=2021M, + update=2024A + ]{expand, expand+} + \begin{codesyntax} + \keyval{expand}{\tsmeta{macros}} + \keyval{expand+}{\tsmeta{macros}} + \end{codesyntax} + Unlike \LaTeX's \env*[no index]{tabular}, \pkg{tabularray} needs to see every \tsverb{&} and \tsverb{\\} when it splits the table body, so it cannot find them inside a macro. \key{expand} makes it expand every occurrence of the given macros once, in the given order, before splitting the body. \key{expand+} adds to the current list of macros rather than replacing it. + + \begin{codestore}[st=outer:expand] + \newcommand*\tblrrowa{20 & 30 & 40 \\} + \newcommand*\tblrrowb{50 & 60 & 70 \\} + \begin{tblr}[ + expand = \tblrrowa, + expand+ = \tblrrowb, + ]{hlines, colspec = {ccc}} + Id & Ego & Superego \\ + \tblrrowa + \tblrrowb + Need & Demand & Desire + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{outer:expand} + \end{center} + \begin{tsremark} + Commands defined with \tsobj[code, no index]{\NewDocumentCommand} cannot be expanded this way. Commands with optional arguments can be defined with \tsobj[code, no index]{\NewExpandableDocumentCommand} and expanded fully with \tsverb**{expand=\expanded}, protecting any fragile commands inside them with \tsobj[code, no index]{\unexpanded}. + \end{tsremark} +\end{codedescribe} diff --git a/doc/04-libraries.tex b/doc/04-libraries.tex new file mode 100644 index 0000000..bcc608f --- /dev/null +++ b/doc/04-libraries.tex @@ -0,0 +1,960 @@ +\chapter{Libraries with Examples}\label{lib} +This chapter examines the libraries that extend \pkg{tabularray} beyond its core. Some act as a bridge to another package, such as \pkg{booktabs} or \pkg{siunitx}, whereas others change the way tables are typeset. None of them is loaded by default, for a practical reason: each one adds a dependency or a compilation cost, and several of them affect every table in the document rather than the tables that use their commands. A library is therefore best treated as a considered trade-off, not as a free addition. + +In this chapter, we introduce the libraries in alphabetical order. Each section compares the output of a library with the plain equivalent, provided that one exists, so that the change it makes can be seen directly. + +\section{Loading a Library}\label{lib:loading} +Leaving libraries to be requested limits the dependencies of the core, and places the decision with the author, who names each one in the preamble. The same mechanism extends to libraries outside the package, which lets others build on \pkg{tabularray} without changing it. + +\begin{codedescribe}[ + code, + new=2021L, + update=2024A, + update=2025A + ]{UseTblrLibrary} + \begin{codesyntax} + \tsobj[code, no index]{\UseTblrLibrary}\{\arg{library list}\} + \end{codesyntax} + \tsobj[code, no index]{\UseTblrLibrary} loads one or more libraries, given as a comma-separated list, and belongs in the preamble. A library can be named more than once, but its code runs only on the first occasion. Any name outside the list below is taken as an external library, so that \tsverb*{\UseTblrLibrary{foo}} loads the file \vrb{tblrlibfoo.sty}. + + \begin{codestore}[st=lib:use] + \usepackage{tabularray} + \UseTblrLibrary{booktabs, siunitx}\end{codestore} + \tscode*[tblr]{lib:use} + \begin{tsremark} + A package can define a library of its own with \tsobj[code]{\NewTblrLibrary}\{\arg{name}\}\{\arg{code}\}, which keeps \tsmeta{code} in reserve until the first \tsobj[code, no index]{\UseTblrLibrary} of that name. + \end{tsremark} +\end{codedescribe} + +\begin{center} + \begin{tblr}{ + colspec = {Q[l, font=\ttfamily] X[l] Q[l]}, + width = \linewidth, + cell{1}{1} = {font=\rmfamily\bfseries}, + row{1} = {font=\bfseries}, + hline{1,2,Z} = {solid}, + rowsep = 1pt, + } + Library & Provides & Also loads \\ + amsmath & Math environments built on \env[no index]{tblr} & \pkg{amsmath} \\ + booktabs & Rule commands and environments in the style of \pkg{booktabs} & \pkg{booktabs}, \pkg{etoolbox} \\ + counter & \LaTeX{} counters that can be stepped inside cells & --- \\ + diagbox & Cells divided by diagonal lines & \pkg{diagbox} \\ + functional & Functions in specifications, and the keys \key[no index]{evaluate, process} & \pkg{functional} \\ + hook & Hooks into the building of a table (experimental) & \pkg{varwidth} library \\ + html & Variables that describe the borders of a cell (experimental) & --- \\ + nameref & \tsobj[code, no index]{\nameref} for captioned tables & \pkg{nameref} \\ + siunitx & Column types \tsverb{S}, \tsverb{s} and the keys \key[no index]{si, guard} & \pkg{siunitx} \\ + tikz & Drawing below or above tables (experimental) & \pkg{tikz}, \pkg{hook} library \\ + varwidth & The key \key[no index]{measure}, for vertical material in cells & \pkg{varwidth} \\ + zref & \tsobj[code, no index]{\zref} for captioned tables & \pkg{zref-user} + \end{tblr} +\end{center} + +Most libraries add commands or environments, and have no effect until those are used. The exceptions act on every table as soon as they are loaded: \pkg{counter} restores counters after measuring, \pkg{functional} evaluates every inner specification before parsing it, \pkg{html} computes extra variables for each cell, and \pkg{varwidth} changes the default value of \key[no index]{measure}. \pkg{hook} and \pkg{tikz} change that default again. + +\section{Library \texttt{amsmath}}\label{lib:amsmath} +This library loads \pkg{amsmath} and defines versions of the array, matrix and cases environments that are built on \env{tblr}. Each new environment has the name of its counterpart with a \vrb{+} in front, and is used in math mode. This gives mathematics access to the full inner specification, along with rows that accommodate tall entries. Each of these environments is a complete table, however, and takes considerably longer to compile than its counterpart, so the original remains preferable when neither benefit is needed. + +\begin{codedescribe}[ + env, + new=2021P +]{+array, +matrix, +bmatrix, +Bmatrix, +pmatrix, +vmatrix, +Vmatrix, +cases} +\begin{codesyntax} +\tsobj[code, no index]{\begin{+array}}[\oarg{outer spec}]\{\arg{inner spec}\} +\tsobj[code, no index]{\begin{+pmatrix}}[\oarg{inner spec}] +\end{codesyntax} +\env{+array} takes outer and inner specifications, as \env{tblr} does, whereas the others take an inner specification as an optional argument. That argument is applied after the defaults of the environment, so it can override them. + +The first matrix below is the \pkg{amsmath} original. The second has taller rows, as it keeps the \val{2pt} \key[no index]{rowsep} of a \env{tblr}, and the third uses the optional argument to style its cells. + +\begin{codestore}[st=lib:amsmath:pmatrix] +$\begin{pmatrix} + \dfrac{2}{3} & -\dfrac{1}{3} \\ + \dfrac{1}{3} & \dfrac{2}{3} + \end{pmatrix}\quad + \begin{+pmatrix} + \dfrac{2}{3} & -\dfrac{1}{3} \\ + \dfrac{1}{3} & \dfrac{2}{3} + \end{+pmatrix}\quad + \begin{+pmatrix}[cells = {r}, row{2} = {bg=yellow!30}] + \dfrac{2}{3} & -\dfrac{1}{3} \\ + \dfrac{1}{3} & \dfrac{2}{3} + \end{+pmatrix}$\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:amsmath:pmatrix} +\end{center} + +The matrix environments differ only in their delimiters. Each one centres its cells and removes the space outside the first and last columns. + +\begin{codestore}[st=lib:amsmath:matrix] +$\begin{+matrix} a & b \\ c & d \end{+matrix}\quad + \begin{+bmatrix} a & b \\ c & d \end{+bmatrix}\quad + \begin{+Bmatrix} a & b \\ c & d \end{+Bmatrix}\quad + \begin{+pmatrix} a & b \\ c & d \end{+pmatrix}\quad + \begin{+vmatrix} a & b \\ c & d \end{+vmatrix}\quad + \begin{+Vmatrix} a & b \\ c & d \end{+Vmatrix}$\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:amsmath:matrix} +\end{center} + +\env{+cases} sets 2 left-aligned columns, a brace on the left, and \vrb{stretch=1.2}, which gives fractions more room than the original on the left. + +\begin{codestore}[st=lib:amsmath:cases] +$f(x) = \begin{cases} + 0, & x = 1 \\ + \dfrac{1}{3}, & x = 2 + \end{cases}\quad + f(x) = \begin{+cases} + 0, & x = 1 \\ + \dfrac{1}{3}, & x = 2 + \end{+cases}$\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:amsmath:cases} +\end{center} + +\env{+array} accepts any inner key, and defaults to a \key[no index]{colsep} of \val{5pt}, the same as the \env{array} environment of \LaTeX. + +\begin{codestore}[st=lib:amsmath:array] +$\begin{+array}{ + colspec = {cc}, hline{2} = {solid}, vline{2} = {solid} + } + x & x^2 \\ + 2 & 4 \\ + 3 & 9 + \end{+array}$\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:amsmath:array} +\end{center} +\begin{tsremark} + The matrix environments and \env{+cases} are built on \env{+array}, so that \tsverb*{\SetTblrInner[+array]{rowsep=0pt}} changes the defaults of all of them at once. +\end{tsremark} +\end{codedescribe} + +\section{Library \texttt{booktabs}}\label{lib:booktabs} +The \pkg{booktabs} package embodies a particular view of table design, in which rules of different weights and generous vertical space take the place of a full grid. This library loads the package for its dimensions and defines its commands as table commands. These commands work in any \pkg{tabularray} table, but only the environments of this library add the space around the rules, so a \env{tblr} adopts the weights of \pkg{booktabs} without its spacing. + +\begin{codedescribe}[ + code, + new=2021L + ]{toprule, midrule, bottomrule} + \begin{codesyntax} + \tsobj[code, no index]{\toprule}[\oarg{rule spec}] + \tsobj[code, no index]{\midrule}[\oarg{rule spec}] + \tsobj[code, no index]{\bottomrule}[\oarg{rule spec}] + \end{codesyntax} + These commands draw a rule across the table, and go in the same place as \tsobj[code, no index]{\hline}. \tsobj[code, no index]{\toprule} and \tsobj[code, no index]{\bottomrule} take their width from \tsobj[code]{\heavyrulewidth} (default: \val{.08em}), and \tsobj[code, no index]{\midrule} from \tsobj[code]{\lightrulewidth} (default: \val{.05em}). The optional argument accepts the keys of \tsobj[code, no index]{\hline}, described in \S\ref{inner:rules}, and overrides these widths. + + \begin{codestore}[st=lib:booktabs:rules] + \begin{tblr}{lll} + \toprule + Poet & City & Work \\ + \midrule + Ferdowsi & Tus & Shahnameh \\ + \bottomrule + \end{tblr}\quad + \begin{tblr}{lll} + \toprule[2pt, red] + Poet & City & Work \\ + \midrule[blue] + Ferdowsi & Tus & Shahnameh \\ + \bottomrule[2pt, red] + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:booktabs:rules} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021L, + update=2021N + ]{cmidrule} + \begin{codesyntax} + \tsobj[code, no index]{\cmidrule}[\oarg{rule spec}]\{\arg{columns}\} + \end{codesyntax} + \tsobj[code, no index]{\cmidrule} draws a rule across the selected columns, with its width taken from \tsobj[code]{\cmidrulewidth} (default: \val{.03em}). It applies \key[no index]{endpos} by default, so the trim keys \key[no index]{l, r, lr} of \S\ref{inner:rules} act on the ends of the rule and not on the crossings between. The default trim of \val{-0.8} is chosen to resemble the output of \pkg{booktabs}, and a value between \val{-1} and \val{0} suits a table with no vertical rules. + + \begin{codestore}[st=lib:booktabs:cmidrule] + \begin{tblr}{llll} + \toprule + Poet & City & Work & Form \\ + \cmidrule{1-2} \cmidrule{3-4} + Ferdowsi & Tus & Shahnameh & Epic \\ + \cmidrule[lr]{1-2} \cmidrule[lr=-0.4]{3-4} + Rumi & Konya & Masnavi & Couplets \\ + \cmidrule[r]{1-2} \cmidrule[l]{3-4} + Hafez & Shiraz & Divan & Ghazals \\ + \bottomrule + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:booktabs:cmidrule} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021N + ]{cmidrulemore, morecmidrules} + \begin{codesyntax} + \tsobj[code, no index]{\cmidrulemore}[\oarg{rule spec}]\{\arg{columns}\} + \tsobj[code, no index]{\morecmidrules} \tsobj[code, no index]{\cmidrule}[\oarg{rule spec}]\{\arg{columns}\} + \end{codesyntax} + Both forms add a second \tsobj[code, no index]{\cmidrule} below the first. \tsobj[code, no index]{\cmidrulemore} is the shorter of the two, and \tsobj[code, no index]{\morecmidrules} follows the usage of \pkg{booktabs}. The rows below show that they give the same result. + + \begin{codestore}[st=lib:booktabs:more] + \begin{tblr}{llll} + \toprule + Poet & City & Work & Form \\ + \cmidrule{1-3} \cmidrulemore{2-4} + Ferdowsi & Tus & Shahnameh & Epic \\ + \cmidrule{1-3} \morecmidrules \cmidrule{2-4} + Rumi & Konya & Masnavi & Couplets \\ + \bottomrule + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:booktabs:more} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + env, + new=2021N, + update=2022A +]{booktabs, longtabs, talltabs} +\begin{codesyntax} +\tsobj[code, no index]{\begin{booktabs}}[\oarg{outer spec}]\{\arg{inner spec}\} +\end{codesyntax} +These environments are the counterparts of \env{tblr}, \env{longtblr} and \env{talltblr}. Each one sets \vrb{rowsep=0pt} and has the rule commands add \tsobj[code]{\aboverulesep} (default: \val{.4ex}) and \tsobj[code]{\belowrulesep} (default: \val{.65ex}) around each rule, in the manner of \pkg{booktabs}. The first table below is a \env{tblr}, in which the rules leave the even \key[no index]{rowsep} as it is. The second is a \env{booktabs}. + +\begin{codestore}[st=lib:booktabs:env] + \begin{tblr}{lll} + \toprule + Poet & City & Work \\ + \midrule + Ferdowsi & Tus & Shahnameh \\ + Hafez & Shiraz & Divan \\ + \bottomrule + \end{tblr}\quad + \begin{booktabs}{lll} + \toprule + Poet & City & Work \\ + \midrule + Ferdowsi & Tus & Shahnameh \\ + Hafez & Shiraz & Divan \\ + \bottomrule + \end{booktabs}\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:booktabs:env} +\end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021N + ]{specialrule} + \begin{codesyntax} + \tsobj[code, no index]{\specialrule}\{\arg{rule spec}\}\{\arg{space above}\}\{\arg{space below}\} + \end{codesyntax} + \tsobj[code, no index]{\specialrule} draws a rule and sets the \key[no index]{abovespace} and \key[no index]{belowspace} of its border (\S\ref{inner:borders}) directly. + + \begin{codestore}[st=lib:booktabs:special] + \begin{booktabs}{row{2} = {bg=yellow!30}} + \toprule + Poet & City & Work \\ + \specialrule{0.5pt}{4pt}{6pt} + Ferdowsi & Tus & Shahnameh \\ + \specialrule{0.8pt, blue}{3pt}{2pt} + Hafez & Shiraz & Divan \\ + \bottomrule + \end{booktabs}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:booktabs:special} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021N + ]{addlinespace, addrowspace} + \begin{codesyntax} + \tsobj[code, no index]{\addlinespace}[\oarg{dim}] + \end{codesyntax} + \tsobj[code, no index]{\addlinespace}, also available as \tsobj[code, no index]{\addrowspace}, adds vertical space between 2 rows with no rule, and divides that space equally between the \key[no index]{belowsep} of the first row and the \key[no index]{abovesep} of the second. The size defaults to \tsobj[code]{\defaultaddspace}, which is \val{.5em} unless changed. + + \begin{codestore}[st=lib:booktabs:space] + \begin{booktabs}{row{2} = {bg=yellow!30}} + \toprule + Poet & City & Work \\ + \addlinespace + Ferdowsi & Tus & Shahnameh \\ + \addlinespace[1em] + Hafez & Shiraz & Divan \\ + \bottomrule + \end{booktabs}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:booktabs:space} + \end{center} +\end{codedescribe} + +\section{Library \texttt{counter}}\label{lib:counter} +\pkg{tabularray} typesets a cell more than once: at least once to measure it, and again to build the table. A counter stepped inside a cell is therefore stepped on every pass, so its values skip. This library saves all \LaTeX{} counters before measuring and restores them afterwards, which leaves only the final pass to count. It has no commands or keys of its own. Its cost is small, yet it applies to every table, so a document with no counters in its cells has little reason to load it. + +The result on the left below shows the same table without the library, and the one on the right with it. The left-hand values depend on how often each cell is typeset, and so are of no use to a document. + +\begin{codestore}[st=lib:counter:def] + \newcounter{mycnt} + \newcommand{\mycnt}{\stepcounter{mycnt}\arabic{mycnt}}\end{codestore} +\begin{codestore}[st=lib:counter:table] + \begin{tblr}{hlines, vlines} + \mycnt & \mycnt & \mycnt \\ + \mycnt & \mycnt & \mycnt + \end{tblr}\end{codestore} +\tscode*[tblr]{lib:counter:def} +\tscode*[tblr]{lib:counter:table} +\tsexec{lib:counter:def} +\begin{center} + {\WithoutCounterLibrary\tsexec{lib:counter:table}}\qquad + \setcounter{mycnt}{0}\tsexec{lib:counter:table} +\end{center} + +\section{Library \texttt{diagbox}}\label{lib:diagbox} +A diagonal cell labels both axes of a table in one place, at the expense of the room available to each label. This library loads \pkg{diagbox} and adapts its command to table cells. + +\begin{codedescribe}[ + code, + new=2021L + ]{diagbox, diagboxthree} + \begin{codesyntax} + \tsobj[code, no index]{\diagbox}[\oarg{options}]\{\arg{lower left}\}\{\arg{upper right}\} + \tsobj[code, no index]{\diagboxthree}[\oarg{options}]\{\arg{lower left}\}\{\arg{middle}\}\{\arg{upper right}\} + \end{codesyntax} + \tsobj[code, no index]{\diagbox} divides a cell with a diagonal line, and \tsobj[code, no index]{\diagboxthree} divides it into 3 parts with 2 lines. The optional argument accepts the options of \pkg{diagbox}, and the box takes its side margins from the cell. In a table in math mode, each part is set in math mode as well, as in the last table below. + + \begin{codestore}[st=lib:diagbox] + \begin{tblr}{hlines, vlines} + \diagbox{s}{S} & Signifier \\ + Signified & Bar + \end{tblr}\quad + \begin{tblr}{hlines, vlines} + \diagboxthree{s}{Bar}{S} & Signifier \\ + Signified & Bar + \end{tblr}\quad + $\begin{tblr}{hlines, vlines} + \diagbox{x_1}{x_2} & 0 \\ + 1 & 0.5 + \end{tblr}$\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:diagbox} + \end{center} +\end{codedescribe} + +\section{Library \texttt{functional}}\label{lib:functional} +This library loads the \pkg{functional} package, in which a function is defined with \tsobj[code]{\prgNewFunction} and gives back its result with \tsobj[code]{\prgReturn}. It applies these functions at 3 stages of building a table: to the inner specification, to the table body, and to the table after its specification has been parsed. These stages turn a table from a static description into a computed result, which suits repetitive or data-driven tables. For a small table the gain is less clear, as the source can become harder to read than the table it produces. + +\subsection{Evaluating Inner Specifications} +With this library loaded, every function in an inner specification is replaced with its return value before the key--value list is parsed, without any further key. In the example below, \tsobj[code]{\funColor} is a function of the \pkg{functional} package. + +\begin{codestore}[st=lib:fun:color] + \begin{tblr}{ + hlines, + row{2} = {bg=\funColor{RGB}{180,180,255}}, + } + Real & Symbolic \\ + Imaginary & Sinthome \\ + Subject & Other + \end{tblr}\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:fun:color} +\end{center} + +A function can also compute its value from the state of the document. The function below selects a colour from the page number, and so the output of the table depends on the page it falls on. \tsobj[code]{\IgnoreSpacesOn} and \tsobj[code]{\IgnoreSpacesOff} prevent the spaces in the definition from being typeset. + +\begin{codestore}[st=lib:fun:page] + \IgnoreSpacesOn + \prgNewFunction \byPage {mm} { + \intIfOddTF {\value{page}} {\prgReturn {#1}} {\prgReturn {#2}} + } + \IgnoreSpacesOff + \begin{tblr}{ + hlines, + row{1} = {bg=\byPage{yellow!30}{cyan!30}}, + row{3} = {bg=\byPage{green!30}{blue!20}}, + } + Real & Symbolic \\ + Imaginary & Sinthome \\ + Subject & Other + \end{tblr}\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:fun:page} +\end{center} +\begin{tsremark} + The inner specification is split into keys and values before it is evaluated. This is why a bare \key[no index]{colspec} containing \vrb{=} must keep its name when this library is loaded, as \S\ref{inner:types} notes. +\end{tsremark} + +\subsection{Evaluating the Table Body} +\begin{codedescribe}[ + key, + new=2022B, + update=2023A + ]{evaluate} + \begin{codesyntax} + \keyval{evaluate}{\arg{function} | all} + \end{codesyntax} + \key{evaluate} is an outer key that replaces each use of a function in the table body with its return value, before the body is split into rows and cells. A function can therefore supply the separators \vrb{&} and \tsverb*{\\}, which \pkg{tabularray} would otherwise overlook. With \val{all}, every function in the body is evaluated. \S\ref{outer:expand} describes a related key for macros. + + A common use is to read rows from a file with \tsobj[code]{\fileInput}, as in the listing below, in which \vrb{rows.tex} contains lines such as \tsverb*{Attar & 2 \\}. + + \begin{codestore}[st=lib:fun:input] + \begin{tblr}[evaluate=\fileInput]{hlines} + Ferdowsi & 1 \\ + \fileInput{rows.tex} + Hafez & 4 + \end{tblr}\end{codestore} + \tscode*[tblr]{lib:fun:input} +\end{codedescribe} + +A function of our own can return parts of a table in the same way, up to the whole of its body. + +\begin{codestore}[st=lib:fun:row] + \IgnoreSpacesOn + \prgNewFunction \myRow {m} { + \prgReturn {#1 & #1 \\} + } + \prgNewFunction \emptyGrid {mm} { + \tlSet \lTmpaTl {\intReplicate {\intEval{#2-1}} {&}} + \tlPutRight \lTmpaTl {\\} + \intReplicate {#1} {\tlUse \lTmpaTl} + } + \IgnoreSpacesOff + \begin{tblr}[evaluate=\myRow]{hlines} + Real & 1 \\ + \myRow{Symbolic} + Imaginary & 3 + \end{tblr}\quad + \begin{tblr}[evaluate=\emptyGrid]{hlines, vlines} + \emptyGrid{3}{7} + \end{tblr}\quad + \begin{tblr}[evaluate=all]{hlines} + \myRow{Symbolic} + Rings & \intEval{3+1} + \end{tblr}\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:fun:row} +\end{center} + +\subsection{Processing Table Elements} +\begin{codedescribe}[ + key, + new=2022B + ]{process} + \begin{codesyntax} + \keyval{process}{\arg{function}} + \end{codesyntax} + \key{process} is an inner key that runs a function once the specification has been parsed and before the table is built. The function reads and changes the table through the functions below, which take row and column numbers. + \begin{describelist*}{code, no index} + \describe{\cellGetText}{\{\arg{row}\}\{\arg{column}\} returns the text of a cell} + \describe{\cellSetText}{\{\arg{row}\}\{\arg{column}\}\{\arg{text}\} replaces the text of a cell} + \describe{\cellSetStyle}{\{\arg{row}\}\{\arg{column}\}\{\arg{style}\} styles a cell} + \describe{\rowSetStyle}{\{\arg{row}\}\{\arg{style}\} styles a row} + \describe{\columnSetStyle}{\{\arg{column}\}\{\arg{style}\} styles a column} + \end{describelist*} +\end{codedescribe} + +The function below sums each column into the last row of the table. The loops of \tsobj[code]{\intStepOneInline} are nested, so that \texttt{\#\#1} is the column and \texttt{\#\#\#\#1} the row. + +\begin{codestore}[st=lib:fun:sum] + \IgnoreSpacesOn + \prgNewFunction \calcSum {} { + \intStepOneInline {1} {\arabic{colcount}} { + \intZero \lTmpaInt + \intStepOneInline {1} {\arabic{rowcount}-1} { + \intAdd \lTmpaInt {\cellGetText {####1} {##1}} + } + \cellSetText {\expWhole{\arabic{rowcount}}} {##1} {\intUse\lTmpaInt} + } + } + \IgnoreSpacesOff + \begin{tblr}{colspec = {rrr}, process = \calcSum} + \hline + 1 & 2 & 3 \\ + 4 & 5 & 6 \\ + 7 & 8 & 9 \\ + \hline + & & + \end{tblr}\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:fun:sum} +\end{center} + +Styles can depend on the content of a cell in the same way. The first table below sets the background of each cell from the sign of its value, and the second styles whole rows and columns. + +\begin{codestore}[st=lib:fun:style] + \IgnoreSpacesOn + \prgNewFunction \colourSign {} { + \intStepOneInline {1} {\arabic{rowcount}} { + \intStepOneInline {1} {\arabic{colcount}} { + \intSet \lTmpaInt {\cellGetText {##1} {####1}} + \intCompareTF {\lTmpaInt} > {0} + {\cellSetStyle {##1} {####1} {bg=green!30}} + {\cellSetStyle {##1} {####1} {bg=red!30}} + } + } + } + \prgNewFunction \stripes {} { + \intStepOneInline {1} {\arabic{rowcount}} { + \intIfOddTF {##1} {\rowSetStyle {##1} {bg=yellow!30}} {} + } + \columnSetStyle {1} {font=\bfseries} + } + \IgnoreSpacesOff + \begin{tblr}{hlines, vlines, cells = {r}, process = \colourSign} + -1 & 2 & 3 \\ + 4 & 5 & -6 \\ + 7 & -8 & 9 + \end{tblr}\quad + \begin{tblr}{hlines, process = \stripes} + Real & 1 \\ + Symbolic & 2 \\ + Imaginary & 3 + \end{tblr}\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:fun:style} +\end{center} + +\section{Library \texttt{hook}}\label{lib:hook} +\DefaultMeasure{vstore} +This experimental library lets code run at fixed points while a table is built, and its interface may change in a later release. Hooks go beyond what the keys can express, but code written for them depends on the order in which a table is built. The library loads the \pkg{varwidth} library and makes \val{vstore} the default value of \key[no index]{measure} (\S\ref{lib:varwidth}). + +\begin{codedescribe}[ + code, + new=2025A + ]{AddToTblrHook, AddToTblrHookNext} + \begin{codesyntax} + \tsobj[code, no index]{\AddToTblrHook}\{\arg{hook}\}[\oarg{label}]\{\arg{code}\} + \tsobj[code, no index]{\AddToTblrHookNext}\{\arg{hook}\}\{\arg{code}\} + \end{codesyntax} + \tsobj[code, no index]{\AddToTblrHook} adds code to a hook for the rest of the document, and \tsobj[code, no index]{\AddToTblrHookNext} adds it for the next use of the hook only. They are short forms of the \LaTeX{} commands \tsobj[code, no index]{\AddToHook} and \tsobj[code, no index]{\AddToHookNext}, which take the same names with \vrb{tabularray/} in front. The hooks are listed below. Without this library they are not used, so code added to them has no effect and raises no error. + \begin{describelist*}{verb, no index} + \describe{trial/before}{Before the cells go through measuring} + \describe{trial/after}{After the cells go through measuring} + \describe{table/before}{Before the whole table is built} + \describe{table/after}{After the whole table is built} + \describe{row/before}{Before a row is typeset} + \describe{row/after}{After a row is typeset} + \describe{cell/before}{Before a cell is typeset} + \describe{cell/after}{After a cell is typeset} + \end{describelist*} + + The code in \vrb{table/before} below runs inside the table, so that only the text of the first table turns red. The rules keep their own colour. + + \begin{codestore}[st=lib:hook:next] + \AddToTblrHookNext{table/before}{\color{red}} + \begin{tblr}{hlines} + Red ink & Unavailable + \end{tblr}\quad + \begin{tblr}{hlines} + Red ink & Unavailable + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:hook:next} + \end{center} + + A label names the code in a hook so that it can be removed later, here with the \LaTeX{} command \tsobj[code, no index]{\RemoveFromHook}. The hook for cells runs once per cell, unlike the text of a cell, as it is not used while measuring. + + \begin{codestore}[st=lib:hook:label] + \newcounter{cellcount} + \AddToTblrHook{cell/before}[demo]{\stepcounter{cellcount}} + \begin{tblr}{hlines} + Sublime & Object \\ + Ticklish & Subject + \end{tblr} + \RemoveFromHook{tabularray/cell/before}[demo] + This table has \arabic{cellcount} cells.\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:hook:label} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2023A + ]{lTblrMeasuringBool} + \tsobj[code, no index]{\lTblrMeasuringBool} is true while \pkg{tabularray} measures the cells, which allows the text of a cell to differ between the passes. It is reliable with \vrb{measure=vstore} only, which is the default under this library. Below, the column keeps the width of the words typeset while measuring. +\end{codedescribe} + +\begin{codestore}[st=lib:hook:bool] + \ExplSyntaxOn + \NewDocumentCommand \PassName { } + { \bool_if:NTF \lTblrMeasuringBool { first~as~tragedy } { then~as~farce } } + \ExplSyntaxOff + \begin{tblr}{hlines, vlines} + \PassName & Real + \end{tblr}\end{codestore} +\tscode*[tblr]{lib:hook:bool} +\begin{center} + \tsexec{lib:hook:bool} +\end{center} + +\section{Library \texttt{html}}\label{lib:html} +\DefaultMeasure{hbox} +This experimental library updates a further set of variables before each cell is built, to describe its borders. They are intended for packages that tag or convert documents, such as \pkg{tagpdf}, \pkg{tex4ht} and \pkg{lwarp}, and they may change in a later release. Their value lies in exposing the visual properties of a table to tools that have to reproduce them in another form, which makes the library of little use to an ordinary document. + +\begin{codedescribe}[ + code, + new=2024A + ]{lTblrCellAboveBorderStyleTl, lTblrCellAboveBorderWidthDim, lTblrCellAboveBorderColorTl} + The word \vrb{Above} in these names can be replaced with \vrb{Below}, \vrb{Left} or \vrb{Right}, for 12 variables in all. Style, width and colour correspond to \vrb{border-style}, \vrb{border-width} and \vrb{border-color} in CSS. A side with no rule has an empty style and a width of \val{0pt}, and the colour stays empty unless a rule sets one. + + These variables are only updated for the final pass, so the columns below have a fixed width. The first row shows the rule above each cell, and the second row the rule on its left. + + \begin{codestore}[st=lib:html] + \newcommand\showAbove{% + \lTblrCellAboveBorderStyleTl{} + \the\lTblrCellAboveBorderWidthDim{} + \lTblrCellAboveBorderColorTl} + \newcommand\showLeft{% + \lTblrCellLeftBorderStyleTl{} + \the\lTblrCellLeftBorderWidthDim{} + \lTblrCellLeftBorderColorTl} + \begin{tblr}{ + colspec = {Q[9em] Q[9em]}, + hline{1} = {2pt, red}, + vline{2} = {1pt, dotted}, + } + \showAbove & \showAbove \\ + \showLeft & \showLeft + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:html} + \end{center} + \begin{tsremark} + \tsobj[code]{\lTblrCellRowSpanInt}, \tsobj[code]{\lTblrCellColSpanInt}, \tsobj[code]{\lTblrCellOmittedBool} and \tsobj[code]{\lTblrCellBackgroundTl} are updated before each cell as well, and need no library. + \end{tsremark} +\end{codedescribe} + +\section{Library \texttt{nameref}}\label{lib:nameref} +\tsobj[code, no index]{\nameref} prints the title of what a label refers to, and a caption is a natural candidate for that title. Without this library, a label on a \env{longtblr} or \env{talltblr} gives the title of the enclosing section. With it, \tsobj[code, no index]{\nameref} prints the \key[no index]{entry} of the table if it has one, or else its \key[no index]{caption}. The preference for \key[no index]{entry} recognises that a caption written for the page is often too long for running text. + +\begin{codestore}[st=lib:nameref] + \begin{longtblr}[ + caption = {A caption that is too long for a reference}, + entry = {A short entry}, + label = {tab:nameref:entry}, + ]{hlines, colspec = {X[c]X[c]}, width = 10cm} + Real & Symbolic + \end{longtblr} + \begin{longtblr}[ + caption = {A caption only}, + label = {tab:nameref:caption}, + ]{hlines, colspec = {X[c]X[c]}, width = 10cm} + Real & Symbolic + \end{longtblr} + The first is \nameref{tab:nameref:entry}, and the + second is \nameref{tab:nameref:caption}.\end{codestore} +\tscode*[tblr]{lib:nameref} +\tsexec{lib:nameref} + +\section{Library \texttt{siunitx}}\label{lib:siunitx} +Aligning numbers on their decimal markers makes them easier to compare, which the alignment keys of \pkg{tabularray} cannot do on their own. This library loads \pkg{siunitx} and connects its formatting of numbers and units to table columns, so that every cell in such a column is treated as a number until it is exempted. \S\ref{inner:types} describes the underlying key \key[no index]{si}. + +\begin{codedescribe}[ + code, + new=2021L, + update=2021M, + update=2025A + ]{S, s} + \begin{codesyntax} + \tsverb{S}[\oarg{siunitx options}] + \tsverb{s}[\oarg{siunitx options}] + \end{codesyntax} + \tsverb{S} is a centred column that aligns numbers on their decimal markers, and \tsverb{s} is a centred column that formats its cells as units. The options are those of \pkg{siunitx}. A cell in these columns that is neither a number nor a unit, such as a column head, needs a pair of braces around it. + + \begin{codestore}[st=lib:si:columns] + \begin{tblr}{ + hlines, vlines, + colspec = {S[table-format=3.2] s}, + } + {Value} & {Unit} \\ + 111 & \kilo\metre \\ + 2.1 & \metre\per\second \\ + 33.11 & \joule + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:si:columns} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + key, + new=2022B + ]{guard} + \begin{codesyntax} + \key[no index]{guard} + \end{codesyntax} + \key{guard} exempts a cell, row or column from number formatting by clearing its \key[no index]{cmd}, which removes the need to brace each cell by hand. A guarded cell keeps its own horizontal alignment, which must be set with \key[no index]{l}, \key[no index]{c} or \key[no index]{r}. The table below uses the \pkg{siunitx} option \vrb{table-number-alignment} to match the numbers of each column to that alignment. + + \begin{codestore}[st=lib:si:guard] + \begin{tblr}{ + hlines, vlines, columns = {6em}, + colspec = { + Q[si={table-format=3.2, table-number-alignment=left}, l] + Q[si={table-format=3.2, table-number-alignment=center}, c] + Q[si={table-format=3.2, table-number-alignment=right}, r] + }, + row{1} = {guard}, + } + I would & prefer & not to \\ + 111 & 111 & 111 \\ + 2.1 & 2.2 & 2.3 \\ + 33.11 & 33.22 & 33.33 + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:si:guard} + \end{center} +\end{codedescribe} + +\begin{codedescribe}[ + code, + new=2021M + ]{TblrNum, TblrUnit} + \begin{codesyntax} + \key[no index]{cmd} \tsobj[code, no index]{=} \tsobj[code, no index]{\TblrNum} + \key[no index]{cmd} \tsobj[code, no index]{=} \tsobj[code, no index]{\TblrUnit} + \end{codesyntax} + These are the commands that the column types apply through \key[no index]{cmd}. \tsobj[code, no index]{\TblrNum} formats a cell as a number and \tsobj[code, no index]{\TblrUnit} as a unit, using the \key[no index]{si} options of the column. They can be set on selected cells, which leaves a head row free of braces and \key{guard}. + + \begin{codestore}[st=lib:si:cmd] + \begin{tblr}{ + hlines, vlines, colspec = {cc}, + cell{2-Z}{1} = {cmd=\TblrNum}, + cell{2-Z}{2} = {cmd=\TblrUnit}, + } + Value & Unit \\ + 1.5 & \kilo\metre \\ + 12.25 & \second + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:si:cmd} + \end{center} +\end{codedescribe} + +\section{Library \texttt{tikz}}\label{lib:tikz} +\DefaultMeasure{vstore} +This experimental library\footnote{We thank \href{https://github.com/jasperhabicht}{Jasper Habicht} for his contributions to this library.} draws \pkg{tikz} pictures below or above a table, and its interface may change in a later release. A drawing can express relations between cells that rules and backgrounds cannot, such as a path across several of them, but this is the most demanding option in the chapter: it loads \pkg{tikz} with its \vrb{calc} library, together with the \pkg{hook} library of \S\ref{lib:hook}, changes the default value of \key[no index]{measure}, and needs a second compilation. + +\begin{codedescribe}[ + env, + new=2025A + ]{tblrtikzbelow, tblrtikzabove} + \begin{codesyntax} + \tsobj[code, no index]{\begin{tblrtikzbelow}} \tsmeta{tikz code} \tsobj[code, no index]{\end{tblrtikzbelow}} + \tsobj[code, no index]{\begin{tblrtikzabove}} \tsmeta{tikz code} \tsobj[code, no index]{\end{tblrtikzabove}} + \end{codesyntax} + These environments keep \pkg{tikz} code for the table that follows, which is drawn behind or over that table. They go before the table, and a \texttt{\%} after each one prevents a stray space. The drawing depends on positions saved in the \vrb{.aux} file, so a document needs 2 compilations. + + The following nodes are available inside these environments: + \begin{center} + \begin{tblr}{ + colspec = {Q[l] Q[l] X[l]}, + width = \linewidth, + row{1} = {font=\bfseries}, + hline{1,2,Z} = {solid}, + rowsep = 1pt, + } + Name & Type & Position \\ + \vrb{table} & Rectangle & The whole table \\ + \tsmeta{i}\vrb{-}\tsmeta{j} & Rectangle & \keysel{cell}{i}\{\tsmeta{j}\} \\ + \vrb{h}\tsmeta{i} & Coordinate & Crossing of \keysel{hborder}{i} and \keysel{vborder}{1} \\ + \vrb{v}\tsmeta{j} & Coordinate & Crossing of \keysel{vborder}{j} and \keysel{hborder}{1} + \end{tblr} + \end{center} + + The first example below uses the table node and cell nodes. The second traces a path with corner nodes, for which the \pkg{tikz} intersection syntax \vrb{h}\tsmeta{i}\vrb{-|v}\tsmeta{j} gives the crossing of any 2 borders. + + \begin{codestore}[st=lib:tikz:nodes] + \begin{tblrtikzbelow} + \path[pattern=dots, pattern color=blue, + draw=blue, thick, rounded corners] + (table.north west) rectangle (table.south east); + \end{tblrtikzbelow}% + \begin{tblrtikzabove} + \draw[red, thick] + (2-2.north west) -- (2-3.south east) + (2-2.south west) -- (2-3.north east); + \end{tblrtikzabove}% + \begin{tblr}{hline{2-3}, vline{2-4}} + 1-1 & 1-2 & 1-3 & 1-4 \\ + 2-1 & 2-2 & 2-3 & 2-4 \\ + 3-1 & 3-2 & 3-3 & 3-4 + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:tikz:nodes} + \end{center} + + \begin{codestore}[st=lib:tikz:corners] + \begin{tblrtikzabove} + \draw[white, thick] + (h1-|v1) -- (h1-|v2) -- (h2-|v2) + -- (h2-|v3) -- (h3-|v3) -- (h3-|v4) + -- (h4-|v4) -- (h4-|v5) -- (h2-|v5) + -- (h2-|v6) -- (h1-|v6); + \end{tblrtikzabove}% + \begin{tblr}{hlines = {wd=4pt}, vlines = {wd=3pt}} + 1-1 & 1-2 & 1-3 & 1-4 & 1-5 \\ + 2-1 & 2-2 & 2-3 & 2-4 & 2-5 \\ + 3-1 & 3-2 & 3-3 & 3-4 & 3-5 + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:tikz:corners} + \end{center} + \begin{tsremark} + The styles \vrb{tblr/table}, \vrb{tblr/cell} and \vrb{tblr/overlay} can be set with \tsobj[code, no index]{\tikzset} to change the table node, every cell node, and each picture drawn in these environments. + \end{tsremark} + \begin{tsremark} + A package written in \vrb{expl3} syntax should read \href{https://github.com/pgf-tikz/pgf/issues/1213}{this \pkg{tikz} issue} before it loads the library. + \end{tsremark} +\end{codedescribe} + +\subsection{Drawing Across Tables} +The nodes of a table have a full name of \vrb{tblr}\tsmeta{name}\vrb{-}\tsmeta{node}, and the environments above add the prefix on our behalf. A table given the inner key \key[no index]{name} can therefore be addressed from any \pkg{tikz} picture. Nodes are only made for a table that follows one of the environments, which may be empty. + +\begin{codestore}[st=lib:tikz:name] + \begin{tblrtikzbelow}\end{tblrtikzbelow}% + \begin{tblr}{name = first, hlines, vlines} + Zal & Rostam + \end{tblr}\hspace{4em}% + \begin{tblrtikzbelow}\end{tblrtikzbelow}% + \begin{tblr}{name = second, hlines, vlines} + Esfandiyar & Bahman + \end{tblr}% + \begin{tikzpicture}[remember picture, overlay] + \draw[->, red, thick] + (tblrfirst-1-2.east) -- (tblrsecond-1-1.west); + \end{tikzpicture}\end{codestore} +\begin{center} + \tsdemo*[tblr]{lib:tikz:name} +\end{center} + +\subsection{Drawing on Long Tables} +Support for long tables is limited. A \env{longtblr} that spans several pages has cell nodes only, and the code runs once per page, so it must only draw on rows of the current page. The following variables help with that check: +\begin{describelist*}{code, no index} + \describe{\lTblrRowHeadInt}{The number of head rows} + \describe{\lTblrRowFootInt}{The number of foot rows} + \describe{\lTblrTablePageInt}{The index of the current page of the table} + \describe{\lTblrRowFirstInt}{The first body row on the current page} + \describe{\lTblrRowLastInt}{The last body row on the current page} +\end{describelist*} + +The example below marks cells with a class through \tsobj[code]{\SetChild}, at the very start of each cell. \tsobj[code]{\ExpTblrChildClass} expands to the row and column of each marked cell, and the code then fills only those on the current page. The \key[no index]{hborder} forces a break, so that the table spans 2 pages. + +\begin{codestore}[st=lib:tikz:long] + \ExplSyntaxOn + \cs_generate_variant:Nn \clist_map_inline:nn {e} + \cs_new_protected:Npn \fillclass #1 + { + \clist_map_inline:en {\ExpTblrChildClass {#1}} + { + \bool_lazy_and:nnT + { \int_compare_p:n {\lTblrRowFirstInt <= \use_i:nn ##1} } + { \int_compare_p:n {\lTblrRowLastInt >= \use_i:nn ##1} } + { \exp_args:Noo \fillcell {\use_i:nn ##1} {\use_ii:nn ##1} } + } + } + \ExplSyntaxOff + \newcommand\fillcell[2]{ + \fill[yellow, rounded corners=4pt] + (#1-#2.north west) rectangle (#1-#2.south east); + } + \begin{tblrtikzbelow} + \fillclass{mark} + \end{tblrtikzbelow}% + \begin{longtblr}[ + caption = {Cells filled across the pages of a long table}, + ]{ + rowhead = 1, rowfoot = 1, hlines, vlines, + colspec = {*{4}{X[r]}}, width = \linewidth, + hborder{5} = {pagebreak}, + } + Head & Head & Head & Head \\ + 2-1 & 2-2 & \SetChild{class=mark}2-3 & 2-4 \\ + 3-1 & 3-2 & 3-3 & 3-4 \\ + \SetChild{class=mark}4-1 & 4-2 & 4-3 & 4-4 \\ + 5-1 & 5-2 & 5-3 & 5-4 \\ + 6-1 & \SetChild{class=mark}6-2 & 6-3 & 6-4 \\ + Foot & Foot & Foot & Foot + \end{longtblr}\end{codestore} +\tscode*[tblr]{lib:tikz:long} +\tsexec{lib:tikz:long} + +\section{Library \texttt{varwidth}}\label{lib:varwidth} +\DefaultMeasure{vbox} +A horizontal box suits a line of text but cannot contain a list, and a table uses one method for all of its cells. The core chooses the simpler method and leaves the general case to this library, which adds a dependency and a small cost in compilation time. + +\begin{codedescribe}[ + key, + new=2021N, + update=2025A + ]{measure} + \begin{codesyntax} + \keyval{measure}{hbox | vbox | vstore} + \end{codesyntax} + To find the natural width of a cell, \pkg{tabularray} typesets it in a box. The core uses a horizontal box, which cannot contain vertical material, so a list raises the error \vrb{Not allowed in LR mode} and display maths raises \vrb{Bad math environment delimiter}. This library loads \pkg{varwidth} and adds the key \key{measure}, which selects the box. + \begin{describelist*}{values} + \describe{hbox}{Typeset the cell in a horizontal box. The default of the core} + \describe{vbox}{Typeset the cell in a \pkg{varwidth} box, which accepts vertical material. The default with this library} + \describe{vstore}{As \val{vbox}, but reuse the box in place of typesetting the cell again while measuring. The default with the \pkg{hook} library. Experimental} + \end{describelist*} + The setting also applies to tables nested in the cells. A column of fixed width, such as \vrb{Q[6em]}, skips measuring and so needs none of this, but an \tsverb{X} column does not. + + \begin{codestore}[st=lib:varwidth:vbox] + \begin{tblr}{hlines, vlines, measure=vbox} + Underneath the Bough: + \begin{itemize} + \item A Book of Verses + \item A Jug of Wine + \item A Loaf of Bread + \end{itemize} + And Thou & Paradise enow + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:varwidth:vbox} + \end{center} + + Lists leave extra space above and below them. A negative \key[no index]{stretch} (\S\ref{inner:table}) removes it, which is the difference between the 2 tables below. + + \begin{codestore}[st=lib:varwidth:stretch] + \begin{tblr}{hlines, vlines, measure=vbox} + \begin{itemize} + \item A Jug of Wine + \item A Loaf of Bread + \end{itemize} & And Thou + \end{tblr}\quad + \begin{tblr}{hlines, vlines, measure=vbox, stretch=-1} + \begin{itemize} + \item A Jug of Wine + \item A Loaf of Bread + \end{itemize} & And Thou + \end{tblr}\end{codestore} + \begin{center} + \tsdemo*[tblr]{lib:varwidth:stretch} + \end{center} + \begin{tsremark} + Natural widths stay the same between the values, but other details of the output can shift slightly, such as a line break in a spanning cell. Adding the \pkg{hook} or \pkg{tikz} library to a finished document therefore calls for a check of its tables. + \end{tsremark} +\end{codedescribe} + +\section{Library \texttt{zref}}\label{lib:zref} +\DefaultMeasure{hbox} +\pkg{zref} is an alternative to the reference system of \LaTeX{}, and its \tsobj[code, no index]{\zref} does not recognise a \key[no index]{label} on a \env{longtblr} or \env{talltblr} by default. This library loads \pkg{zref-user} and sets each such \key[no index]{label} for \tsobj[code, no index]{\zref} as well, so that \tsobj[code, no index]{\ref} and \tsobj[code, no index]{\zref} both work on the same name. This is a matter of compatibility and adds no capability of its own, so the library is useful only to documents that already rely on \pkg{zref}. + +\begin{codestore}[st=lib:zref] + \begin{longtblr}[ + caption = {A table with a label}, + label = {tab:zref}, + ]{hlines, colspec = {X[c]X[c]}, width = 10cm} + Real & Symbolic + \end{longtblr} + Table \zref{tab:zref} is on page \zref[page]{tab:zref}.\end{codestore} +\tscode*[tblr]{lib:zref} +\tsexec{lib:zref} diff --git a/doc/TabularrayDoc.cls b/doc/TabularrayDoc.cls index edbb25b..ce8b418 100644 --- a/doc/TabularrayDoc.cls +++ b/doc/TabularrayDoc.cls @@ -1,56 +1,42 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesClass{TabularrayDoc}[2026A LaTeX document class] -\def\baseclass{memoir} +\def\baseclass{book} \DeclareOption*{\PassOptionsToClass{\CurrentOption}{\baseclass}} \def\@checkoptions#1#2{ - \edef\@curroptions{\@ptionlist{\@currname.\@currext}} - \@tempswafalse - \@tfor\@this:=#2\do{ - \@expandtwoargs\in@{,\@this,}{,\@curroptions,} - \ifin@ \@tempswatrue \@break@tfor \fi} - \let\@this\@empty - \if@tempswa \else \PassOptionsToClass{#1}{\baseclass}\fi + \edef\@curroptions{\@ptionlist{\@currname.\@currext}} + \@tempswafalse + \@tfor\@this:=#2\do{ + \@expandtwoargs\in@{,\@this,}{,\@curroptions,} + \ifin@ \@tempswatrue \@break@tfor \fi} + \let\@this\@empty + \if@tempswa \else \PassOptionsToClass{#1}{\baseclass}\fi } \ProcessOptions\relax \LoadClass{\baseclass} % Layout -% % This is the big outer size -% \setstocksize{326mm}{265mm} -% % This is where the machine cuts -% \settrimmedsize{276mm}{215mm}{*} -% % This is where the text goes -% \settypeblocksize{276mm}{215mm}{*} -% \setpagecc{276mm}{215mm}{*} -% % \setlrmarginsandblock{21mm}{21mm}{*} -% \setlrmarginsandblock{21mm}{21mm}{*} -% \setulmarginsandblock{0.875in}{0.625in}{*} -% \setheadfoot{0.875in}{0mm} -% \setheaderspaces{*}{0mm}{*} -% \setmarginnotes{0.1875in}{.5in}{0in} -% \setcolsepandrule{0.25in}{0pt} -\checkandfixthelayout -% \setlength{\oddsidemargin}{0mm} -% \setlength{\evensidemargin}{0mm} -\setSingleSpace{0.875} -\OnehalfSpacing* -% \hyphenpenalty=0 -% \widowpenalty=10000 -% \clubpenalty=10000 -\flushbottom +\usepackage[ + paperwidth = 82.667em, + paperheight = 116.915em, + textwidth = 39.3333em, + marginparwidth = 21.6667em, + marginpar = 17.1333em, + marginparsep = 2em, + top = 4.2835em, + bottom = 8.5667em + % showframe +]{geometry} +\usepackage{setspace} +\onehalfspacing \setlength{\parskip}{0pt} -\setlength{\parindent}{1.5ex} -\setlength{\hangindent}{0pt} +\setlength{\hangindent}{2em} +\setlength{\parindent}{2em} -\chapterstyle{article} - -% \semiisopage[11] \raggedbottom -\checkandfixthelayout -\checkthelayout -\fixthelayout +\raggedright % Fonts +\usepackage{amsmath} % before \arg is redefined below \usepackage[no-math]{fontspec} \setmainfont{TeX Gyre Pagella}[ Scale=MatchUppercase, @@ -62,7 +48,8 @@ ] \setmonofont{JetBrainsMono}[ Scale=MatchUppercase, - CharacterVariant={1,2,4,8,12,14,18,19,20,99} + CharacterVariant={1,2,4,8,12,14,18,19,20,99}, + RawFeature={-calt} ] \usepackage{microtype} \DeclareMicrotypeAlias{TeX Gyre Pagella}{TU-basic} @@ -88,6 +75,7 @@ \usepackage{codelisting} \input{codelisting.tabularray.sty} \usepackage[index, infograb, silence]{codedescribe} +\providecommand{\abstractname}{Abstract} \NewDocumentCommand{\ttbf}{}{\normalfont\ttfamily\bfseries} \defgroupfmt{meta}{ meta, color = darkgreen } \defgroupfmt{verb}{ color = magenta } @@ -113,17 +101,25 @@ \RenewDocumentCommand{\arg}{ O{} m }{\tsobj[marg,#1]{#2}} \NewDocumentCommand{\key}{ O{} m }{\tsobj[keys,#1]{#2}} -\NewDocumentCommand{\keyval}{ m m }{\tsobj[keys]{#1} \tsobj[code]= \tsobj[values]{#2}} -\RenewDocumentCommand{\oarg}{ O{} m }{\tsobj[oarg,#1]{#2}} +\NewDocumentCommand{\keyval}{ m m }{\tsobj[keys]{#1} \tsobj[code, no index]{=} \tsobj[values]{#2}} +\NewDocumentCommand{\oarg}{ O{} m }{\tsobj[oarg,#1]{#2}} \NewDocumentCommand{\env}{ s O{} m }{% - \tsobj[env,#2]{#3} environment% - \IfBooleanTF{#1}{s}{}% + \tsobj[env,#2]{#3}% + \IfBooleanT{#1}{ environment}% } \NewDocumentCommand{\pkg}{ s O{no index} m }{% - \tsobj[pkg, #2]{#3} package% - \IfBooleanTF{#1}{s}{}% + \tsobj[pkg, #2]{#3}% + \IfBooleanT{#1}{ package}% } \NewDocumentCommand{\val}{ O{} m }{\tsobj[values, #1]{#2}} \NewDocumentCommand{\vrb}{ O{} m }{\tsobj[verb, #1]{#2}} +\NewDocumentCommand{\keysel}{ m m o }{% + \tsobj[keys, no index]{#1}\{\tsmeta{#2}\}% + \IfValueT{#3}{ \tsobj[code, no index]{=} #3}% +} +\NewDocumentCommand{\issue}{ m }{% + \href{https://github.com/TeXackers/tabularray/issues/#1}{\##1}% +} + \NewDocumentCommand{\deschead}{ m }{\describe{}{\bfseries #1}} \ No newline at end of file diff --git a/doc/codelisting.tabularray.sty b/doc/codelisting.tabularray.sty index 548baf5..31870fb 100644 --- a/doc/codelisting.tabularray.sty +++ b/doc/codelisting.tabularray.sty @@ -1,6 +1,6 @@ %% %% Tabularray Code Listing Style Definition -%% Author: Jevgeni H. <@ponte-vecchio> +%% Author: Jae Y. Han <@ponte-vecchio> %% Version: 2026A %% \RequirePackage{listings} @@ -26,14 +26,25 @@ row, rows, rowspec, - hlines,vlines,hline,vline + cell,cells, + hlines,vlines,hline,vline, + hborder,vborder, + booktabs,longtabs,talltabs, + tblrtikzbelow,tblrtikzabove }, keywd = [2]{ - halign, valign, wd, ht, + halign, valign, wd, ht, width, co, si, colsep, colsep+, leftsep, leftsep+, rightsep, rightsep+, rowsep, rowsep+, abovesep, abovesep+, belowsep, belowsep+, - bg, fg, font, cmd, preto, appto, + bg, fg, bgcolor, fgcolor, font, mode, cmd, preto, appto, hlines,vlines,hline,vline, + dash, text, leftpos, rightpos, abovepos, belowpos, endpos, rulesep, + abovespace, abovespace+, belowspace, belowspace+, + leftspace, leftspace+, rightspace, rightspace+, pagebreak, + hspan, vspan, stretch, baseline, delimiter, rowhead, rowfoot, + caption, entry, label, note, remark, more, theme, + headsep, footsep, presep, postsep, expand, expand+, long, tall, + evaluate, process, measure, guard, name, Q,X,{|},\$\$, \$ } } diff --git a/doc/manual.tex b/doc/manual.tex index a0ec79a..d269049 100644 --- a/doc/manual.tex +++ b/doc/manual.tex @@ -1,8 +1,12 @@ \documentclass[12pt, oneside]{TabularrayDoc} -\usepackage{tabularray} -\UseTblrLibrary{functional} +\usepackage{tabularray-dev} +\UseTblrLibrary{ + amsmath, booktabs, counter, diagbox, functional, html, + nameref, siunitx, tikz, varwidth, zref +} +\usetikzlibrary{patterns} \IgnoreSpacesOn \prgNewFunction \YNColour {} { \intStepOneInline {1} {\arabic{rowcount}} { @@ -16,6 +20,17 @@ } \IgnoreSpacesOff +\ExplSyntaxOn +\NewDocumentCommand \DefaultMeasure { m } + { \tl_set:Nn \l__tblr_inner_spec_measure_tl {#1} } +\DefaultMeasure { hbox } +\NewDocumentCommand \WithoutCounterLibrary { } + { + \cs_set_protected:Npn \__tblr_save_counters:n ##1 { } + \cs_set_protected:Npn \__tblr_restore_counters:n ##1 { } + } +\ExplSyntaxOff + % https://github.com/TeXackers/tabularray/issues/198 \renewcommand\TblrOverlap[1]{#1} @@ -25,25 +40,30 @@ \begin{document} \frontmatter -\begin{titlingpage} -\tstitle{ - author={% - Leothelion\footnote{\tsfmt{\url{https://github.com/ponte-vecchio}}, primary author of the documentation}, - Author\footnote{\tsfmt{\url{https://github.com/ponte-vecchio}}} - }, - date={2026A (\tsdate)}, - title={{\ttfamily tabularray}: A Practitioner's Guide} -} -\begin{tsabstract} - This document serves as a practitioner's guide to the \pkg{tabularray} package, which provides a powerful and flexible interface for typesetting tables in \LaTeX. The guide is structured into two main sections: conceptualisation and practice. The conceptualisation section delves into the underlying principles and design philosophy of the package, while the practice section offers hands-on examples and explanations of key features, with a focus on the versatile Q-type for table cell specification. -\end{tsabstract} -\end{titlingpage} +\begin{titlepage} + \tstitle{ + author={% + Leothelion\footnote{\tsfmt{\url{https://github.com/ponte-vecchio}}, primary author of the documentation}, + % add yours + Author\footnote{\tsfmt{\url{https://github.com/ponte-vecchio}}} + }, + date={2026A (\tsdate)}, + title={{\ttfamily tabularray}: A Practitioner's Guide} + } + \begin{tsabstract} + This document serves as a practitioner's guide to the \pkg{tabularray} package, which provides a powerful and flexible interface for typesetting tables in \LaTeX. The package was originally written by Jianrui Lyu, and its ownership and management were transferred to the TeXackers organisation in early 2026. Release 2026A is the first under these new arrangements, and the overhaul of this documentation is one example of the work that has followed. + + The guide begins with a brief list of keys and commands for the impatient. It then examines the inner and outer specifications and the libraries in turn, showing by example what each option changes in the output. Because the interface commonly offers several routes to the same result, these examples illustrate each option and do not prescribe a correct method of typesetting. + \end{tsabstract} +\end{titlepage} \tableofcontents\cleardoublepage \mainmatter \input{01-impatient.tex} \input{02-inner.tex} +\input{03-outer.tex} +\input{04-libraries.tex} \backmatter \cleardoublepage