From c1aac14d5d1d32826a5e68a5dfc59a05b4f1e989 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sat, 11 Apr 2020 22:50:13 +0000 Subject: keyvaltable (5apr20) git-svn-id: svn://tug.org/texlive/trunk@54677 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/keyvaltable/keyvaltable.dtx | 1074 +++++++++++++------- 1 file changed, 730 insertions(+), 344 deletions(-) (limited to 'Master/texmf-dist/source/latex') diff --git a/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx b/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx index 813904fb233..f68b0bf67c3 100644 --- a/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx +++ b/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx @@ -22,7 +22,7 @@ %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{keyvaltable} %<*package> - [2020/02/19 v2.1 Package for filling tables using key-value lists] + [2020/04/05 v2.2 Package for filling tables using key-value lists] % % %<*driver> @@ -47,7 +47,7 @@ showhead=false,headformat={\bfseries\footnotesize}, rowbg=black!7!white..black!3!white, showrules=false, - shape=tabu]{GoalApproach}{ + backend=tabu]{GoalApproach}{ id: align=r, default=(\alph{kvtRow}), head=\#; goal: align=X[l]; approach: align={X[2,l]}; @@ -223,7 +223,10 @@ cherries,50g,cherries,heat up and add to bowl % \NiceDescribeKey{align}{vals={l,c,r,p,X,\ldots}, init=l} % This property specifies the alignment of content in the % column. The \meta{value} can be set to any column alignment -% understood by table environments. +% understood by table environments.\footnote{More complex values, for +% instance using the notation of the \pkgname{array} package for +% inserting material before or after a column, are permitted but not +% further tested. Use at your own risk.} % % \NiceDescribeKey{default}{vals=\vmeta{content}, init=\vmeta{empty}} % This property specifies the default \meta{content} of a cell in this @@ -497,6 +500,14 @@ cherries,50g,cherries,heat up and add to bowl % \end{KeyValTable} % \end{LTXexample} % +% By default, all counters start at value $1$. Through the following +% possibilities, this behavior can be changed. +% +% \NiceDescribeKey{resume}{vals={true,false}, init=false, def=true}\label{opt:resume} +% This option is available in |KeyValTable| environments. When this +% option is set to |true|, the value of the |kvtRow| counter is resumed +% from the previous |KeyValTable| environment. The other two counters +% are not affected by this option. % % \subsection{Row Labeling} % @@ -608,27 +619,33 @@ cherries,50g,cherries,heat up and add to bowl % list of \meta{property}|=|\meta{value} pairs. % The following \meta{property} keys can be configured. % -% \NiceDescribeKey{shape} -% {vals={multipage,onepage,tabular,tabularx,longtable,xltabular,tabu,longtabu}, -% init=multipage} -% This property specifies the table's shape. For \meta{value}, the -% package currently supports |multipage| and |onepage| as well as -% |tabular|, |tabularx|, |longtable|, |xltabular|, |tabu|, and -% |longtabu|. In case of |multipage|, the table may span multiple pages -% and on each page, the column header is repeated. In case of |onepage|, -% the table does not split into multiple pages. The remaining values -% use the respective environment for producing the table (see -% \cref{sec:AltTabEnv} for the effect). +% \NiceDescribeKeys{2} +% {backend}{vals={tabular,tabularx,longtable,xltabular,tabu,longtabu}} +% {shape}{vals={multipage,onepage}, init=multipage} +% The |backend| property specifies the table environment to be used for +% producing the table. A set of six environments is currently supported, +% including environments that can span multiple pages and environments +% whose columns can stretch/shrink to fill the available space ("|X|" +% columns). +% The |shape| property abstracts from the concrete environments. +% In case of |multipage|, the table may span multiple pages and +% depending on whether |X|-columns are used or not, an appropriate +% environment is selected. In case of |onepage|, the table does not +% split into multiple pages. +% See \cref{sec:AltTabEnv} for more details on the available shapes and +% backends. +% Only one of |shape| and |backend| can be specified. If both are +% specified, the property that is specified last wins. % % \NiceDescribeKey{width}{vals=\vmeta{dimension}, init=\cmd\linewidth} % This property specifies the width of the table, if the selected -% |shape| supports it (see \cref{sec:AltTabEnv}). +% |shape|/|backend| supports it (see \cref{sec:AltTabEnv}). % % \NiceDescribeKeys{2} % {valign}{vals={t,c,b}, init=\vmeta{empty}} % {halign}{vals={l,c,r}, init=\vmeta{empty}} % These two properties specify the vertical and, respectively, horizontal -% alignment of the table, if the selected |shape| supports it (see +% alignment of the table, if the selected |shape|/|backend| supports it (see % \cref{sec:AltTabEnv}). % % \NiceDescribeKey{showhead}{vals={true,false}, init=true} @@ -733,6 +750,58 @@ cherries,50g,cherries,heat up and add to bowl % \label{fig:TableOptionExamples} % \end{figure} % +% \subsubsection{Table Styles and Resumable Options} +% +% Rather than specifying properties for individual tables or table +% types, \thispackage also supports named \emph{table styles}. +% +% \NiceDescribeKey{style}{vals=\vmeta{list of style names}, init=\vmeta{empty}} +% Through this property of tables or table types, a list of styles can +% be applied to a single table or, respectively, a table type. Each +% style must have been defined with |\kvtNewTableStyle| before. +% +% \NiceDescribeMacro{\kvtNewTableStyle}{\marg{name}\marg{options}} +% This macro declares a new table style with the given \meta{name} and +% defines it to be equivalent to using the given \meta{options}. +% The \meta{name} must not already be defined. +% +% \NiceDescribeMacro{\kvtRenewTableStyle}{\marg{name}\marg{options}} +% This macro re-defines an existing table style \meta{name} with new +% \meta{options}. +% +% The following example demonstrates table styles for an individual +% table. +% +% \begin{LTXexample}[morepreset=\RecipePreset,morekeywords={style,kvtNewTableStyle}] +% \kvtNewTableStyle{plain}{ +% norules,nobg,headformat=\textbf} +% \begin{KeyValTable}[style=plain]{Recipe} +% \Row{amount=150g, ingredient=ice cream, +% step=put into bowl} +% \Row{amount= 50g, ingredient=cherries, +% step=heat up and add to bowl} +% \end{KeyValTable} +% \end{LTXexample} +% +% \NiceNote{The \meta{options} in |\kvtNewTableStyle| can be left empty. +% In this case, the table style does not have any effect on the appearance +% of tables. However, the style can already be used for "tagging" tables +% and table types, while the final options for the style can be +% configured at a later point in time.} +% +% Even without table styles, the appearance of the previous +% |KeyValTable| can be used again through the following option. +% \NiceDescribeKey{resume*}{vals={true,false}, init=false, def=true} +% When set to |true|, this option makes the table use the options from +% the previous |KeyValTable| environment. This option also implies the +% |resume| option (see \vref{opt:resume}). + +% If the previous environment also used |resume*|, then the options of +% its predecessor environment are used, and so forth. +% Note that this means that table options are not accumulated over +% subsequent uses of |resume*|. +% This behavior is the same as in the \pkgname{enumitem} package. +% % % \subsection{Column Appearance} % @@ -1116,11 +1185,11 @@ cherries,50g,cherries,heat up and add to bowl % % \subsection{Captions} % -% There are two ways to add captions to (\pkgname{keyvaltable}-) tables: +% There are two ways to add captions to \pkgname{keyvaltable} tables: % The first way is to enclose the table in a |table| environment. This % is particularly suit for tables that do not span multiple pages, such -% as those produced through the |onepage| shape (or |tabular|, -% |tabularx|, and |tabu| -- see \cref{sec:AltTabEnv}). +% as those produced through the |onepage| shape or the backends +% |tabular|, |tabularx|, and |tabu| (see \cref{sec:AltTabEnv}). % % \begin{LTXexample}[morepreset=\RecipePreset,morekeywords={caption,label,ref}] % \begin{table} @@ -1137,20 +1206,37 @@ cherries,50g,cherries,heat up and add to bowl % \end{LTXexample} % % The second way to add captions is through the |caption| option of -% \pkgname{keyvaltable} tables. This is particularly suit for tables -% that can span multiple pages, such as those produced through the -% |multipage| shape (or |longtable|, |xltabular|, and |longtabu| -- see -% \cref{sec:AltTabEnv}). +% \pkgname{keyvaltable} tables. This option is available for the +% "multipage" shape and, respectively, the table backends |longtable|, +% |xltabular|, and |longtabu| (see \cref{sec:AltTabEnv}). % -% \NiceDescribeKeys{2} +% \NiceDescribeKeys{4} % {caption}{vals=\vmeta{text}, init=\vmeta{none}} +% {caption/lot}{vals=\vmeta{text}, init=\vmeta{none}} +% {caption/alt}{vals=\vmeta{text}, init=\vmeta{none}} % {label}{vals=\vmeta{name}, init=\vmeta{none}} % These options set the caption and, respectively, label of a table. -% The caption is added to the end of the table. +% Through the option |caption/lot|, the caption to be put into the list +% of tables can be specified; if omitted, |caption| is used. +% Through the option |caption/alt|, the alternative caption to be +% displayed on those pages of multipage tables where the main caption is +% not shown; if omitted, no caption is displayed on these pages. +% +% The position of the caption is determined by the following option. +% +% \NiceDescribeKey{captionpos}{vals={t,b}, init=b} +% This option specifies the position of table captions. Value "|t|" +% specifies that captions are at the top of (above) their tables; value +% "|b|" specifies that captions are at the bottom of (below) their +% tables. +% Moreover, in case of "|t|" the main caption is on top of the +% \emph{first} page of a table while in case of "|b|" the main caption +% is at the bottom of the \emph{last} page of a table. +% % The following example shows the options in action. % -% \begin{LTXexample}[morepreset=\RecipePreset,morekeywords={caption,label,ref}] -% \begin{KeyValTable}[shape=multipage, +% \begin{LTXexample}[morepreset=\RecipePreset\setcounter{table}{0},morekeywords={caption,label,ref}] +% \begin{KeyValTable}[captionpos=t, % caption=Cherries++, label=Cherries2]{Recipe} % \Row{amount=150g, ingredient=ice cream, % step=put into bowl} @@ -1163,28 +1249,33 @@ cherries,50g,cherries,heat up and add to bowl % % \subsection{Alternative Table Environments} % \label{sec:AltTabEnv} -% -% Originally, the \thispackage package uses the \pkgname{tabu} package -% and |tabu|, resp. |longtabu| environments for typesetting the actual -% tables. Through the |shape| option of tables, the table environment -% used by \thispackage tables can be changed. -% \Vref{tab:TabEnv} compares -% the possible shapes/environments with regards to +% The \thispackage package internally uses traditional table +% environments, such as |tabular|, for typesetting the actual tables. +% Through the |shape| and |backend| properties of a table or table type, +% the table environment used by for the table or, respectively, table +% type can be changed. +% \Vref{tab:TabEnv} compares the possible shapes/environments with +% regards to % \begin{itemize}[nosep] % \item whether they support tables that span multiple pages, % \item whether they support |caption| and |label| options, % \item whether they support |X|-type (variable-width) columns, -% \item and whether their width can be specified (through the |width| option). +% \item whether their width can be specified (through the |width| +% option), and +% \item whether they support a vertical or horizontal alignment of the +% table to be specified. % \end{itemize} -% Finally, the table also displays the -% package(s) that must be loaded manually when the respective shapes are +% Finally, the table also lists the names of the packages that provide +% the respective environments. The packages for the shapes |onepage| and +% |multipage| are loaded automatically. All other packages must be +% loaded via |\usepackage| when the respective shape or backend shall be % used. % \begin{table}\centering % \newcommand\RHead[1]{\rotatebox{90}{\small\varwidth{\linewidth}#1\endvarwidth}}% % \newcommand\YesNo[1]{\ifstrequal{#1}{yes}{\checkmark}{}}% -% \NewKeyValTable[shape=tabular,headformat=\sffamily\textbf]{ShapeProps}{ +% \NewKeyValTable[backend=tabular,headformat=\sffamily\textbf]{ShapeProps}{ % shape: format=\small\texttt; -% env: format=\small\texttt, head=environment; +% env: format=\small\texttt, head=backend; % multipage: align=c, head=\RHead{multipage}, format=\YesNo; % caption: align=c, head=\RHead{caption}, format=\YesNo; % Xcols: align=c, head=\RHead{\texttt{X} columns}, format=\YesNo; @@ -1199,14 +1290,14 @@ cherries,50g,cherries,heat up and add to bowl % \Row{shape=onepage, env=tabu, multipage=no, caption=no, Xcols=yes, width=yes, align=v, packages=tabu} % \Row{shape=multipage, env=longtabu, multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={tabu, longtable}} % \midrule -% \Row{shape=tabular, env=tabular, multipage=no, caption=no, Xcols=no, width=no, align=v} -% \Row{shape=tabularx, env=tabularx, multipage=no, caption=no, Xcols=yes, width=yes, align=v, packages={tabularx}} -% \Row{shape=longtable, env=longtable, multipage=yes, caption=yes, Xcols=no, width=no, align=h, packages={longtable}} -% \Row{shape=xltabular, env=xltabular, multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={xltabular}} -% \Row{shape=tabu, env=tabu, multipage=no, caption=no, Xcols=yes, width=yes, align=v, packages={tabu}} -% \Row{shape=longtabu, env=longtabu, multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={tabu,longtable}} +% \Row{ env=tabular, multipage=no, caption=no, Xcols=no, width=no, align=v} +% \Row{ env=tabularx, multipage=no, caption=no, Xcols=yes, width=yes, align=v, packages={tabularx}} +% \Row{ env=longtable, multipage=yes, caption=yes, Xcols=no, width=no, align=h, packages={longtable}} +% \Row{ env=xltabular, multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={xltabular}} +% \Row{ env=tabu, multipage=no, caption=no, Xcols=yes, width=yes, align=v, packages={tabu}} +% \Row{ env=longtabu, multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={tabu,longtable}} % \end{KeyValTable} -% \caption{Comparison of table shapes / environments} +% \caption{Comparison of table shapes and backends} % \label{tab:TabEnv} % \end{table} % @@ -1219,11 +1310,11 @@ cherries,50g,cherries,heat up and add to bowl % l: align=l; c: align=c; r: align=r;}[headers={ % l+c+r: head=\textbf{\kvtTableOpt{shape} shape}\\ ::}] % -% \begin{KeyValTable}[shape=tabular]{ShapeNoX} +% \begin{KeyValTable}[backend=tabular]{ShapeNoX} % \Row{l=left, c=center, r=right} % \Row{l=left-2, c=2-center-2, r=2-right} % \end{KeyValTable}\\ -% \begin{KeyValTable}[shape=longtable]{ShapeNoX} +% \begin{KeyValTable}[backend=longtable]{ShapeNoX} % \Row{l=left, c=center, r=right} % \Row{l=left-2, c=2-center-2, r=2-right} % \end{KeyValTable} @@ -1236,24 +1327,24 @@ cherries,50g,cherries,heat up and add to bowl % l: align=l; X: align=X; r: align=r;}[headers={ % l+X+r: head=\textbf{\kvtTableOpt{shape} shape}\\ ::}] % -% \begin{KeyValTable}[shape=tabularx]{ShapeWithX} +% \begin{KeyValTable}[backend=tabularx]{ShapeWithX} % \Row{l=left, X=expandable, r=right} % \Row{l=left-2, X=expandable-2, r=2-right} % \end{KeyValTable}\medskip\\ -% \begin{KeyValTable}[shape=xltabular]{ShapeWithX} +% \begin{KeyValTable}[backend=xltabular]{ShapeWithX} % \Row{l=left, X=expandable, r=right} % \Row{l=left-2, X=expandable-2, r=2-right} % \end{KeyValTable} -% \begin{KeyValTable}[shape=tabu]{ShapeWithX} +% \begin{KeyValTable}[backend=tabu]{ShapeWithX} % \Row{l=left, X=expandable, r=right} % \Row{l=left-2, X=expandable-2, r=2-right} % \end{KeyValTable} -% \begin{KeyValTable}[shape=longtabu]{ShapeWithX} +% \begin{KeyValTable}[backend=longtabu]{ShapeWithX} % \Row{l=left, X=expandable, r=right} % \Row{l=left-2, X=expandable-2, r=2-right} % \end{KeyValTable} % \end{LTXexample} -% \caption{Examples for the shape option} +% \caption{Examples for the backend option} % \label{fig:TableTypes} % \end{figure} % @@ -1492,6 +1583,44 @@ cherries,50g,cherries,heat up and add to bowl % % \subsection{Auxiliary Code} % +% \subsubsection{List Parsing} +% +% \begin{macro}{\kvt@DeclareTrimListParser} +% The |\kvt@DeclareTrimListParser|(|*|)\marg{command}\marg{separator} +% macro is equivalent to \pkgname{etoolbox}'s |\DeclareListParser|, +% except that the \meta{command} is defined such that it will remove +% trailing spaces from list elements before passing the list elements to +% the processing macro (i.e., to |\do| or the user-provided macro). +% Note: With |\DeclareListParser|, \meta{command} is defined to only +% remove leading spaces but not trailing ones. +% This implementation relies on the internals of +% \pkgname{etoolbox} and works with v2.4 of the package, at least. +% \begin{macrocode} +\newcommand\kvt@DeclareTrimListParser{% + \@ifstar{\kvt@DeclareTrimListParser@i{*}} + {\kvt@DeclareTrimListParser@i{}}} +\newcommand\kvt@DeclareTrimListParser@i[3]{% + \DeclareListParser#1{#2}{#3}\expandafter + \patchcmd\csname etb@lst@\expandafter\@gobble\string#2\endcsname + {\etb@listitem}{\kvt@etb@listitem}{} + {\kvt@warn{Failed to patch a command defined by the etoolbox + package, possibly because etoolbox internals have changed. + You might encounter superfluous spaces.}}} +% \end{macrocode} +% The cascade of |\expandafter| below ensures that first the trimming +% macro is expanded and afterwards the outer |\unexpanded| of the +% timming macro's expansion is expanded, which by definition of the +% "noexp" trimming macro fully expands the macro's logic. +% The auxiliary macro below is only for switching the two arguments such +% that the expansion control can be applied to the second argument. +% \begin{macrocode} +\newcommand\kvt@etb@listitem[2]{% + \expandafter\expandafter\expandafter\kvt@etb@listitem@i + \expandafter\expandafter\expandafter{\trim@post@space@noexp{#2}}{#1}} +\newcommand\kvt@etb@listitem@i[2]{\etb@listitem{#2}{#1}} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\kvt@dossvlist} % The |\kvt@dossvlist|\marg{list} macro parses a semicolon-separated % list and runs |\do|\meta{item} for every element of the list. @@ -1503,17 +1632,19 @@ cherries,50g,cherries,heat up and add to bowl % \begin{macro}{\kvt@forpsvlist} % The |\kvt@forpsvlist|\marg{handler}\marg{list} parses a `+'-separated list. % \begin{macrocode} -\DeclareListParser*{\kvt@forpsvlist}{+} +\kvt@DeclareTrimListParser*{\kvt@forpsvlist}{+} % \end{macrocode} % \end{macro} % % \begin{macro}{\kvt@dobrklist} % The |\kvt@dobrklist|\marg{list} parses a `|\\|'-separated list. % \begin{macrocode} -\DeclareListParser{\kvt@dobrklist}{\\} +\kvt@DeclareTrimListParser{\kvt@dobrklist}{\\} % \end{macrocode} % \end{macro} % +% \subsubsection{Errors and Warnings} +% % \begin{macro}{\kvt@error} % \begin{macro}{\kvt@warn} % These macros produce error and warning messages. @@ -1524,6 +1655,8 @@ cherries,50g,cherries,heat up and add to bowl % \end{macro} % \end{macro} % +% \subsubsection{Setting Keys} +% % \begin{macro}{\kvt@setkeys} % \begin{macro}{\kvt@setcmdkeys} % \begin{macro}{\kvt@setcskeys} @@ -1648,8 +1781,11 @@ cherries,50g,cherries,heat up and add to bowl % The following code defines the possible table options. % % \changes{v0.2}{2016/05/21}{Added ``shape'' table option} -% \changes{v2.0}{2019/05/11}{added table options "caption" and "label"} +% \changes{v2.0}{2019/05/11}{Added table options "caption" and "label"} % \changes{v2.1}{2020/01/18}{Added ``valign'' and ``halign'' table options} +% \changes{v2.2}{2020/02/24}{Added ``style'' table option} +% \changes{v2.2}{2020/02/27}{added option "backend"} +% \changes{v2.2}{2020/03/08}{added option "captionpos"} % \begin{macrocode} \define@cmdkey[kvt]{Table}{rowbg}{} \define@cmdkey[kvt]{Table}{headbg}{} @@ -1658,12 +1794,13 @@ cherries,50g,cherries,heat up and add to bowl \define@cmdkey[kvt]{Table}{width}{} \define@boolkey[kvt]{Table}{showhead}{} \define@boolkey[kvt]{Table}{showrules}{} -\define@cmdkey[kvt]{Table}{caption}{} -\define@cmdkey[kvt]{Table}{label}{} +\define@choicekey[kvt]{Table}{captionpos}{t,b} + {\csdef{cmdkvt@Table@captionpos}{#1}} \define@choicekey[kvt]{Table}{valign}{t,c,b} {\csdef{cmdkvt@Table@valign}{#1}} \define@choicekey[kvt]{Table}{halign}{l,c,r} {\csdef{cmdkvt@Table@halign}{#1}} +\define@key[kvt]{Table}{style}{\kvt@UseTableStyles{#1}} % \end{macrocode} % The following options only abbreviate options defined above. % \changes{v2.1}{2020/01/14}{added abbreviation option "norules"} @@ -1676,14 +1813,48 @@ cherries,50g,cherries,heat up and add to bowl \ifbool{#1} {\kvt@setkeys{showrules=false}{Table}} {\kvt@setkeys{showrules=true}{Table}}} +\define@key[kvt]{Table}{backend}{\ifinlist{#1}{\kvt@@tablebackends} + {\csdef{cmdkvt@Table@shape}{#1}} + {\kvt@error{Table backend '#1' not known} + {Check for misspellings in '#1'}}} +\define@key[kvt]{Table}{shape}{\ifinlist{#1}{\kvt@@tableshapes} + {\csdef{cmdkvt@Table@shape}{#1}} + {\ifinlist{#1}{\kvt@@tablebackends} + {\kvt@warn{Using a backend ('#1') as shape is deprecated. + Use the 'backend' option instead.}% + \csdef{cmdkvt@Table@shape}{#1}} + {\kvt@error{Table shape '#1' not known} + {Check for misspellings in '#1'}}}} +% \end{macrocode} +% +% The following table options only apply to individual |KeyValTable| +% environments and cannot be set with |\NewKeyValTable| or |\kvtSet|. +% \changes{v2.2}{2020/02/23}{added table options "resume" and "resume*"} +% \changes{v2.2}{2020/03/12}{added options "caption/lot" and "caption/alt"} +% \begin{macrocode} +\define@cmdkey[kvt]{TableEnv}{caption}{} +\define@cmdkey[kvt]{TableEnv}{caption/lot}{} +\define@cmdkey[kvt]{TableEnv}{caption/alt}{} +\define@cmdkey[kvt]{TableEnv}{label}{} +\define@boolkey[kvt]{TableEnv}{resume}[true]{% + \ifbool{#1}{\ifundef\kvt@@rowcountlast + {\kvt@error{No previous table whose counter could be resumed.} + {Check whether the "resume" is intentional and whether a + previously existing predecessor table has disappeared.}}{}}{}} +\define@boolkey[kvt]{TableEnv}{resume*}[true]{% + \ifbool{#1} % \end{macrocode} -% When adding further |shape| options below, ensure to also add a -% corresponding |\kvt@DefineStdTabEnv| counterpart further below in the -% code. +% The |\kvt@@lastenvopt| macro holds the previous |KeyValTable|'s +% options. Beyond these options, |resume*| automatically also sets +% |resume|. % \begin{macrocode} -\define@choicekey[kvt]{Table}{shape} - {multipage,onepage,tabular,longtable,tabularx,xltabular,tabu,longtabu} - {\csdef{cmdkvt@Table@shape}{#1}} + {\ifundef\kvt@@lastenvopt + {\kvt@error{No previous table whose options could be resume*'d.} + {Check whether the "resume*" is intentional and whether a + previously existing predecessor table has disappeared.}}{}% + \kvt@setcmdkeys\kvt@@lastenvopt{Table}% + \kvt@setkeys{resume}{TableEnv}} + {}} % \end{macrocode} % % @@ -1808,9 +1979,11 @@ cherries,50g,cherries,heat up and add to bowl % % \subsubsection{Option Defaults} % -% The following sets the default values for the options. +% The following sets the default values for the options. This is done +% only after the package is otherwise completely processed, to ensure +% that all features are already defined/registered at that point. % \begin{macrocode} -\kvtSet{% +\AtEndOfPackage{\kvtSet{% rowbg=white..black!10, headbg=black!14, showhead=true, @@ -1819,7 +1992,7 @@ cherries,50g,cherries,heat up and add to bowl headalign=, shape=multipage, width=\linewidth, - caption={}, label={}, + captionpos=b, % \end{macrocode} % Column options % \begin{macrocode} @@ -1838,7 +2011,7 @@ cherries,50g,cherries,heat up and add to bowl ColGroup/align=c, ColGroup/format=\kvtStrutted, HeadCell/align=c, -} +}} % \end{macrocode} % % @@ -1928,6 +2101,10 @@ cherries,50g,cherries,heat up and add to bowl % \meta{tname} and adds the column with the configuration to the table. % \begin{macrocode} \def\kvt@parsecolspec#1#2:#3:#4\@undefined{% +% \end{macrocode} +% Catch syntax errors first. +% \begin{macrocode} + \kvt@checkcolspecempty{#4}{column}{#2}% \def\kvt@@column{#2}% \trim@spaces@in\kvt@@column \expandafter\kvt@parsecolspec@i\expandafter{\kvt@@column}{#1}{#3}} @@ -2066,6 +2243,13 @@ cherries,50g,cherries,heat up and add to bowl % \meta{cgopts}. % \begin{macrocode} \def\kvt@parsecolgroup#1#2:#3:#4\@undefined{% +% \end{macrocode} +% Catch syntax errors first. +% \begin{macrocode} + \kvt@checkcolspecempty{#4}{column group}{#2}% +% \end{macrocode} +% Next, check for a valid \meta{cgname}. +% \begin{macrocode} \ifinlistcs{#2}{kvt@allcolumns@#1}{\kvt@error {Name `#2' cannot be used for a column group in table type `#1', as it is already used for a column} @@ -2116,6 +2300,23 @@ cherries,50g,cherries,heat up and add to bowl % \end{macrocode} % \end{macro} % +% \begin{macro}{\kvt@checkcolspecempty} +% The |\kvt@checkcolspecempty|\marg{empty}\marg{type}\marg{name} +% macro checks the \meta{empty} parameter of a parsing macro for a +% colon-separated key-value pair. +% If \meta{empty} is empty, this corresponds to the valid case that only +% the name of a column group was provided and no properties. If +% \meta{empty} equals ":", then a name and properties were provided. In +% all other cases, superfluous colons were found. +% \begin{macrocode} +\newcommand\kvt@checkcolspecempty[3]{% + \ifstrempty{#1}{}{\ifstrequal{#1}{:}{}{\kvt@error + {Too many ':' in definition of #2 '#3'} + {Check whether there is an accidental ':' that should actually be + a ',' or ';'.}}}} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\kvt@checkcolgroup} % The |\kvt@checkcolgroup|\marg{span-psv}\marg{tname}\marg{cgname} macro % performs some checks on \meta{span-psv} as a specification of which @@ -2245,8 +2446,7 @@ cherries,50g,cherries,heat up and add to bowl % header for the columns is added as header row. % \begin{macrocode} \def\do##1{% - \def\kvt@@tmp{##1}\trim@post@space@in\kvt@@tmp% - \expandafter\ifstrequal\expandafter{\kvt@@tmp}{::} + \ifstrequal{##1}{::} {\appto\kvt@@parseheadrows{% \cseappto{kvt@@custheadrows@#2}{% \csexpandonce{kvt@headings@#2}}}} @@ -2315,7 +2515,7 @@ cherries,50g,cherries,heat up and add to bowl % for the column in |\kvt@@curhd|) and set |\kvt@@lasthd| to the % current one. % \begin{macrocode} - {\ifnum\kvt@@span>\z@ \expandafter\kvt@concludecolumn\fi + {\ifnum\kvt@@span>\z@ \expandafter\kvt@concludehdcolumn\fi \ifdefvoid\kvt@@curhd{}{\ifcsdef{kvt@@hdcelldone@\kvt@@curhd}{% \kvt@error{Header cell `\kvt@@curhd' must consist of only consecutive columns, but it is not}% @@ -2323,7 +2523,7 @@ cherries,50g,cherries,heat up and add to bowl specified in `\string\NewKeyValTable{#1}'}}{}}% \kvt@@span\@ne \let\kvt@@lasthd\kvt@@curhd}% }\dolistcsloop{kvt@displaycols@#1}% - \kvt@concludecolumn + \kvt@concludehdcolumn % \end{macrocode} % Finally, conclude the whole header row and append the row to the % overall list of rows, stored in \cs{kvt@@custheadrows@\meta{tname}}, @@ -2341,8 +2541,31 @@ cherries,50g,cherries,heat up and add to bowl % The |\kvt@rowcolorornot|\marg{color} expands to % |\rowcolor|\marg{color} if \meta{color} is nonempty and does have no % effect if \meta{color} is empty. +% \begin{macro}{\kvt@rowcolorcmdornot} +% The |\kvt@rowcolorcmdornot|\marg{cmd} expands to +% |\rowcolor|\marg{color}, where \meta{color} is the (one-time) +% expansion of \meta{cmd}, if \meta{cmd} is a defined macro whose +% expansion is nonempty; its expansion is empty otherwise. % \begin{macrocode} \newcommand\kvt@rowcolorornot[1]{\ifstrempty{#1}{}{\rowcolor{#1}}} +\newcommand\kvt@rowcolorcmdornot[1]{\ifdefvoid{#1}{}{% + \expandafter\rowcolor\expandafter{#1}}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\kvt@@bodyrow} +% The counter |\kvt@@bodyrow| is used internally in |KeyValTable| +% environments for keeping track of rows for the background-coloring. +% The difference between this counter and |\kvtRow| is that the former +% also counts |uncounted| rows and is unaffected by the |resume| option. +% The counter only counts rows produced by |\Row| and its corresponding +% collecting counterparts. Header rows as well as manually inserted +% rows, including those produced by macros like |\midrule| in a +% |longtable| environment, are not counted (as opposed by the internal +% counter of |\rowcolors|. +% \begin{macrocode} +\newcount\kvt@@bodyrow % \end{macrocode} % \end{macro} % @@ -2354,18 +2577,19 @@ cherries,50g,cherries,heat up and add to bowl % \end{macrocode} % \end{macro} % -% \begin{macro}{\kvt@concludecolumn} -% The |\kvt@concludecolumn| macro appends a cell, potentially spanning +% \begin{macro}{\kvt@concludehdcolumn} +% The |\kvt@concludehdcolumn| macro appends a cell, potentially spanning % multiple columns, to the row under construction (which is in % |\kvt@@tmpgrphd|). % \begin{macrocode} -\newcommand\kvt@concludecolumn{% +\newcommand\kvt@concludehdcolumn{% \kvt@@switchcol \ifdefvoid\kvt@@lasthd{}{% \eappto\kvt@@tmpgrphd{\noexpand\multicolumn {\the\kvt@@span} {\csexpandonce{kvt@@hdcell@align@\kvt@@lasthd}} - {\csexpandonce{kvt@@hdcell@head@\kvt@@lasthd}}}% + {\noexpand\cmdkvt@Table@headformat + {\csexpandonce{kvt@@hdcell@head@\kvt@@lasthd}}}}% % \end{macrocode} % Mark the header cell as already used and concluded, such that another % use of the same header cell can be detected and raise an error. @@ -2382,7 +2606,11 @@ cherries,50g,cherries,heat up and add to bowl % \begin{macrocode} \def\kvt@parsehdcolspec#1#2:#3:#4\@undefined{% % \end{macrocode} -% First link the individual columns of a header cell to the cell. +% Catch syntax errors first. +% \begin{macrocode} + \kvt@checkcolspecempty{#4}{header cell}{#2}% +% \end{macrocode} +% Next, link the individual columns of a header cell to the cell. % In this, ensure that no column is contained in more than one header % cell. % \begin{macrocode} @@ -2492,6 +2720,15 @@ cherries,50g,cherries,heat up and add to bowl % \end{macro} % \begin{macrocode} \kvt@SetOptions{#2}{#1}% +% \end{macrocode} +% Save \meta{options} globally for a potential "|resume*|" option in the +% immediately following |KeyValTable| environment. +% If |resume*| is specified for the current environment, then the +% previous options are not replaced. That is, |resume*| resumes the +% options from the previous non-resuming environment. +% \begin{macrocode} + \ifbool{kvt@TableEnv@resume*}{} + {\gdef\kvt@@lastenvopt{#1}}% \csuse{kvt@StartTable@\cmdkvt@Table@shape}{#2}% }{% \csuse{kvt@EndTable@\cmdkvt@Table@shape}} @@ -2503,224 +2740,18 @@ cherries,50g,cherries,heat up and add to bowl % specific table options in the current environment, based on the % options for table type \meta{tname} and the specific \meta{options}. % \begin{macrocode} -\newcommand\kvt@SetOptions[2]{% - \begingroup\edef\kvt@@do{\endgroup\noexpand% - \kvt@setkeys{\csexpandonce{kvt@options@#1},\unexpanded{#2}}{Table}% - }\kvt@@do} -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Table Environment Code} -% -% \begin{macro}{\kvt@StartTabularlike} -% The -% |\kvt@StartTabularlike|\marg{env}\marg{tname} -% macro begins a table environment for the given table type \meta{tname}. -% The \meta{env} parameter specifies the concrete environment name. -% \begin{macrocode} -\newcommand\kvt@StartTabularlike[2]{% -% \end{macrocode} -% The |\kvt@@recenttable| allows the |\AfterEndEnvironment| hook for -% |KeyValTable| to access the most recent table type. -% \changes{v1.0}{2019/02/18}{Implemented \texttt{showrules} option} -% \begin{macrocode} - \gdef\kvt@@recenttable{#2}% - \metatblAtEnd{#1}{\kvt@@endhook}\let\kvt@@endhook\relax% - \ifbool{kvt@Table@showrules} - {\def\kvt@@rule##1{\csuse{##1rule}}} - {\def\kvt@@rule##1{}}% - \appto\kvt@@endhook{\kvt@@rule{bottom}} -% \end{macrocode} -% The following saves the row counter value for the table type globally, -% such that subsequent tables of the same \meta{tname} can start counting -% from there. -% \begin{macrocode} - \appto\kvt@@endhook{% - \noalign{\csxdef{kvt@rowcount@#2}{\thekvtTypeRow}}}% -% \end{macrocode} -% Adding caption and label, if given, to the end hook. This displays the -% caption solely at the very end of the table. -% \begin{macrocode} - \ifdefempty\cmdkvt@Table@caption{}{% - \metatblHasCaption{#1} - {\appto\kvt@@endhook{\rowcolor{white}% - \caption{\cmdkvt@Table@caption}}% - \ifdefempty\cmdkvt@Table@label{}{% - \appto\kvt@@endhook{\expandafter% - \label\expandafter{\cmdkvt@Table@label}}}} - {\kvt@warn{Caption lost, table environment '#1' - does not support captions.}}}% -% \end{macrocode} -% The following lines perform some checks before the table environment -% is started. -% \begin{macrocode} - \ifdefvoid{\cmdkvt@Table@valign}{}{\metatblCanVAlign{#1}{} - {\undef{\cmdkvt@Table@valign}% - \kvt@warn{Table environment '#1' of table '#2' - does not support the vertical alignment option (valign). - Ignoring the option}}}% - \ifdefvoid{\cmdkvt@Table@halign}{}{\metatblCanHAlign{#1}{} - {\undef{\cmdkvt@Table@halign}% - \kvt@warn{Table environment '#1' of table '#2' - does not support the horizontal alignment option (halign). - Ignoring the option}}}% +\newcommand\kvt@SetOptions[2]{\expandafter + \kvt@SetOptions@i\expandafter{\csname kvt@options@#1\endcsname}{#2}} % \end{macrocode} -% Initializing the row counters. The global counter |kvtTotalRow| needs -% no local initialization. +% The auxiliary macro |\kvt@SetOptions@i|\marg{optcmd}\marg{options} +% first sets the options in the expansion of \meta{optcmd} and then the +% \meta{options}. % \begin{macrocode} - \setcounter{kvtRow}{0}% - \setcounter{kvtTypeRow}{\csuse{kvt@rowcount@#2}}% -% \end{macrocode} -% In |\kvt@@do|, the start code for the environment, including the -% header rows, is gathered, with expansion to fill in all the table -% settings and options. -% \changes{v0.3}{2016/06/05}{Added \texttt{showhead} option} -% \changes{v1.0}{2019/03/09}{Added \texttt{width} option} -% \changes{v2.1}{2020/01/19}{Added \texttt{valign} and \texttt{halign} options} -% \begin{macrocode} - \begingroup\edef\kvt@@do{\endgroup - \metatblIsTabu{#1}{}{\noexpand\kvt@dottedrowcolors - {\ifbool{kvt@Table@showhead} - {\the\numexpr\csuse{kvt@headrowcount@#2}+1\relax} - {1}}% - {\expandonce\cmdkvt@Table@rowbg}}% - \expandafter\noexpand\csname #1\endcsname -% \end{macrocode} -% As background on the positions of the parameters below, here is the -% syntax for beginning the supported environments: -% \begin{itemize}[nosep] -% \item|\begin{tabular}|\oarg{valign}\marg{preamble} -% \item|\begin{tabularx}|\marg{width}\oarg{valign}\marg{preamble} -% \item|\begin{longtable}|\oarg{halign}\marg{preamble} -% \item|\begin{xltabular}|\oarg{halign}\marg{width}\marg{preamble} -% \item|\begin{tabu}| to \meta{width}\oarg{valign}\marg{preamble} -% \item|\begin{longtabu}| to \meta{width}\oarg{halign}\marg{preamble} -% \end{itemize} -% The above cases are covered in the following lines. -% \begin{macrocode} - \ifdefvoid{\cmdkvt@Table@halign}{} - {\metatblIsTabu{#1}{}{[\cmdkvt@Table@halign]}}% - \metatblHasWidth{#1} - {\metatblIsTabu{#1} - {to \expandonce\cmdkvt@Table@width} - {{\expandonce\cmdkvt@Table@width}}} - {}% - \ifdefvoid{\cmdkvt@Table@valign}{}{[\cmdkvt@Table@valign]}% - \ifdefvoid{\cmdkvt@Table@halign}{} - {\metatblIsTabu{#1}{[\cmdkvt@Table@halign]}{}}% - {\csexpandonce{kvt@alignments@#2}}% -% \end{macrocode} -% The remainder below already starts the content of the table -% environment. -% \begin{macrocode} - \noexpand\kvt@@rule{top}% - \ifbool{kvt@Table@showhead} - {\csuse{kvt@headings@#2}\noexpand\kvt@@rule{mid}} - {}% - \metatblIsTabu{#1} - {\noexpand\kvt@taburowcolors{\expandonce\cmdkvt@Table@rowbg}}{}% - \metatblIsLong{#1}{\noexpand\endhead}{}% - }\kvt@@do} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\kvt@dottedrowcolors} -% The |\kvt@dottedrowcolors|\marg{start-row}\marg{colors} sets up row -% colors using the |\rowcolors| macro of \pkgname{xcolor}. -% The \marg{colors} parameter expects arguments of the form -% "\meta{color1}|..|\meta{color2}" (the syntax used for the |rowbg| -% option. The row colors then alternate between \meta{color1} and -% \meta{color2}, starting with \meta{color1} in \meta{start-row}. -% This macro substitutes |\taburowcolors| for non-\pkgname{tabu} -% environments. -% If \meta{colors} is empty, then no row colors are setup. -% \begin{macrocode} -\newcommand\kvt@dottedrowcolors[2]{% - \ifstrempty{#2}{}{\kvt@dottedrowcolors@i{#1}#2\@nil}} -\def\kvt@dottedrowcolors@i#1#2..#3\@nil{% -% \end{macrocode} -% Since |\rowcolors| expects its color arguments to specify the odd and -% even color, we swap arguments depending on the parity of -% \meta{start-row} to ensure \meta{color1} is applied to -% \meta{start-row}. -% \begin{macrocode} - \ifnumodd{#1} - {\rowcolors{#1}{#2}{#3}} - {\rowcolors{#1}{#3}{#2}}} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\kvt@taburowcolors} -% The |\kvt@taburowcolors|\marg{colors} expands to -% |\taburowcolors|\marg{colors} if \meta{colors} is nonempty and does -% have no effect if \meta{color} is empty. -% \begin{macrocode} -\newcommand\kvt@taburowcolors[1]{% - \ifstrempty{#1}{}{\taburowcolors{#1}}} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\kvt@DefineStdTabEnv} -% The |\kvt@DefineStdTabEnv|\oarg{shape}\marg{env} -% macro defines the macros needed for the given \meta{shape} value. -% If \meta{shape} is omitted, \meta{env} (the name of the environment to -% use for the shape) is used as \meta{shape} value. -% -% Note: In the future, the macro could automatically add \meta{option} -% to the list of possible values for the |shape| option. -% \begin{macrocode} -\newcommand\kvt@DefineStdTabEnv{\@dblarg\kvt@DefineStdTabEnv@i} -\newcommand\kvt@DefineStdTabEnv@i[2][]{% - \expandafter\newcommand\csname kvt@StartTable@#1\endcsname[1]{% - \kvt@StartTabularlike{#2}{##1}}% - \csedef{kvt@EndTable@#1}{% - \expandafter\noexpand\csname end#2\endcsname}} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\kvt@DefineDualTabEnv} -% The |\kvt@DefineDualTabEnv|\marg{shape}\marg{nonX-env}\marg{X-env} -% macro defines the macros for the given \meta{shape} name. -% The macros are defined in a way such that the table environment -% \meta{nonX-env} is used for typesetting tables that do not use |X| -% columns and that table environment \meta{X-env} is used for -% typesetting tables that do use |X| columns. -% \begin{macrocode} -\newcommand\kvt@DefineDualTabEnv[3]{% - \expandafter\newcommand\csname kvt@StartTable@#1\endcsname[1]{% - \kvt@ifhasXcolumns{##1} - {\csedef{kvt@EndTable@#1}{% - \expandafter\noexpand\csname end#3\endcsname}% - \kvt@StartTabularlike{#3}{##1}% - }{\csedef{kvt@EndTable@#1}{% - \expandafter\noexpand\csname end#2\endcsname}% - \kvt@StartTabularlike{#2}{##1}}}} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\kvt@ifhasXcolumns} -% The |\kvt@ifhasXcolumns|\marg{tname}\marg{iftrue}\marg{iffalse} -% takes a table type \meta{tname} and checks whether the table type -% contains an "|X|" column. If such a column is contained, the macro -% expands to \meta{iftrue}. Otherwise, it expands to \meta{iffalse}. -% \begin{macrocode} -\newcommand\kvt@ifhasXcolumns[1]{% - \expandafter\expandafter\expandafter\metatbl@ifhasXcolumns - \expandafter\expandafter\expandafter{% - \csname kvt@alignments@#1\endcsname}} +\newcommand\kvt@SetOptions@i[2]{\expandafter + \kvt@setkeys\expandafter{#1,#2}{Table,TableEnv}} % \end{macrocode} % \end{macro} % -% The following lines define the macros for the various table shapes / -% environments. -% \begin{macrocode} -\kvt@DefineStdTabEnv{tabular} -\kvt@DefineStdTabEnv{longtable} -\kvt@DefineStdTabEnv{tabularx} -\kvt@DefineStdTabEnv{xltabular} -\kvt@DefineStdTabEnv{tabu} -\kvt@DefineStdTabEnv{longtabu} -% \end{macrocode} % % \subsubsection{Table Environment Properties} % @@ -2759,6 +2790,7 @@ cherries,50g,cherries,heat up and add to bowl % \begin{macrocode} \newrobustcmd\metatblRegisterEnv[2]{% \edef\metatbl@@envname{#1}% + \csdef{metatbl@@registered@#1}{true}% \setkeys[metatbl]{EnvProp}{#2}} % \end{macrocode} % \end{macro} @@ -2786,29 +2818,24 @@ cherries,50g,cherries,heat up and add to bowl % \end{macrocode} % \end{macro} % +% \begin{macro}{\metatblRegistered} % \begin{macro}{\metatblIsLong} % \begin{macro}{\metatblIsTabu} % \begin{macro}{\metatblHasWidth} % \begin{macro}{\metatblHasCaption} % \begin{macro}{\metatblCanVAlign} % \begin{macro}{\metatblCanHAlign} +% All macros in the following block expect three arguments, +% \marg{env-name}\marg{iftrue}\marg{iffalse}. % The macro -% |\metatblIsLong|\marg{env-name}\marg{iftrue}\marg{iffalse} -% expands to \meta{iftrue} if \meta{env-name} is a "long" table -% environment, i.e., one that can span multiple pages. Otherwise, the -% macro expands to \meta{iffalse}. -% The macro -% |\metatblIsTabu|\marg{env-name}\marg{iftrue}\marg{iffalse} -% expands to \meta{iftrue} if \meta{env-name} is a table environment -% that inherits from |tabu| and expands to \meta{iffalse} otherwise. -% The macro -% |\metatblHasWidth|\marg{env-name}\marg{iftrue}\marg{iffalse} -% expands to \meta{iftrue} if \meta{env-name} is a table environment -% that expects a width argument and expands to \meta{iffalse} otherwise. -% |\metatblHasCaption|\marg{env-name}\marg{iftrue}\marg{iffalse} -% expands to \meta{iftrue} if \meta{env-name} is a table environment -% that supports a caption and expands to \meta{iffalse} otherwise. -% \begin{macrocode} +% |\metatblRegistered| +% expands to \meta{iftrue} if \meta{env-name} has been registered via +% |\metatblRegisterEnv| and expands to \meta{iffalse} otherwise. +% The remaining macros expand to \meta{iftrue}, if the respective +% property has been set to |true| in when \meta{env-name} was registered +% via |\metatblRegisterEnv|, and expand to \meta{iffalse} otherwise. +% \begin{macrocode} +\newcommand\metatblRegistered[1]{\ifcsdef{metatbl@@registered@#1}} \newcommand\metatblIsLong[1]{\ifbool{metatbl@EnvProp@isLong@#1}} \newcommand\metatblIsTabu[1]{\ifbool{metatbl@EnvProp@isTabu@#1}} \newcommand\metatblHasWidth[1]{\ifbool{metatbl@EnvProp@hasWidth@#1}} @@ -2822,6 +2849,7 @@ cherries,50g,cherries,heat up and add to bowl % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\metatblUsePackage} % \begin{macro}{\metatblRequire} @@ -2849,7 +2877,7 @@ cherries,50g,cherries,heat up and add to bowl % \meta{code} for addition at the end of tables based on the % \meta{env-name} environment. % \begin{macrocode} -\newcommand\metatblAtEnd[2]{% #1=env-name, #2=code +\newcommand\metatblAtEnd[2]{% \csname metatbl@EnvProp@atEnd@#1\endcsname{#2}} % \end{macrocode} % \end{macro} @@ -2956,6 +2984,305 @@ cherries,50g,cherries,heat up and add to bowl % \end{macro} % % +% \subsubsection{Table Environment Code} +% +% \begin{macro}{\kvt@StartTabularlike} +% The +% |\kvt@StartTabularlike|\marg{env}\marg{tname} +% macro begins a table environment for the given table type \meta{tname}. +% The \meta{env} parameter specifies the concrete environment name. +% \begin{macrocode} +\newcommand\kvt@StartTabularlike[2]{% +% \end{macrocode} +% \changes{v1.0}{2019/02/18}{Implemented \texttt{showrules} option} +% \begin{macrocode} + \metatblAtEnd{#1}{\kvt@@endhook}% + \let\kvt@@endhook\@empty + \let\kvt@@prehook\@empty + \ifbool{kvt@Table@showrules} + {\def\kvt@@rule##1{\csuse{##1rule}}} + {\def\kvt@@rule##1{}}% + \appto\kvt@@prehook{\kvt@@rule{top}}% + \appto\kvt@@endhook{\kvt@@rule{bottom}}% +% \end{macrocode} +% The following saves the row counter value for the table type globally, +% such that subsequent tables of the same \meta{tname} can start counting +% from there. Moreover, it save the local row counter for the case that +% the next table uses the "|resume|" option. +% \begin{macrocode} + \appto\kvt@@endhook{\noalign{% + \csxdef{kvt@rowcount@#2}{\thekvtTypeRow}% + \csxdef{kvt@@rowcountlast}{\thekvtRow}}}% +% \end{macrocode} +% Adding caption and label. +% \begin{macrocode} + \ifdefvoid\cmdkvt@TableEnv@caption + {\let\kvt@@caption@main\@empty + \let\kvt@@caption@alt\@empty} + {\metatblHasCaption{#1} + {\edef\kvt@@caption@main{% + \csexpandonce{kvt@caption@\cmdkvt@Table@captionpos}% + \ifcsvoid{cmdkvt@TableEnv@caption/lot}{} + {[{\csexpandonce{cmdkvt@TableEnv@caption/lot}}]}% + {\expandonce\cmdkvt@TableEnv@caption + \ifdefvoid\cmdkvt@TableEnv@label{}{% + \noexpand\label{\expandonce\cmdkvt@TableEnv@label}}}% + \noexpand\\}% + \ifcsvoid{cmdkvt@TableEnv@caption/alt} + {\def\kvt@@caption@alt{}} + {\edef\kvt@@caption@alt{% + \csexpandonce{kvt@caption@\cmdkvt@Table@captionpos}[]% + {\csexpandonce{cmdkvt@TableEnv@caption/alt}}% + \noexpand\\}}% + }{\kvt@error + {Caption lost, table backend '#1' does not support captions} + {Consider placing the KeyValTable environment inside a 'table' + environment and use the \string\caption\space macro inside.}}}% + \ifdefstring{\cmdkvt@Table@captionpos}{t} + {\let\kvt@@caption@headmain\kvt@@caption@main\let\kvt@@caption@footmain\@empty + \let\kvt@@caption@headalt\kvt@@caption@alt \let\kvt@@caption@footalt\@empty} + {\let\kvt@@caption@footmain\kvt@@caption@main\let\kvt@@caption@headmain\@empty + \let\kvt@@caption@footalt\kvt@@caption@alt \let\kvt@@caption@headalt\@empty}% + \ifbool{kvt@Table@showhead} + {\eappto\kvt@@prehook{\csuse{kvt@headings@#2}\noexpand\kvt@@rule{mid}}} + {}% +% \end{macrocode} +% The following lines perform some checks before the table environment +% is started. +% \begin{macrocode} + \ifdefvoid{\cmdkvt@Table@valign}{}{\metatblCanVAlign{#1}{} + {\undef{\cmdkvt@Table@valign}% + \kvt@warn{Table environment '#1' of table '#2' + does not support the vertical alignment option (valign). + Ignoring the option}}}% + \ifdefvoid{\cmdkvt@Table@halign}{}{\metatblCanHAlign{#1}{} + {\undef{\cmdkvt@Table@halign}% + \kvt@warn{Table environment '#1' of table '#2' + does not support the horizontal alignment option (halign). + Ignoring the option}}}% +% \end{macrocode} +% Initializing the row counters. The global counter |kvtTotalRow| needs +% no local initialization. +% \begin{macrocode} + \global\kvt@@bodyrow=0\relax + \ifbool{kvt@TableEnv@resume} + {\setcounter{kvtRow}{\csuse{kvt@@rowcountlast}}} + {\setcounter{kvtRow}{0}}% + \setcounter{kvtTypeRow}{\csuse{kvt@rowcount@#2}}% +% \end{macrocode} +% Initialize the background colors for the body rows. +% \begin{macrocode} + \expandafter\kvt@setrowcolors\expandafter{\cmdkvt@Table@rowbg}% +% \end{macrocode} +% In |\kvt@@do|, the start code for the environment, including the +% header rows, is gathered, with expansion to fill in all the table +% settings and options. +% \changes{v0.3}{2016/06/05}{Added \texttt{showhead} option} +% \changes{v1.0}{2019/03/09}{Added \texttt{width} option} +% \changes{v2.1}{2020/01/19}{Added \texttt{valign} and \texttt{halign} options} +% \begin{macrocode} + \begingroup\edef\kvt@@do{\endgroup + \expandafter\noexpand\csname #1\endcsname +% \end{macrocode} +% As background on the positions of the parameters below, here is the +% syntax for beginning the supported environments: +% \begin{itemize}[nosep] +% \item|\begin{tabular}|\oarg{valign}\marg{preamble} +% \item|\begin{tabularx}|\marg{width}\oarg{valign}\marg{preamble} +% \item|\begin{longtable}|\oarg{halign}\marg{preamble} +% \item|\begin{xltabular}|\oarg{halign}\marg{width}\marg{preamble} +% \item|\begin{tabu}| to \meta{width}\oarg{valign}\marg{preamble} +% \item|\begin{longtabu}| to \meta{width}\oarg{halign}\marg{preamble} +% \end{itemize} +% The above cases are covered in the following lines. +% \begin{macrocode} + \ifdefvoid{\cmdkvt@Table@halign}{} + {\metatblIsTabu{#1}{}{[\cmdkvt@Table@halign]}}% + \metatblHasWidth{#1} + {\metatblIsTabu{#1} + {to \expandonce\cmdkvt@Table@width} + {{\expandonce\cmdkvt@Table@width}}} + {}% + \ifdefvoid{\cmdkvt@Table@valign}{}{[\cmdkvt@Table@valign]}% + \ifdefvoid{\cmdkvt@Table@halign}{} + {\metatblIsTabu{#1}{[\cmdkvt@Table@halign]}{}}% + {\csexpandonce{kvt@alignments@#2}}% +% \end{macrocode} +% The remainder below already starts the content of the table +% environment. It also sets the header and footer for multipage tables. +% \begin{macrocode} + \expandonce\kvt@@caption@headmain + \expandonce\kvt@@prehook + \metatblIsLong{#1}{% + \noexpand\endfirsthead + \expandonce\kvt@@caption@headalt + \expandonce\kvt@@prehook + \noexpand\endhead}{}% + \expandonce\kvt@@caption@footmain + \metatblIsLong{#1}{% + \noexpand\endlastfoot + \expandonce\kvt@@caption@footalt + \noexpand\endfoot}{}% + }\kvt@@do} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\kvt@caption@b} +% \begin{macro}{\kvt@caption@t} +% The |\kvt@caption@b| and |\kvt@caption@t| macros behave like +% |\caption| but add extra behavior depending on whether the caption is +% displayed above (|\kvt@caption@t|) or below (|\kvt@caption@b|) the +% table. Currently, |\kvt@caption@b| only fixes the spacing between the +% table and the caption. +% \begin{macrocode} +\newcommand\kvt@caption@t{\caption} +\newcommand\kvt@caption@b{% +% \end{macrocode} +% Fixme: The following |\baselineskip| before the caption compensates +% that \pkgname{longtable} adds a |\baselineskip| below the caption (in +% its macro |\LT@makecaption|) but not above. The \pkgname{ltcaption} +% package replaces the hard-coded |\baselineskip| by |\LTcapskip| but +% also only puts it below the caption. The code below could at least be +% improved to use |\LTcapskip| if it is available. +% \begin{macrocode} + \noalign{\parbox{0pt}{\vskip\baselineskip}}% + \caption} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\kvt@setrowcolors} +% The |\kvt@setrowcolors|\marg{colors} sets up row +% colors using the |\rowcolors| macro of \pkgname{xcolor}. +% The \marg{colors} parameter expects arguments of the form +% "\meta{color1}|..|\meta{color2}" (the syntax used for the |rowbg| +% option. The row colors then alternate between \meta{color1} and +% \meta{color2}, starting with \meta{color1} in the first row. +% If \meta{colors} is empty, then no row colors are setup. +% \begin{macrocode} +\newcommand\kvt@setrowcolors[1]{% + \ifstrempty{#1}{}{\kvt@setrowcolors@i#1\@nil}} +\def\kvt@setrowcolors@i#1..#2\@nil{% + \def\kvt@@bgcolor@odd{#1}% + \def\kvt@@bgcolor@even{#2}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\kvt@userowcolors} +% The |\kvt@userowcolors| macro macro expands to +% |\rowcolor|\marg{color}, where \meta{color} is the background color +% set via |\kvt@setrowcolors| for odd, respectively even rows, based on +% |\kvt@@bodyrow|. +% \begin{macrocode} +\newcommand\kvt@userowcolors{\ifnumodd{\the\kvt@@bodyrow} + {\kvt@rowcolorcmdornot{\kvt@@bgcolor@odd}} + {\kvt@rowcolorcmdornot{\kvt@@bgcolor@even}}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\kvt@RegisterBackend} +% \begin{macro}{\kvt@RegisterShape} +% The |\kvt@RegisterBackend|\marg{env} macro registers the table +% environment \meta{env} as a table backend for use by \thispackage. +% The |\kvt@RegisterShape|\marg{name}\marg{nonX-env}\marg{X-env} +% registers a shape with the given \meta{name} and associates it with +% the environment \meta{nonX-env} when the shape is used for a table +% without |X| columns and with environment \meta{X-env} otherwise. +% \begin{macrocode} +\newcommand\kvt@RegisterBackend[1]{% + \ifinlist{#1}{\kvt@@tablebackends} + {\kvt@error{Backend '#1' already registered} + {Internal error. Check use of \string\kvt@RegisterBackend.}} + {\kvt@CheckMetatblEnv{#1}% + \listadd{\kvt@@tablebackends}{#1}% + \kvt@DefineStdTabEnv{#1}{#1}}} +\newcommand\kvt@RegisterShape[3]{% + \ifinlist{#1}{\kvt@@tableshapes} + {\kvt@error{Shape '#1' already registered} + {Internal error. Check use of \string\kvt@RegisterShape.}} + {\kvt@CheckMetatblEnv{#2}\kvt@CheckMetatblEnv{#3}% + \listadd{\kvt@@tableshapes}{#1}% + \ifstrequal{#2}{#3} + {\kvt@DefineStdTabEnv{#1}{#2}} + {\kvt@DefineDualTabEnv{#1}{#2}{#3}}}} +\newcommand\kvt@CheckMetatblEnv[1]{\metatblRegistered{#1}{} + {\kvt@error{Environment '#1' not supported by keyvaltable} + {Check \string\metatblRegisterEnv\space for how to make it + supported.}}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\kvt@RegisterBackend} +% \begin{macro}{\kvt@RegisterShape} +% The macros |\kvt@@tablebackends| and |\kvt@@tableshapes| hold +% \pkgname{etoolbox} lists of registered names of table backends and +% table shapes. +% \begin{macrocode} +\newcommand\kvt@@tablebackends{} +\newcommand\kvt@@tableshapes{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\kvt@DefineStdTabEnv} +% The |\kvt@DefineStdTabEnv|\marg{shape}\marg{env} +% macro defines the macros needed for the given \meta{shape} value. +% If \meta{shape} is omitted, \meta{env} (the name of the environment to +% use for the shape) is used as \meta{shape} value. +% \begin{macrocode} +\newcommand\kvt@DefineStdTabEnv[2]{% + \csdef{kvt@StartTable@#1}##1{% + \kvt@StartTabularlike{#2}{##1}}% + \csedef{kvt@EndTable@#1}{% + \expandafter\noexpand\csname end#2\endcsname}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\kvt@DefineDualTabEnv} +% The |\kvt@DefineDualTabEnv|\marg{shape}\marg{nonX-env}\marg{X-env} +% macro defines the macros for the given \meta{shape} name. +% The macros are defined in a way such that the table environment +% \meta{nonX-env} is used for typesetting tables that do not use |X| +% columns and that table environment \meta{X-env} is used for +% typesetting tables that do use |X| columns. +% \begin{macrocode} +\newcommand\kvt@DefineDualTabEnv[3]{% + \expandafter\newcommand\csname kvt@StartTable@#1\endcsname[1]{% + \kvt@ifhasXcolumns{##1} + {\csedef{kvt@EndTable@#1}{% + \expandafter\noexpand\csname end#3\endcsname}% + \kvt@StartTabularlike{#3}{##1}% + }{\csedef{kvt@EndTable@#1}{% + \expandafter\noexpand\csname end#2\endcsname}% + \kvt@StartTabularlike{#2}{##1}}}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\kvt@ifhasXcolumns} +% The |\kvt@ifhasXcolumns|\marg{tname}\marg{iftrue}\marg{iffalse} +% takes a table type \meta{tname} and checks whether the table type +% contains an "|X|" column. If such a column is contained, the macro +% expands to \meta{iftrue}. Otherwise, it expands to \meta{iffalse}. +% \begin{macrocode} +\newcommand\kvt@ifhasXcolumns[1]{% + \expandafter\expandafter\expandafter\metatbl@ifhasXcolumns + \expandafter\expandafter\expandafter{% + \csname kvt@alignments@#1\endcsname}} +% \end{macrocode} +% \end{macro} +% +% The following lines define the macros for the various table +% environments. +% \begin{macrocode} +\kvt@RegisterBackend{tabular} +\kvt@RegisterBackend{longtable} +\kvt@RegisterBackend{tabularx} +\kvt@RegisterBackend{xltabular} +\kvt@RegisterBackend{tabu} +\kvt@RegisterBackend{longtabu} +% \end{macrocode} +% +% % \subsubsection{Environment-Independent Parts} % % \begin{macro}{\kvt@AddKeyValRow} @@ -3012,10 +3339,12 @@ cherries,50g,cherries,heat up and add to bowl \ifdefvoid\cmdkvt@Row@above{}{% \eappto\kvt@@row{\noexpand\noalign{\noexpand\vspace{% \expandonce\cmdkvt@Row@above}}}}% - \ifdefvoid\cmdkvt@Row@bg{}{% - \eappto\kvt@@row{\noexpand\rowcolor{\expandonce\cmdkvt@Row@bg}}}% + \appto\kvt@@row{\noalign{\global\advance\kvt@@bodyrow\@ne}}% \ifbool{kvt@Row@uncounted}{}{% \appto\kvt@@row{\noalign{\kvt@stepcounters}}}% + \ifdefvoid\cmdkvt@Row@bg + {\appto\kvt@@row{\kvt@userowcolors}} + {\eappto\kvt@@row{\noexpand\rowcolor{\expandonce\cmdkvt@Row@bg}}}% % \end{macrocode} % If a row alignment is specified, a default |\multicolumn| display is % enabled for the row's cells. @@ -3272,54 +3601,111 @@ cherries,50g,cherries,heat up and add to bowl % \end{macrocode} % \end{macro} % -% \subsubsection{Row Styles} +% \subsubsection{Table and Row Styles} +% +% The following are the user macros. % % \begin{macro}{\kvtNewRowStyle} +% \changes{v2.0}{2019/03/25}{Added the macro} +% \begin{macro}{\kvtRenewRowStyle} +% \changes{v2.0}{2019/03/25}{Added the macro} % The |\kvtNewRowStyle|\marg{name}\marg{row-options} macro declares % \meta{name} as a row style and defines it to be equivalent to % specifying \meta{row-options} directly in the optional argument of % |\Row|. The macro fails if \meta{name} is already declared as a row % style. -% \changes{v2.0}{2019/03/25}{Added the macro} +% The |\kvtRenewRowStyle|\marg{name}\marg{row-options} macro re-defines +% an already existing row style with new \meta{row-options}. % \begin{macrocode} -\newcommand\kvtNewRowStyle[2]{% - \ifcsundef{kvt@@rowstyle@#1} - {\csdef{kvt@@rowstyle@#1}{#2}} - {\kvt@error{Row style '#1' is already defined}{Use - \string\kvtRenewRowStyle\space to change an existing style.}}} +\newcommand\kvtNewRowStyle{\kvt@NewStyle{row}{\kvtRenewRowStyle}} +\newcommand\kvtRenewRowStyle{\kvt@RenewStyle{row}{\kvtNewRowStyle}} % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\kvtRenewRowStyle} -% The |\kvtRenewRowStyle|\marg{name}\marg{row-options} macro re-defines -% an already existing row style with new \meta{row-options}. -% \changes{v2.0}{2019/03/25}{Added the macro} -% \begin{macrocode} -\newcommand\kvtRenewRowStyle[2]{% - \ifcsundef{kvt@@rowstyle@#1} - {\kvt@error{Row style '#1' is not defined} - {Use \string\kvtNewRowStyle\space to define a new row style.}} - {\csdef{kvt@@rowstyle@#1}{#2}}} +% \begin{macro}{\kvtNewTableStyle} +% \changes{v2.2}{2020/02/24}{Added the macro} +% \begin{macro}{\kvtRenewTableStyle} +% \changes{v2.2}{2020/02/24}{Added the macro} +% The |\kvtNewTableStyle|\marg{name}\marg{options} macro declares +% \meta{name} as a table style and defines it to be equivalent to +% specifying \meta{options} directly in the optional argument of +% a |KeyValTable| environment or of a |\NewKeyValTable|. The macro fails +% if \meta{name} is already declared as a table style. +% The |\kvtRenewTableStyle|\marg{name}\marg{options} macro re-defines +% an already existing table style with new \meta{options}. +% \begin{macrocode} +\newcommand\kvtNewTableStyle{\kvt@NewStyle{table}{\kvtRenewTableStyle}} +\newcommand\kvtRenewTableStyle{\kvt@RenewStyle{table}{\kvtNewTableStyle}} % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\kvt@UseRowStyle} -% The |\kvt@UseRowStyle|\marg{style} macro sets the row keys based on -% the \meta{row-options} stored for the given \meta{style}. -% \begin{macrocode} -\newcommand\kvt@UseRowStyle[1]{% - \ifcsundef{kvt@@rowstyle@#1} - {\kvt@error{Row style '#1' is not defined} - {Use \string\kvtNewRowStyle\space to define a new row style.}} - {\kvt@setcskeys{kvt@@rowstyle@#1}{Row}}} +% The following are the internal macros that the style code shares. +% +% \begin{macro}{\kvt@NewStyle} +% \begin{macro}{\kvt@RenewStyle} +% The |\kvt@NewStyle|\marg{type}\marg{renewcmd}\marg{name}\marg{options} +% macro defines a new style, \meta{name}, for \meta{type} (|table| or +% |row|) to correspond to \meta{options}. +% Analogously, +% |\kvt@RenewStyle|\marg{type}\marg{newcmd}\marg{name}\marg{options} +% macro re-defines a style. +% \begin{macrocode} +\newcommand\kvt@NewStyle[4]{% + \ifcsundef{kvt@@#1style@#3} + {\csdef{kvt@@#1style@#3}{#4}} + {\kvt@error{The #1 style '#3' is already defined}{Use + \string#2\space to change an existing style.}}} +\newcommand\kvt@RenewStyle[4]{% + \ifcsundef{kvt@@#1style@#3} + {\kvt@error{A #1 style '#3' is not defined} + {Use \string#2\space to define a new #1 style.}} + {\csdef{kvt@@#1style@#3}{#4}}} % \end{macrocode} % \end{macro} +% \end{macro} +% % \begin{macro}{\kvt@UseRowStyles} -% The |\kvt@UseRowStyle|\marg{styles} macro sets the row keys based on -% the \meta{row-options} for all styles in the comma-separated list -% \meta{styles}. +% \begin{macro}{\kvt@UseTableStyles} +% \changes{v2.2}{2020/02/24}{Added the macro} +% The |\kvt@UseRowStyles|\marg{styles} and +% |\kvt@UseTableStyles|\marg{styles} macros set the keys for the given, +% comma-separated list of \meta{styles}. % \begin{macrocode} \newcommand\kvt@UseRowStyles[1]{% + \kvt@UseStyles{row}{Row}{\kvt@NewRowStyle}{#1}} +\newcommand\kvt@UseTableStyles[1]{% + \kvt@UseStyles{table}{Table}{\kvt@NewTableStyle}{#1}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\kvt@UseStyle} +% The |\kvt@UseStyle|\marg{type}\marg{fam}\marg{newcmd}\marg{style} +% macro sets the keys for type \meta{type} based on the \meta{options} +% stored for the given \meta{style}. +% The \meta{fam} identifies the +% \pkgname{xkeyval} family for \meta{type} and \meta{newcmd} is the +% macro for defining new \meta{type} styles. +% \begin{macrocode} +\newcommand\kvt@UseStyle[4]{% + \ifcsundef{kvt@@#1style@#4} + {\kvt@error{A #1 style '#4' is not defined} + {Use \string#3\space to define a new #1 style.}} + {\kvt@setcskeys{kvt@@#1style@#4}{#2}}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\kvt@UseStyles} +% The |\kvt@UseStyles|\marg{type}\marg{fam}\marg{newcmd}\marg{styles} +% macro sets the \meta{type} keys based on the \meta{options} for all +% styles in the comma-separated list \meta{styles}. +% The \meta{fam} identifies the +% \pkgname{xkeyval} family for \meta{type} and \meta{newcmd} is the +% macro for defining new \meta{type} styles. +% \begin{macrocode} +\newcommand\kvt@UseStyles[4]{% % \end{macrocode} % We use |\kvt@xkv@disablepreset| to eliminate undesired effects that % would otherwise be caused by preset values for keys. @@ -3334,8 +3720,8 @@ cherries,50g,cherries,heat up and add to bowl % |\setkeys| would then again employ the presets for |Row| (e.g., from a % |\kvtSet{Row/bg=blue}|) and undesirably overwrite the |bg=red|. % \begin{macrocode} - \kvt@xkv@disablepreset[kvt]{Row}{% - \forcsvlist\kvt@UseRowStyle{#1}}} + \kvt@xkv@disablepreset[kvt]{#2}{% + \forcsvlist{\kvt@UseStyle{#1}{#2}{#3}}{#4}}} % \end{macrocode} % \end{macro} % @@ -3737,12 +4123,12 @@ cherries,50g,cherries,heat up and add to bowl % \begin{macrocode} \kvt@IfVersion{<}{2.0}{% \metatblRequire{tabu,longtabu} - \kvt@DefineStdTabEnv[onepage]{tabu} - \kvt@DefineStdTabEnv[multipage]{longtabu} + \kvt@RegisterShape{onepage}{tabu}{tabu} + \kvt@RegisterShape{multipage}{longtabu}{longtabu} }{% \metatblRequire{tabularx,longtable,xltabular} - \kvt@DefineDualTabEnv{onepage}{tabular}{tabularx} - \kvt@DefineDualTabEnv{multipage}{longtable}{xltabular} + \kvt@RegisterShape{onepage}{tabular}{tabularx} + \kvt@RegisterShape{multipage}{longtable}{xltabular} } % \end{macrocode} % -- cgit v1.2.3