summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-02-21 22:54:25 +0000
committerKarl Berry <karl@freefriends.org>2020-02-21 22:54:25 +0000
commit8c001b9ec06abf4a378fbe9fd81bde3e5343d6c1 (patch)
tree38b64b09487f20a4b4235b8222f92114e9da3af6 /Master/texmf-dist/source
parentee6d6cebcf0c8b850920001a6420f42c156050b0 (diff)
keyvaltable (21feb20)
git-svn-id: svn://tug.org/texlive/trunk@53861 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r--Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx705
-rw-r--r--Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins4
2 files changed, 512 insertions, 197 deletions
diff --git a/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx b/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx
index 6dea8208410..813904fb233 100644
--- a/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx
+++ b/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 2016-2019 by Richard Grewe <r-g+tex@posteo.net>
+% Copyright (C) 2016-2020 by Richard Grewe <r-g+tex@posteo.net>
% -------------------------------------------------------
%
% This file may be distributed and/or modified under the
@@ -22,12 +22,12 @@
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{keyvaltable}
%<*package>
- [2019/05/11 v2.0 Package for filling tables using key-value lists]
+ [2020/02/19 v2.1 Package for filling tables using key-value lists]
%</package>
%
%<*driver>
\documentclass[svgnames]{ltxdoc}
-\usepackage{rgltxdoc}[2019/05/04 v1.2]
+\usepackage{rgltxdoc}[2019/12/21 v1.3]
\usepackage{etoc}
\usepackage{amssymb}% \checkmark
\EnableCrossrefs
@@ -624,15 +624,30 @@ cherries,50g,cherries,heat up and add to bowl
% This property specifies the width of the table, if the selected
% |shape| 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
+% \cref{sec:AltTabEnv}).
+%
% \NiceDescribeKey{showhead}{vals={true,false}, init=true}
% This property specifies whether the header row shall be shown. The
% \meta{value} must be a Boolean (i.e., |true| or |false|), where |true|
% specifies that the header row is shown and |false| specifies that the
% header row is not shown.
%
-% \NiceDescribeKey{showrules}{vals={true,false}, init=true}
-% This property specifies whether top and bottom rules as well
-% as a rule below the header row are drawn (|true|) or not (|false|).
+% \NiceDescribeKeys{2}
+% {showrules}{vals={true,false}, init=true}
+% {norules}{vals={true,false}, init=false, def=true}
+% The |showrules| property specifies whether top and bottom rules as
+% well as a rule below the header row are drawn (|true|) or not
+% (|false|). The |norules| property serves the same purpose, but the
+% value |true| hides the rules and the value |false| causes the rules to
+% be drawn.
+% Note that both properties only affect the rules that \thispackage
+% produces automatically; rules manually added, e.g., via |\hline| or
+% |\midrule| are not affected by the properties.
%
% \NiceDescribeKey{headalign}{vals={\vmeta{empty} or \vmeta{coltype}}, init=\vmeta{empty}}
% This property specifies the alignment for header cells. If left
@@ -676,34 +691,42 @@ cherries,50g,cherries,heat up and add to bowl
% \vref{fig:TableOptionExamples} demonstrates the \meta{options} in
% examples.
% \begin{figure}
-% \begin{LTXexample}[morekeywords={shape,showhead,rowbg}]
-% \NewKeyValTable[shape=onepage,
-% showhead=false,
+% \begin{LTXexample}[morekeywords={showhead,rowbg}]
+% \kvtSet{format=\texttt}
+% \NewKeyValTable[showhead=false,
% rowbg=blue!10..blue!15,
-% ]{TabOptions}{
-% opt: align=l, format=\texttt;
-% val: align=l, format=\texttt;}
-% \begin{table}\centering
+% ]{TabOptions}{opt; val}
% \begin{KeyValTable}{TabOptions}
-% \Row{opt=shape, val=onepage}
-% \Row{opt=showhead, val=false}
-% \Row{opt=rowbg, val=blue!10..blue!15}
+% \Row{opt=showhead, val=false}
+% \Row{opt=rowbg, val=blue!10..blue!15}
% \end{KeyValTable}
-% \caption{table options demo}
-% \end{table}
% \end{LTXexample}
-% \begin{LTXexample}[morekeywords={showrules,headbg,headalign,headformat,norowbg}]
+% \begin{LTXexample}[morepreset={\kvtSet{format=\texttt}},morekeywords={showrules,headbg,headalign,headformat,halign,norowbg}]
% \NewKeyValTable[showrules=false,headbg=blue!25,
-% headalign=c,headformat=\textbf,norowbg
-% ]{TabOptions2}{
-% opt: align=l, format=\texttt;
-% val: align=l, format=\texttt;}
+% headalign=c,headformat=\textbf,norowbg,
+% halign=r,
+% ]{TabOptions2}{opt; val}
% \begin{KeyValTable}{TabOptions2}
-% \Row{opt=showrules, val=false}
-% \Row{opt=headbg, val=blue!25}
-% \Row{opt=headalign, val=c}
-% \Row{opt=headformat, val=\string\textbf}
-% \Row{opt=norowbg, val=true}
+% \Row{opt=showrules, val=false}
+% \Row{opt=headbg, val=blue!25}
+% \Row{opt=headalign, val=c}
+% \Row{opt=headformat, val=\string\textbf}
+% \Row{opt=norowbg, val=true}
+% \Row{opt=halign, val=r}
+% \end{KeyValTable}
+% \end{LTXexample}
+% \begin{LTXexample}[morepreset={\kvtSet{format=\texttt}},morekeywords={nobg,norules,valign,shape,width}]
+% \NewKeyValTable[valign=t,nobg,norules,
+% shape=onepage,width=3cm,headformat=\textbf,
+% ]{TabOptions3}{opt: align=X;}
+% \begin{KeyValTable}{TabOptions3}
+% \Row{opt=nobg}
+% \Row{opt=norules}
+% \end{KeyValTable}
+% \begin{KeyValTable}{TabOptions3}
+% \Row{opt={shape=onepage}}
+% \Row{opt={valign=t}}
+% \Row{opt={width=3cm}}
% \end{KeyValTable}
% \end{LTXexample}
% \caption{Examples for table options}
@@ -739,11 +762,19 @@ cherries,50g,cherries,heat up and add to bowl
% options must be a comma-separated list of key-value pairs.
% The following options are supported.
%
-% \NiceDescribeKey{hidden}{vals={true,false}, init=false}
+% \NiceDescribeKey{hidden}{vals={true,false}, init=false, def=true}
% This property specifies whether the row shall be hidden (|true|) or
% not (|false|). If only |hidden| is used without a value, this is
% equivalent to |hidden=true|.
%
+% \NiceDescribeKey{align}{vals={\vmeta{empty} or \vmeta{coltype}}, init=\vmeta{empty}}
+% This property specifies the alignment of the cells in the row.
+% If this property is not specified, the respective columns' alignment
+% is used. The alignment applies to normal cells as well as to cells
+% in column groups.\footnote{Note that the alignment does not override
+% the alignment specified in any \cs{multicolumn} if it is assigned to
+% a cell in the row.}
+%
% \NiceDescribeKey{bg}{vals=\vmeta{color}, init=\vmeta{empty}}
% This property specifies the background color for the particular row.
% If this option is not specified (or set to an empty value
@@ -751,6 +782,27 @@ cherries,50g,cherries,heat up and add to bowl
% option of the table.
%
% \NiceDescribeKeys{3}
+% {format}{vals=\vmeta{single argument macro}, init=\vmeta{"identity"}}
+% {format*}{vals=\vmeta{single argument macro}, init=\vmeta{"identity"}}
+% {format!}{vals=\vmeta{single argument macro}, init=\vmeta{none}}
+% These properties specify formatting for all cells of the particular
+% row. The difference between the three properties is how they
+% interact with the column formats of the respective cells in the row.
+% The |format| property is applied to the cell content \emph{before}
+% the column format, and the |format*| property is applied
+% \emph{after} the column format.
+% The |format!| property overrides any column formats in the
+% respective row and also renders the |format| and |format*|
+% properties ineffective.
+%
+% \NiceDescribeKey{headlike}{vals={true,false}, init=false, def=true}
+% This property, when used without a value or with value |true|,
+% specifies that the row shall be formatted like a header row.
+% Concretely, the alignment, background color, and format of the row's
+% cells is then set to the values of the table's |headalign|,
+% |headbg|, and |headformat| properties.
+%
+% \NiceDescribeKeys{3}
% {above}{vals=\vmeta{dimension}, init=\vmeta{empty}}
% {below}{vals=\vmeta{dimension}, init=\vmeta{empty}}
% {around}{vals=\vmeta{dimension}, init=\vmeta{empty}}
@@ -765,8 +817,8 @@ cherries,50g,cherries,heat up and add to bowl
% |\kvtSet{Row/|\meta{option}|=|\meta{value}|}| (see also
% \cref{sec:kvtSet}).}
%
-% The following example demonstrates the options.
-% \begin{LTXexample}[morepreset=\RecipePreset,morekeywords={hidden,above,bg}]
+% The following example demonstrates some of the options.
+% \begin{LTXexample}[morepreset=\RecipePreset,morekeywords={hidden,above,bg,format}]
% \begin{KeyValTable}{Recipe}
% \Row{amount=150g, ingredient=ice cream,
% step=put into bowl}
@@ -774,7 +826,7 @@ cherries,50g,cherries,heat up and add to bowl
% step=heat up and add to bowl}
% \Row[hidden]{amount=25g, ingredient=cream,
% step=decorate on top}
-% \Row[above=1ex,bg=Gold]{
+% \Row[above=1ex,bg=Gold,format=\textit]{
% step=serve with a smile}
% \end{KeyValTable}
% \end{LTXexample}
@@ -842,7 +894,7 @@ cherries,50g,cherries,heat up and add to bowl
%
% Individual cells can be formatted by using the respective
% \hologo{LaTeX} code directly in the value of the cell.
-% One can disabled column's configured |format| for the cell by
+% One can disable the column's configured |format| for the cell by
% using the starred column name in |\Row|.
% The following example demonstrates starred column names.
%
@@ -1115,44 +1167,50 @@ cherries,50g,cherries,heat up and add to bowl
% 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 whether they support
-% tables that span multiple pages, whether they support |X|-type
-% (variable-width) columns, and whether their width can be specified
-% (through the |width| option). Finally, the table also displays the
+% used by \thispackage tables 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).
+% \end{itemize}
+% Finally, the table also displays the
% package(s) that must be loaded manually when the respective shapes are
% used.
-% Examples can be found in \vref{fig:TableTypes}.
% \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}{
% shape: format=\small\texttt;
% env: format=\small\texttt, head=environment;
-% multipage: align=c, head=\RHead{multi-\\[-3pt] page}, format=\YesNo;
+% 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;
% width: align=c, head=\RHead{width}, format=\YesNo;
+% align: align=c, head=\RHead{align}, format=\textsf;
% packages: align=l, format=\pkgnames}%
% \begin{KeyValTable}{ShapeProps}
-% \Row{shape=onepage, env=tabular/tabularx, multipage=no, caption=no, Xcols=yes, width=yes, packages=tabularx}
-% \Row{shape=multipage, env=longtabu/xltabular, multipage=yes, caption=yes, Xcols=yes, width=yes, packages={longtable, xltabular}}
+% \Row{shape=onepage, env=tabular/tabularx, multipage=no, caption=no, Xcols=yes, width=yes, align=v, packages=tabularx}
+% \Row{shape=multipage, env=longtable/xltabular, multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={longtable, xltabular}}
% \midrule
% \noalign{\footnotesize with package option |compat=1.0|:}
-% \Row{shape=onepage, env=tabu, multipage=no, caption=no, Xcols=yes, width=yes, packages=tabu}
-% \Row{shape=multipage, env=longtabu, multipage=yes, caption=yes, Xcols=yes, width=yes, packages={tabu, longtable}}
+% \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}
-% \Row{shape=tabularx, env=tabularx, multipage=no, caption=no, Xcols=yes, width=yes, packages={tabularx}}
-% \Row{shape=longtable, env=longtable, multipage=yes, caption=yes, Xcols=no, width=no, packages={longtable}}
-% \Row{shape=xltabular, env=xltabular, multipage=yes, caption=yes, Xcols=yes, width=yes, packages={xltabular}}
-% \Row{shape=tabu, env=tabu, multipage=no, caption=no, Xcols=yes, width=yes, packages={tabu}}
-% \Row{shape=longtabu, env=longtabu, multipage=yes, caption=yes, Xcols=yes, width=yes, packages={tabu,longtable}}
+% \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}}
% \end{KeyValTable}
% \caption{Comparison of table shapes / environments}
% \label{tab:TabEnv}
% \end{table}
%
+% Examples can be found in \vref{fig:TableTypes}.
% \begin{figure}[p]
% \begin{LTXexample}[width=0.475\hsize,
% morekeywords={tabular,longtable}]
@@ -1160,6 +1218,7 @@ cherries,50g,cherries,heat up and add to bowl
% id: align=l, default=\thekvtTypeRow;
% l: align=l; c: align=c; r: align=r;}[headers={
% l+c+r: head=\textbf{\kvtTableOpt{shape} shape}\\ ::}]
+%
% \begin{KeyValTable}[shape=tabular]{ShapeNoX}
% \Row{l=left, c=center, r=right}
% \Row{l=left-2, c=2-center-2, r=2-right}
@@ -1169,12 +1228,14 @@ cherries,50g,cherries,heat up and add to bowl
% \Row{l=left-2, c=2-center-2, r=2-right}
% \end{KeyValTable}
% \end{LTXexample}
+%
% \begin{LTXexample}[width=0.475\hsize,
% morekeywords={tabularx,xltabular,tabu,longtabu}]
% \NewKeyValTable[showrules=false]{ShapeWithX}{
% id: align=l, default=\thekvtTypeRow;
% l: align=l; X: align=X; r: align=r;}[headers={
% l+X+r: head=\textbf{\kvtTableOpt{shape} shape}\\ ::}]
+%
% \begin{KeyValTable}[shape=tabularx]{ShapeWithX}
% \Row{l=left, X=expandable, r=right}
% \Row{l=left-2, X=expandable-2, r=2-right}
@@ -1196,7 +1257,10 @@ cherries,50g,cherries,heat up and add to bowl
% \label{fig:TableTypes}
% \end{figure}
%
-%
+% ^^M The following \clearpage is a hack! It fixes the page breaking
+% ^^M that is messed up because of the longtable/xltabular/longtabu
+% ^^M in fig:TableTypes.
+% \clearpage
% \section{Use with Other Packages}
%
% \subsection{Named References (\pkgname{cleveref})}\label{sec:package-cleveref}
@@ -1481,11 +1545,21 @@ cherries,50g,cherries,heat up and add to bowl
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\kvt@setkeys@nopresets}
+% The
+% |\kvt@setkeys@nopresets|\marg{keys}\marg{family} macro
+% expands to a |\kvt@setkeys| in which no presets are active.
+% \begin{macrocode}
+\newcommand\kvt@setkeys@nopresets[2]{%
+ \kvt@xkv@disablepreset[kvt]{#2}{\kvt@setkeys{#1}{#2}}}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\kvt@colsetkeys}
% \begin{macro}{\kvt@colsetcmdkeys}
% \begin{macro}{\kvt@colsetcskeys}
% The |\kvt@colsetkeys|\marg{fam}\marg{keys} macro abbreviates
-% |\setkeys[KeyValTable]|\meta{fam}\meta{keys}.
+% |\setkeys[KeyValTable]| with the same arguments.
% The |\kvt@colsetcmdkeys|\marg{famcmd}\marg{keys} and
% |\kvt@colsetcskeys|\marg{famcs}\marg{keys} abbreviate the cases where
% \meta{fam} is stored in macro \meta{famcmd} or, respectively,
@@ -1575,13 +1649,10 @@ cherries,50g,cherries,heat up and add to bowl
%
% \changes{v0.2}{2016/05/21}{Added ``shape'' table option}
% \changes{v2.0}{2019/05/11}{added table options "caption" and "label"}
+% \changes{v2.1}{2020/01/18}{Added ``valign'' and ``halign'' table options}
% \begin{macrocode}
\define@cmdkey[kvt]{Table}{rowbg}{}
\define@cmdkey[kvt]{Table}{headbg}{}
-\define@boolkey[kvt]{Table}{norowbg}[true]{%
- \kvt@setkeys{rowbg={}}{Table}}
-\define@key[kvt]{Table}{nobg}[true]{%
- \kvt@setkeys{rowbg={},headbg={}}{Table}}
\define@cmdkey[kvt]{Table}{headalign}{}
\define@cmdkey[kvt]{Table}{headformat}{}
\define@cmdkey[kvt]{Table}{width}{}
@@ -1589,7 +1660,22 @@ cherries,50g,cherries,heat up and add to bowl
\define@boolkey[kvt]{Table}{showrules}{}
\define@cmdkey[kvt]{Table}{caption}{}
\define@cmdkey[kvt]{Table}{label}{}
-
+\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}}
+% \end{macrocode}
+% The following options only abbreviate options defined above.
+% \changes{v2.1}{2020/01/14}{added abbreviation option "norules"}
+% \begin{macrocode}
+\define@boolkey[kvt]{Table}{norowbg}[true]{%
+ \kvt@setkeys{rowbg={}}{Table}}
+\define@boolkey[kvt]{Table}{nobg}[true]{%
+ \kvt@setkeys{rowbg={},headbg={}}{Table}}
+\define@boolkey[kvt]{Table}{norules}[true]{%
+ \ifbool{#1}
+ {\kvt@setkeys{showrules=false}{Table}}
+ {\kvt@setkeys{showrules=true}{Table}}}
% \end{macrocode}
% When adding further |shape| options below, ensure to also add a
% corresponding |\kvt@DefineStdTabEnv| counterpart further below in the
@@ -1627,9 +1713,9 @@ cherries,50g,cherries,heat up and add to bowl
%
% \begin{macro}{\kvt@def@globalopt}
% \begin{macro}{\kvt@def@globalopts}
-% The |\kvt@def@globalopt|\marg{family}{key} macro creates an option key
-% "\meta{family}/\meta{key}" for |\kvtSet| that set the preset value for
-% the \meta{key} in \meta{family}.
+% The |\kvt@def@globalopt|\marg{family}{key} macro creates the option key
+% "\meta{family}/\meta{key}". When used in |\kvtSet|, this key sets the preset
+% value for the \meta{key} in \meta{family}.
% The |\kvt@def@globalopts|\marg{family}{keys} macro extends the former
% macro to comma-separated lists of \meta{keys} within a single
% \meta{family}.
@@ -1644,20 +1730,20 @@ cherries,50g,cherries,heat up and add to bowl
%
% \begin{macrocode}
\define@cmdkey[kvt]{ColGroup}{span}{%
- \csdef{kvt@colgrp@span@\kvt@@colgrp}{#1}}
+ \csgdef{kvt@colgrp@span@\kvt@@tname @\kvt@@colgrp}{#1}}
\define@cmdkey[kvt]{ColGroup}{align}{%
- \csdef{kvt@colgrp@align@\kvt@@colgrp}{#1}}
+ \csgdef{kvt@colgrp@align@\kvt@@tname @\kvt@@colgrp}{#1}}
\define@cmdkey[kvt]{ColGroup}{format}{%
- \csdef{kvt@colgrp@format@\kvt@@colgrp}{#1}}
+ \csgdef{kvt@colgrp@format@\kvt@@tname @\kvt@@colgrp}{#1}}
\kvt@def@globalopts{ColGroup}{align, format}
% \end{macrocode}
%
%
% \subsubsection{Layout Customization Options}
%
-% The following defines the options for the second optional argument to
-% |\NewKeyValTable|. These options intentionally do not support setting
-% global defaults via |\kvtSet|.
+% The following defines the option keys for the second optional argument
+% to |\NewKeyValTable|. These options intentionally do not support
+% setting global defaults via |\kvtSet|.
% \begin{macrocode}
\define@cmdkey[kvt]{Layout}{headers}{%
\expandafter\kvt@parseheadrows\expandafter{\kvt@@tname}{#1}}
@@ -1683,17 +1769,37 @@ cherries,50g,cherries,heat up and add to bowl
% \changes{v2.0}{2019/05/11}{added row options "nobg" and "norowbg"}
% \changes{v2.0}{2019/05/11}{added row option "style"}
% \changes{v2.0}{2019/05/11}{added row option "uncounted"}
+% \changes{v2.1}{2020/02/15}{added row options "format", "format*",
+% "format!", "align", and "headlike"}
% \begin{macrocode}
\define@cmdkey[kvt]{Row}{bg}{}
+\define@cmdkey[kvt]{Row}{format}{}
+\define@cmdkey[kvt]{Row}{format*}{}
+\define@cmdkey[kvt]{Row}{format!}{}
+\define@cmdkey[kvt]{Row}{align}{}
+\define@boolkey[kvt]{Row}{headlike}[true]{%
+ \ifbool{#1}{%
+ \edef\kvt@@opts{%
+ bg={\expandonce\cmdkvt@Table@headbg},%
+ format!={\expandonce\cmdkvt@Table@headformat},%
+ align={\expandonce\cmdkvt@Table@headalign}}%
+ \expandafter\kvt@setkeys@nopresets\expandafter{\kvt@@opts}{Row}%
+ }{}}
\define@boolkey[kvt]{Row}{hidden}[true]{}
\define@cmdkey[kvt]{Row}{below}{}
\define@cmdkey[kvt]{Row}{above}{}
\define@key[kvt]{Row}{around}{%
- \kvt@setkeys{below={#1},above={#1}}{Row}}
+ \kvt@setkeys@nopresets{below={#1},above={#1}}{Row}}
\define@key[kvt]{Row}{style}{\kvt@UseRowStyles{#1}}
\define@boolkey[kvt]{Row}{uncounted}[true]{}
\define@boolkey[kvt]{Row}{expand}[true]{}
\define@boolkey[kvt]{Row}{expandonce}[true]{}
+% \end{macrocode}
+% The following specifies which row options can be specified globally,
+% i.e. via a |Row/option| key. Not contained in the list are the
+% |format| options and the |headlike| option, as setting these globally
+% appears strange.
+% \begin{macrocode}
\kvt@def@globalopts{Row}{
bg,hidden,below,above,around,style,uncounted,
expand,expandonce}
@@ -1782,16 +1888,14 @@ cherries,50g,cherries,heat up and add to bowl
% tables is that this code would prevent |\multicolumn| to be used in
% the first column.
% \changes{v1.0}{2019/02/03}{Added zero-width column for \cs{multicolumn}}
-% Fixme: Ideally, the whole extra column should be removed through
-% sufficient use of |\noalign| in headers and rows, such that even the
-% presence of |\multicolumn| does not produce errors.
+% \changes{v2.1}{2020/02/16}{Removed zero-width column again}
% \begin{macrocode}
- \csedef{kvt@alignments@#2}{p{0pt}\expandonce\kvt@HackIntercolSpace}%
+ \csdef{kvt@alignments@#2}{}%
\csdef{kvt@allcolumns@#2}{}%
\csdef{kvt@displaycols@#2}{}%
\csdef{kvt@rowcount@#2}{0}%
\csdef{kvt@rows@#2}{}%
- \csdef{kvt@headings@#2}{\kvt@defaultheader}
+ \csdef{kvt@headings@#2}{\kvt@defaultheader}%
\listadd\kvt@alltables{#2}%
% \end{macrocode}
% Now parse \meta{colspecs}, a semicolon-separated list of individual
@@ -1883,20 +1987,20 @@ cherries,50g,cherries,heat up and add to bowl
% takes $n$ header cell titles, \meta{head1} to \meta{headn} and formats
% them based on the |headformat| and |headalign| options.
% More precisely, when fully expanded, |\kvt@defaultheader| yields
-% "\meta{rowcolor}|& |\meta{fmthead1}| & |\ldots| & |\meta{fmtheadn}|\tabularnewline|".
+% "\meta{rowcolor}\meta{fmthead1}| & |\ldots| & |\meta{fmtheadn}|\tabularnewline|".
% In the above, \meta{rowcolor}=|\rowcolor{|\meta{headbg}|}|.
% \begin{macrocode}
\newcommand\kvt@defaultheader{%
\noexpand\kvt@rowcolorornot{\cmdkvt@Table@headbg}%
- \kvt@defaultheader@i}
-\newcommand\kvt@defaultheader@i[1]{%
- \kvt@ifnil{#1}{\noexpand\tabularnewline}{%
- \unexpanded{&}%
+ \kvt@defaultheader@i{}}
+\newcommand\kvt@defaultheader@i[2]{%
+ \kvt@ifnil{#2}{\noexpand\tabularnewline}{%
+ \unexpanded{#1}%
\ifdefvoid\cmdkvt@Table@headalign
- {\expandonce\cmdkvt@Table@headformat{\unexpanded{#1}}}
+ {\expandonce\cmdkvt@Table@headformat{\unexpanded{#2}}}
{\noexpand\multicolumn{1}{\expandonce\cmdkvt@Table@headalign}
- {\expandonce\cmdkvt@Table@headformat{\unexpanded{#1}}}}%
- \kvt@defaultheader@i}}
+ {\expandonce\cmdkvt@Table@headformat{\unexpanded{#2}}}}%
+ \kvt@defaultheader@i{&}}}
% \end{macrocode}
% \begin{macro}{\kvt@ifnil}
% The |\kvt@ifnil|\marg{val}\marg{iftrue}\marg{iffalse} macro expands to
@@ -1914,16 +2018,6 @@ cherries,50g,cherries,heat up and add to bowl
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\kvt@HackIntercolSpace}
-% The |\kvt@HackIntercolSpace| macro captures the negative space that
-% cancels out the spacing otherwise caused by the extra column that the
-% package adds.
-% \begin{macrocode}
-\newcommand\kvt@HackIntercolSpace{%
- @{\hspace{-.5\arrayrulewidth}}}
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}{\kvt@alltables}
% The |\kvt@alltables| is an \pkgname{etoolbox} list containing the names
% of all tables declared by |\NewKeyValTable|.
@@ -1983,16 +2077,14 @@ cherries,50g,cherries,heat up and add to bowl
columns groups.}}{}%
\def\kvt@@colgrp{#2}%
\kvt@setkeys{#3}{ColGroup}%
- \kvt@checkcolgroupcs{kvt@colgrp@span@\kvt@@colgrp}{#1}{#2}%
- \eappto\kvt@@result{%
+ \kvt@checkcolgroupcs{kvt@colgrp@span@#1@#2}{#1}{#2}%
% \end{macrocode}
% The following defines the |\Row| key for \meta{cgname}, as an
% abbreviation for setting the value of the first displayed column of
% \meta{cgname} (|\kvt@@colgrp@first| to a |\multicolumn| that spans the
-% "right" number of columns. Notice the "*" after |\kvt@@colgrp@first|,
-% which disables the first column's default formatting to replace it by
-% the formatting of \meta{cgname}.
+% "right" number of columns).
% \begin{macrocode}
+ \eappto\kvt@@result{%
\noexpand\define@cmdkey[KeyValTable]{#1}{#2}{%
% \end{macrocode}
% The following |\ifdefvoid| check ensures that if \meta{cgname} is a
@@ -2000,14 +2092,27 @@ cherries,50g,cherries,heat up and add to bowl
% are hidden), then setting \meta{cgname} to a value has no effect.
% \begin{macrocode}
\ifdefvoid\kvt@@colgrp@first{}{%
- \noexpand\setkeys[KeyValTable]{#1}{%
- \expandonce\kvt@@colgrp@first*=\noexpand\multicolumn
- {\expandonce\kvt@@colgrp@n}%
- {\csexpandonce{kvt@colgrp@align@#2}}%
- {\csexpandonce{kvt@colgrp@format@#2}{\unexpanded{##1}}}}%
+% \end{macrocode}
+% The "abbreviation" is implemented via |\setkeys|. The letter normally
+% employs the defined |\presetkeys|, but we disable this through
+% |\kvt@xkv@disablepreset| to avoid that column keys that are set before
+% a colgroup key are overwritten by their preset values.
+% \begin{macrocode}
+ \noexpand\kvt@xkv@disablepreset[KeyValTable]{#1}{%
+ \noexpand\setkeys[KeyValTable]{#1}{%
+% \end{macrocode}
+% Notice the "*" after |\kvt@@colgrp@first|,
+% which disables the first column's default formatting to replace it by
+% the formatting of \meta{cgname}.
+% \begin{macrocode}
+ \expandonce\kvt@@colgrp@first=\noexpand\kvt@@@colgroup
+ {\unexpanded{#2}}%
+ {\expandonce\kvt@@colgrp@n}%
+ {\csexpandonce{kvt@colgrp@align@#1@#2}}%
+ {\unexpanded{##1}}}}%
}%
- }%
- \noexpand\listcsadd{kvt@grpcolkeys@#1}{#2}}}
+ }}%
+ \listcsadd{kvt@grpcolkeys@#1}{#2}}
% \end{macrocode}
% \end{macro}
%
@@ -2090,7 +2195,14 @@ cherries,50g,cherries,heat up and add to bowl
{Compare `\string\kvt@@curgrp' to the column ordering as
specified in `\string\NewKeyValTable{#1}'}%
\fi
- \edef\kvt@@colgrp@n{\the\numexpr\kvt@@colgrp@n+1\relax}}%
+ \edef\kvt@@colgrp@n{\the\numexpr\kvt@@colgrp@n+1\relax}%
+% \end{macrocode}
+% Since this macro is not encapsulated in a group (in order to return
+% |\kvt@@colgrp@n| and |\kvt@@colgrp@first|), we finally prevent the
+% local \cs{kvt@@incolgrp@\meta{column}} from leaking outside this
+% macro.
+% \begin{macrocode}
+ \csundef{kvt@@incolgrp@##1}}%
}\forlistcsloop{\kvt@@coldo}{kvt@displaycols@#2}}
% \end{macrocode}
% \end{macro}
@@ -2182,8 +2294,9 @@ cherries,50g,cherries,heat up and add to bowl
\let\kvt@@tmpgrphd\@empty
\kvt@@span\z@
\undef\kvt@@curhd \undef\kvt@@lasthd
+ \kvt@def@atseconduse\kvt@@switchcol{\appto\kvt@@tmpgrphd{&}}%
% \end{macrocode}
-% Next, loop over all displayed (non-hidden) columns stored in
+% Next, loop over all displayed columns, stored in
% \cs{kvt@displaycols@\meta{tname}}. The following |\do|\marg{colname}
% macro collects (spanned) columns as specified in \meta{colspec}, in the
% ordering in which the table's columns are displayed. The spanned
@@ -2247,21 +2360,11 @@ cherries,50g,cherries,heat up and add to bowl
% |\kvt@@tmpgrphd|).
% \begin{macrocode}
\newcommand\kvt@concludecolumn{%
-% \end{macrocode}
-% The following conditional checks whether this is the first header cell
-% in the header row. If this is the case, then the
-% |\kvt@@extraalign| macro is set to |\kvt@HackIntercolSpace|, such that
-% the |\multicolumn| below does not throw away this spacing.
-% \begin{macrocode}
- \ifdefequal\kvt@@tmpgrphd\@empty
- {\let\kvt@@extraalign\kvt@HackIntercolSpace}
- {\let\kvt@@extraalign\@empty}%
- \appto\kvt@@tmpgrphd{&}%
+ \kvt@@switchcol
\ifdefvoid\kvt@@lasthd{}{%
\eappto\kvt@@tmpgrphd{\noexpand\multicolumn
{\the\kvt@@span}
- {\expandonce\kvt@@extraalign
- \csexpandonce{kvt@@hdcell@align@\kvt@@lasthd}}
+ {\csexpandonce{kvt@@hdcell@align@\kvt@@lasthd}}
{\csexpandonce{kvt@@hdcell@head@\kvt@@lasthd}}}%
% \end{macrocode}
% Mark the header cell as already used and concluded, such that another
@@ -2285,9 +2388,9 @@ cherries,50g,cherries,heat up and add to bowl
% \begin{macrocode}
\def\kvt@@colreg##1{%
\ifinlistcs{##1}{kvt@allcolumns@#1}{}
- {\kvt@error{Column `##1', referenced in header cell `#2', not known
- in table type `#1'}{Check the \string\NewKeyValTable{#1} for
- the names of known columns and check `##1' for a typo.}}%
+ {\kvt@error{Column `##1', referenced in header cell `#2', not
+ known in table type `#1'}{Check the \string\NewKeyValTable{#1}
+ for the names of known columns and check `##1' for a typo.}}%
\ifcsmacro{kvt@@hdcellof@##1}
{\kvt@error{Column `##1' used in more than one header cell}
{Check the fourth, optional argument of \string\NewKeyValTable
@@ -2393,12 +2496,6 @@ cherries,50g,cherries,heat up and add to bowl
}{%
\csuse{kvt@EndTable@\cmdkvt@Table@shape}}
% \end{macrocode}
-% The following saves the row counter value outside the table
-% environment but still in the then-local scope.
-% \begin{macrocode}
-\AfterEndEnvironment{KeyValTable}{%
- \csdef{kvt@rowcount@\kvt@@recenttable}{\thekvtTypeRow}}
-% \end{macrocode}
% \end{environment}
%
% \begin{macro}{\kvt@SetOptions}
@@ -2434,6 +2531,13 @@ cherries,50g,cherries,heat up and add to bowl
{\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}
@@ -2447,6 +2551,20 @@ cherries,50g,cherries,heat up and add to bowl
{\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}}}%
+% \end{macrocode}
% Initializing the row counters. The global counter |kvtTotalRow| needs
% no local initialization.
% \begin{macrocode}
@@ -2458,6 +2576,7 @@ cherries,50g,cherries,heat up and add to bowl
% 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
@@ -2466,12 +2585,34 @@ cherries,50g,cherries,heat up and add to bowl
{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}}
@@ -2595,6 +2736,10 @@ cherries,50g,cherries,heat up and add to bowl
\metatbl@boolprop{hasWidth}{#1}}
\define@boolkey[metatbl]{EnvProp}{hasCaption}{%
\metatbl@boolprop{hasCaption}{#1}}
+\define@boolkey[metatbl]{EnvProp}{canVAlign}{%
+ \metatbl@boolprop{canVAlign}{#1}}
+\define@boolkey[metatbl]{EnvProp}{canHAlign}{%
+ \metatbl@boolprop{canHAlign}{#1}}
\define@cmdkey[metatbl]{EnvProp}{packages}{\metatbl@setprop{pkg}{#1}}
% \end{macrocode}
% The |atEnd| property shall be set to \hologo{TeX} code with one
@@ -2645,6 +2790,8 @@ cherries,50g,cherries,heat up and add to bowl
% \begin{macro}{\metatblIsTabu}
% \begin{macro}{\metatblHasWidth}
% \begin{macro}{\metatblHasCaption}
+% \begin{macro}{\metatblCanVAlign}
+% \begin{macro}{\metatblCanHAlign}
% The macro
% |\metatblIsLong|\marg{env-name}\marg{iftrue}\marg{iffalse}
% expands to \meta{iftrue} if \meta{env-name} is a "long" table
@@ -2666,26 +2813,32 @@ cherries,50g,cherries,heat up and add to bowl
\newcommand\metatblIsTabu[1]{\ifbool{metatbl@EnvProp@isTabu@#1}}
\newcommand\metatblHasWidth[1]{\ifbool{metatbl@EnvProp@hasWidth@#1}}
\newcommand\metatblHasCaption[1]{\ifbool{metatbl@EnvProp@hasCaption@#1}}
+\newcommand\metatblCanVAlign[1]{\ifbool{metatbl@EnvProp@canVAlign@#1}}
+\newcommand\metatblCanHAlign[1]{\ifbool{metatbl@EnvProp@canHAlign@#1}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \begin{macro}{\metatblUsePackage}
% \begin{macro}{\metatblRequire}
-% The |\metatblUsePackage|\marg{env-names} and
-% |\metatblRequire|\marg{env-names} macros load the packages required
+% Macros |\metatblUsePackage|\marg{env-names} and
+% |\metatblRequire|\marg{env-names} load the packages required
% for typesetting |KeyValTable| tables based on the table environments
% listed in \meta{env-names}.
% The former aims more at normal document use, the second at use by
% package developers.
% \begin{macrocode}
\newcommand\metatblUsePackage[1]{%
- \def\do##1{\metatbl@csnamearg\usepackage{metatbl@EnvProp@pkg@##1}}%
+ \def\do##1{%
+ \metatbl@csnamearg\usepackage{metatbl@EnvProp@pkg@##1}}%
\docsvlist{#1}}
\newcommand\metatblRequire[1]{%
- \def\do##1{\metatbl@csnamearg\RequirePackage{metatbl@EnvProp@pkg@##1}}%
+ \def\do##1{%
+ \metatbl@csnamearg\RequirePackage{metatbl@EnvProp@pkg@##1}}%
\docsvlist{#1}}
% \end{macrocode}
% \end{macro}
@@ -2717,11 +2870,13 @@ cherries,50g,cherries,heat up and add to bowl
% \begin{macrocode}
\metatblRegisterEnv{tabular}{%
isLong=false, hasWidth=false, isTabu=false, hasCaption=false,
+ canVAlign=true, canHAlign=false,
packages={},
atEnd={\preto\endtabular{#1}},
}
\metatblRegisterEnv{tabularx}{%
isLong=false, hasWidth=true, isTabu=false, hasCaption=false,
+ canVAlign=true, canHAlign=false,
packages=tabularx,
atEnd={%
% \end{macrocode}
@@ -2734,16 +2889,19 @@ cherries,50g,cherries,heat up and add to bowl
}
\metatblRegisterEnv{longtable}{%
isLong=true, hasWidth=false, isTabu=false, hasCaption=true,
+ canVAlign=false, canHAlign=true,
packages={longtable},
atEnd={\preto\endlongtable{#1}},
}
\metatblRegisterEnv{xltabular}{%
isLong=true, hasWidth=true, isTabu=false, hasCaption=true,
+ canVAlign=false, canHAlign=true,
packages=xltabular,
atEnd={\preto\XLT@ii@TX@endtabularx{\toks@\expandafter{\the\toks@#1}}},
}
\metatblRegisterEnv{tabu}{%
isLong=false, hasWidth=true, isTabu=true, hasCaption=false,
+ canVAlign=true, canHAlign=false,
packages={tabu},
% \end{macrocode}
% The following is not a mistake: |tabu| does
@@ -2753,6 +2911,7 @@ cherries,50g,cherries,heat up and add to bowl
}
\metatblRegisterEnv{longtabu}{%
isLong=true, hasWidth=true, isTabu=true, hasCaption=true,
+ canVAlign=false, canHAlign=true,
packages={tabu,longtable},
% \end{macrocode}
% The following is not a mistake: |tabu| does
@@ -2790,7 +2949,7 @@ cherries,50g,cherries,heat up and add to bowl
% When an |X| column is encountered, |\metatbl@@branch| is redefined to
% expand to \meta{iftrue} in the end.
% \begin{macrocode}
- \def\NC@rewrite@X{\def\metatbl@@branch{\@firstoftwo}\NC@find}%
+ \def\NC@rewrite@X{\def\metatbl@@branch{\@firstoftwo}\NC@find l}%
\@mkpream{#1}%
\expandafter\endgroup\metatbl@@branch}
% \end{macrocode}
@@ -2858,6 +3017,39 @@ cherries,50g,cherries,heat up and add to bowl
\ifbool{kvt@Row@uncounted}{}{%
\appto\kvt@@row{\noalign{\kvt@stepcounters}}}%
% \end{macrocode}
+% If a row alignment is specified, a default |\multicolumn| display is
+% enabled for the row's cells.
+% \begin{macrocode}
+ \ifdefvoid\cmdkvt@Row@align
+ {\let\kvt@@rowmkmulticolumn\@empty}
+ {\edef\kvt@@rowmkmulticolumn{%
+ \noexpand\multicolumn{1}{\expandonce\cmdkvt@Row@align}}}%
+% \end{macrocode}
+% The following defines a macro
+% |\kvt@@cellfmtbuilder|\marg{cmd}\marg{csname}.
+% This macro defines the macro \meta{cmd}\marg{cell} to format the cell
+% content, \meta{cell}, based on the column format \meta{csname} and the
+% row formatting options.
+% Through this "builder" macro, the row format options need only be
+% considered once and the column format options can then be included
+% when the displayed columns are iterated over.
+% \begin{macrocode}
+ \ifcsvoid{cmdkvt@Row@format!}
+ {\edef\kvt@@cellfmtbuilder##1##2{%
+ \noexpand\edef##1####1{%
+ \noexpand\kvt@expandonce@onearg\noexpand\kvt@@mkmulticolumn
+ {\ifcsvoid{cmdkvt@Row@format*}{\@firstofone}
+ {\noexpand\unexpanded{\csexpandonce{cmdkvt@Row@format*}}}%
+ {\noexpand\csexpandonce{##2}{%
+ \ifdefvoid\cmdkvt@Row@format{\@firstofone}
+ {\noexpand\unexpanded{\expandonce\cmdkvt@Row@format}}%
+ {####1}}}}}}}%
+ {\edef\kvt@@cellfmtbuilder##1##2{%
+ \noexpand\edef##1####1{%
+ \noexpand\kvt@expandonce@onearg\noexpand\kvt@@mkmulticolumn{%
+ \noexpand\unexpanded{\csexpandonce{cmdkvt@Row@format!}}%
+ {####1}}}}}%
+% \end{macrocode}
% The following loop uses |\do|\marg{cname} to append the content of
% all displayed columns (in the given format and using the given default
% value), where each column value is in
@@ -2867,50 +3059,70 @@ cherries,50g,cherries,heat up and add to bowl
% \changes{v1.0}{2019/02/03}{Added \cs{multicolumn} support}
% \begin{macrocode}
\kvt@@span=0\relax
+ \kvt@def@atseconduse\kvt@@switchcol{\appto\kvt@@row{&}}%
\def\do##1{%
% \end{macrocode}
+% First, check whether a column-spanning cell is active
+% ($\cs{kvt@@span}>0$). If this is the case, ensure that if the raw cell
+% content in the current column is empty, then the column is simply
+% ignored and otherwise an error is produced.
+% \begin{macrocode}
+ \ifnumgreater\kvt@@span{0}
+ {\advance\kvt@@span\m@ne
+ \ifcsvoid{cmdKeyValTable@#2@##1}{}
+ {\ifdefvoid\kvt@@curcgname
+ {\kvt@error{Column '##1' nonempty inside a
+ \string\multicolumn}{}}
+ {\kvt@error{Column '##1' nonempty inside column group
+ '\kvt@@curcgname'}{}}}}
+ {\kvt@@switchcol
+% \end{macrocode}
+% Initialize the multicolumn display to the row's default.
+% \begin{macrocode}
+ \let\kvt@@mkmulticolumn\kvt@@rowmkmulticolumn
+ \letcs\kvt@@curcolformat{kvt@col@format@#2@##1}%
+% \end{macrocode}
% First recover the cell content (either the specified value for the row
% or, if no value is specified for the row, the cell's default value)
% without formatting.
% \begin{macrocode}
- \ifcsvoid{cmdKeyValTable@#2@##1}
- {\letcs\kvt@@cell{kvt@col@default@#2@##1}}
- {\letcs\kvt@@cell{cmdKeyValTable@#2@##1}%
+ \ifcsvoid{cmdKeyValTable@#2@##1}
+ {\letcs\kvt@@cell{kvt@col@default@#2@##1}}
+ {\letcs\kvt@@cell{cmdKeyValTable@#2@##1}%
% \end{macrocode}
-% Apply expansion control options, but only to manually supplied cell
-% values, not to default values.
+% Unless the default cell value is used, first check for a multicolumn
+% value. Default cell values should not need this. The check is done
+% before the expansion code afterwards, in order for applying the
+% expansion to the code in the cell value rather than to the multicolumn
+% code.
% \begin{macrocode}
- \ifbool{kvt@Row@expandonce}
- {\expandafter\let\expandafter\kvt@@cell\kvt@@cell}{}%
- \ifbool{kvt@Row@expand}
- {\protected@edef\kvt@@cell{\kvt@@cell}}{}}%
+ \expandafter\kvt@CheckMulticolumn\expandafter{\kvt@@cell}{#2}%
% \end{macrocode}
-% Separately also already create the formatted content.
+% Apply expansion control options, but only to manually supplied cell
+% values, not to default values.
% \begin{macrocode}
- \ifcsvoid{kvt@@noformat@#2@##1}
- {\edef\kvt@@formatter{\expandonce{\csname kvt@col@format@#2@##1\endcsname}}}%
- {\def\kvt@@formatter{\@firstofone}}%
- \edef\kvt@@fmtcell{\expandonce\kvt@@formatter{%
- \expandonce\kvt@@cell}}%
- \csundef{kvt@@noformat@#2@##1}%
+ \ifbool{kvt@Row@expandonce}
+ {\expandafter\let\expandafter\kvt@@cell\kvt@@cell}{}%
+ \ifbool{kvt@Row@expand}
+ {\protected@edef\kvt@@cell{\kvt@@cell}}{}}%
% \end{macrocode}
-% Next, check whether a column-spanning cell is active
-% ($\cs{kvt@@span}>0$). If this is the case, ensure that if the raw cell
-% content in the current column is empty, then formatting does not make
-% the cell non-empty and, thereby, cause errors with the active
-% column-spanning cell.
+% Separately also already create the content -- with formatting unless
+% the user explicitly requested no cell formatting.
% \begin{macrocode}
- \ifnumgreater\kvt@@span{0}
- {\advance\kvt@@span\m@ne
- \ifstrempty\kvt@@cell{\def\kvt@@fmtcell{}}{}}
- {\appto\kvt@@row{&}}%
+ \ifcsvoid{kvt@@noformat@#2@##1}
+ {\kvt@@cellfmtbuilder\kvt@@formatter{kvt@@curcolformat}}%
+ {\let\kvt@@formatter\@firstofone}%
+ \csundef{kvt@@noformat@#2@##1}%
+ \edef\kvt@@fmtcell{\expandafter\expandonce\expandafter{%
+ \expandafter\kvt@@formatter\expandafter{%
+ \kvt@@cell}}}%
% \end{macrocode}
-% Now check whether the cell itself spans multiple columns.
+% Finally, append the cell to the row.
% \begin{macrocode}
- \expandafter\kvt@CheckMulticolumn\kvt@@cell
- \relax\relax\relax\relax\@undefined
- \expandafter\appto\expandafter\kvt@@row\expandafter{\kvt@@fmtcell}%
+ \expandafter\appto\expandafter\kvt@@row\expandafter{%
+ \kvt@@fmtcell}}%
}\dolistcsloop{kvt@displaycols@#2}%
+ \undef\kvt@@cellfmtbuilder
% \end{macrocode}
% Finally, add the concluding newline for the row as well as
% the vertical space after the row, if requested.
@@ -2926,6 +3138,36 @@ cherries,50g,cherries,heat up and add to bowl
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\kvt@def@atseconduse}
+% The |\kvt@def@atseconduse|\marg{cmd}\marg{code} defines the macro
+% \meta{cmd} to expand to \meta{code} but only from its second use
+% onwards. At its first use, \meta{cmd} only redefines itself to
+% \meta{code} but does not do anything else.
+% \begin{macrocode}
+\newcommand\kvt@def@atseconduse[2]{\def#1{\def#1{#2}}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt@expandonce@onearg}
+% The |\kvt@expandonce@onearg|\marg{cmd}\marg{arg} macro expands to
+% \meta{arg} if \meta{cmd} is empty and expands to an |\expandonce| on
+% \meta{cmd} with \meta{arg} as argument otherwise.
+% This macro is for an |\edef| context in which an empty \meta{cmd}
+% should not leave any parentheses around the \meta{arg}.
+% \begin{macrocode}
+\newcommand\kvt@expandonce@onearg[2]{%
+ \ifdefequal{#1}{\@empty}{#2}{\expandonce{#1}{#2}}}
+% \end{macrocode}
+% Note that the alternative of avoiding the conditional (|\ifdefequal|)
+% in the above code and using |\@firstofone| instead of |\@empty| for a
+% noop in \meta{cmd} does not work:
+% Using `|\expandonce|\marg{cmd}\marg{arg}' would expand to
+% `|\unexpanded\expandafter{\@firstofone}|' and produces the error
+% `Argument of |\@firstofone| has an extra |}|'.
+% Using `|\expandonce{|\meta{cmd}\marg{arg}|}|' would expand to
+% `|\unexpanded|\marg{arg}' and, thus, prevent expansion of \meta{arg}.
+% \end{macro}
+%
% \begin{macro}{\kvt@stepcounters}
% The |\kvt@stepcounters|\oarg{delta} macro increments all row counters
% by \meta{delta}. If \meta{delta} is omitted, \meta{delta}=1.
@@ -2939,30 +3181,94 @@ cherries,50g,cherries,heat up and add to bowl
%
% \begin{macro}{\kvt@CheckMulticolumn}
% The
-% |\kvt@CheckMulticolumn|\marg{arg1}\marg{arg2}\marg{arg3}\marg{arg4}|\@undefined|
-% macro checks whether a cell's initial content (captured by \meta{arg1}
-% to \meta{arg4}, starts a multi-column cell. If this is the case, the
-% macro records the arguments to |\multicolumn| for use by
-% |\kvt@AddKeyValRow|.
-% In this case, \meta{arg1}=|\multicolumn|, \meta{arg2}=\meta{n} (number
-% of columns to span), \meta{arg3}=\meta{format} (column alignment), and
-% \meta{arg4}=\meta{item} (the content of the cell).
+% |\kvt@CheckMulticolumn|\marg{content}\marg{tname} macro
+% checks whether a cell's \meta{content} in a table of type \meta{tname}
+% spans multiple columns in one of two ways:
+% \begin{enumerate}[nosep]
+% \item \meta{content} = |\multicolumn|\marg{n}\marg{align}\marg{content} or
+% \item \meta{content} = |\kvt@@@colgroup|\marg{cgname}\marg{n}\marg{align}\marg{content}
+% \end{enumerate}
+% The first way corresponds to the case that a user of the package
+% explicitly assigns a |\multicolumn| expression to a cell in a row.
+% The second way is generated by the package when a user assigns a
+% normal cell value to a column group key.
+% \begin{macrocode}
+\newcommand\kvt@CheckMulticolumn[2]{%
+% \end{macrocode}
+% For parsing \meta{content}, the macro uses |\kvt@CheckMulticolumn@i|
+% and adds 5 |\relax| after \meta{content} for the case that
+% \meta{content} is empty or too short.
% \begin{macrocode}
-\def\kvt@CheckMulticolumn#1#2#3#4\@undefined{%
- \ifx#1\multicolumn
+ \kvt@CheckMulticolumn@i{#2}#1%
+ \relax\relax\relax\relax\relax\kvt@@undefined}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt@CheckMulticolumn@i}
+% The
+% |\kvt@CheckMulticolumn@i|\marg{tname}\marg{c1}$\cdots$\marg{c5}\marg{ign}|\@undefined|
+% macro checks \meta{content} when split into \meta{c1}$\cdots$\meta{c5}
+% for one of the two multicolumn cases listed in the description of
+% |\kvt@CheckMulticolumn|.
+% \begin{macrocode}
+\def\kvt@CheckMulticolumn@i#1#2#3#4#5#6#7\kvt@@undefined{%
+ \ifdefmacro{#2}{%
+% \end{macrocode}
+% First case: \meta{c1}=|\multicolumn|. In this case, we have
+% \meta{c2}=\meta{n}, \meta{c3}=\meta{align}, and
+% \meta{c4}=\meta{content}.
+% \begin{macrocode}
+ \ifx#2\multicolumn
+ \kvt@SetMulticolumn{#4}{#3}{#5}%
+ \let\kvt@@curcgname\@empty
+% \end{macrocode}
+% Second case: \meta{c1}=|\kvt@@@colgroup|. In this case, we have
+% \meta{c3}=\meta{n}, \meta{c4}=\meta{align}, and
+% \meta{c5}=\meta{content}. Moreover, \meta{c2} holds \meta{cgname}.
+% \begin{macrocode}
+ \else\ifx#2\kvt@@@colgroup
+ \letcs\kvt@@curcolformat{kvt@colgrp@format@#1@#3}%
+ \def\kvt@@curcgname{#3}%
+% \end{macrocode}
+% If a row alignment is defined, it overrides the alignment of the
+% column group:
+% \begin{macrocode}
+ \ifdefvoid\cmdkvt@Row@align
+ {\kvt@SetMulticolumn{#5}{#4}{#6}}
+ {\expandafter
+ \kvt@SetMulticolumn\expandafter{\cmdkvt@Row@align}{#4}{#6}}%
+ \fi\fi}{}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt@@@colgroup}
+% The |\kvt@@@colgroup| macro is not used as an actual macro but only as
+% an identifier for |\kvt@CheckMulticolumn@i|.
+% \begin{macrocode}
+\newcommand\kvt@@@colgroup{kvt@@@colgroup}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt@SetMulticolumn}
+% The |\kvt@SetMulticolumn|\marg{align}\marg{n}\marg{content} records
+% that \meta{n} cells, starting from the current cell, belong to a
+% multicolumn cell with alignment \meta{align} and the given
+% \meta{content}.
+% \begin{macrocode}
+\newcommand\kvt@SetMulticolumn[3]{%
% \end{macrocode}
% First, record \meta{n} in |\kvt@@span|. The subtraction of $-1$ is
% already in preparation for the next column, in which one spanning has
% already been reduced.
% \begin{macrocode}
- \kvt@@span=#2\relax \advance\kvt@@span\m@ne
+ \kvt@@span=#2\relax \advance\kvt@@span\m@ne
% \end{macrocode}
-% Second, move the defined cell format to inside of the \meta{item}
-% argument of |\multicolumn| rather than around the |\multicolumn|.
+% Next, unwrap the cell's \meta{content} to |\kvt@@cell| and record the
+% |\kvt@@mkmulticolumn| for re-wrapping the content later, after all
+% cell formatting has been applied.
% \begin{macrocode}
- \edef\kvt@@fmtcell{\unexpanded{\multicolumn{#2}{#3}}%
- {\expandonce\kvt@@formatter{\expandonce{#4}}}}%
- \fi}
+ \def\kvt@@cell{#3}%
+ \def\kvt@@mkmulticolumn{\multicolumn{#2}{#1}}}
% \end{macrocode}
% \end{macro}
%
@@ -3015,12 +3321,18 @@ cherries,50g,cherries,heat up and add to bowl
% \begin{macrocode}
\newcommand\kvt@UseRowStyles[1]{%
% \end{macrocode}
-% We use |\kvt@xkv@disablepreset| to eliminate undesired effects from
-% presets. When, for example, using |\Row[bg=red,style=abc]{...}|, this
-% causes a |\setkeys[kvt]{Row}{xyz}| (if |xyz| is how the style |abc| is
-% defined) inside the |\setkeys[kvt]{Row}{bg=red,style=abc}|. The former
+% We use |\kvt@xkv@disablepreset| to eliminate undesired effects that
+% would otherwise be caused by preset values for keys.
+% For an example of such side-effect, consider a style "|vis|" that is
+% defined as "|hidden=false|". Then,
+% |\Row[bg=red,style=vis]{...}|
+% causes a
+% |\setkeys[kvt]{Row}{hidden=false}|
+% to be processed inside the |\setkeys[kvt]{Row}{bg=red,style=vis}|,
+% after the |bg=red| is processed.
+% The former
% |\setkeys| would then again employ the presets for |Row| (e.g., from a
-% |\kvtSet{Row/bg=blue}| and overwrite the |bg=red|.
+% |\kvtSet{Row/bg=blue}|) and undesirably overwrite the |bg=red|.
% \begin{macrocode}
\kvt@xkv@disablepreset[kvt]{Row}{%
\forcsvlist\kvt@UseRowStyle{#1}}}
@@ -3028,17 +3340,9 @@ cherries,50g,cherries,heat up and add to bowl
% \end{macro}
%
% \begin{macro}{\kvt@xkv@disablepreset}
-% \begin{macro}{\kvt@xkv@savepreset}
-% \begin{macro}{\kvt@xkv@restorepreset}
% The |\kvt@xkv@disablepreset|\oarg{prefix}\marg{family}\marg{code}
-% disables presets (head and tail) for \meta{family} during the
+% disables head presets and tail presets for \meta{family} during the
% expansion of \meta{code}.
-% The auxiliary macros
-% |\kvt@xkv@savepreset|\marg{prefix}\marg{family}\marg{h/t}
-% and
-% |\kvt@xkv@restorepreset|\marg{prefix}\marg{family}\marg{h/t}
-% save+unset and, respectively, restore the preset keys for
-% \meta{family} -- head keys for \meta{h/t}=h and tail keys otherwise.
% \begin{macrocode}
\newcommand\kvt@xkv@disablepreset[3][KV]{%
\ifnumgreater{\XKV@depth}{1}
@@ -3048,6 +3352,17 @@ cherries,50g,cherries,heat up and add to bowl
#3%
\kvt@xkv@restorepreset{#1}{#2}{h}%
\kvt@xkv@restorepreset{#1}{#2}{t}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\kvt@xkv@savepreset}
+% \begin{macro}{\kvt@xkv@restorepreset}
+% The auxiliary macro
+% |\kvt@xkv@savepreset|\marg{prefix}\marg{family}\marg{h/t}
+% saves and unsets the preset keys (head keys for \meta{h/t}=h and tail
+% keys otherwise) for \meta{family}. The macro
+% |\kvt@xkv@restorepreset|\marg{prefix}\marg{family}\marg{h/t}
+% restores the preset keys saved via |\kvt@xkv@savepreset|.
+% \begin{macrocode}
\newcommand\kvt@xkv@savepreset[3]{%
\csletcs{kvt@@saved@preset#3}{XKV@#1@#2@preset#3}%
\csundef{XKV@#1@#2@preset#3}}
@@ -3056,7 +3371,6 @@ cherries,50g,cherries,heat up and add to bowl
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \subsection{Collecting Key-Value Table Content}
%
@@ -3113,7 +3427,7 @@ cherries,50g,cherries,heat up and add to bowl
% \end{macro}
%
% \begin{macro}{\kvt@protected@write}
-% The |\kvt@protected@write|\marg{file}{content} macro writes
+% The |\kvt@protected@write|\marg{file}\marg{content} macro writes
% \meta{content} to \meta{file}. The write ensures that \meta{content}
% is written in a particularly protected form that
% \begin{enumerate}[noitemsep]
@@ -3322,9 +3636,10 @@ cherries,50g,cherries,heat up and add to bowl
%
% \begin{macro}{\ShowKeyValTableFile}
% The |\ShowKeyValTableFile|\oarg{options}\marg{tname}\marg{filename}
-% macro typesets a |KeyValTable| environment of type \meta{tname} with
-% the given \meta{options}. The body of the environment (i.e., the rows
-% of the table) are read from the file \meta{filename}.
+% loads the content of the file with name \meta{filename} and places it
+% inside the body of a |KeyValTable| environment of type \meta{tname} with
+% the given \meta{options}. That is, the filename should contain the rows
+% of the table.
% \changes{v2.0}{2019/03/25}{Added the macro}
% \begin{macrocode}
\newcommand\ShowKeyValTableFile[3][]{%
@@ -3436,7 +3751,7 @@ cherries,50g,cherries,heat up and add to bowl
% received a key-value syntax.
% \begin{macrocode}
\kvt@IfVersion{<}{2.0}{%
- \let\kvt@parselayout=\kvt@parseheadrows
+ \renewcommand\kvt@parselayout[2]{\kvt@parseheadrows{#2}{#1}}%
}{}
% \end{macrocode}
%
diff --git a/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins b/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins
index 9c606c8ca5e..077ef3f629b 100644
--- a/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins
+++ b/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins
@@ -1,5 +1,5 @@
%%
-%% Copyright (C) 2016-2018 by Richard Grewe <r-g+tex@posteo.net>
+%% Copyright (C) 2016-2020 by Richard Grewe <r-g+tex@posteo.net>
%%
%% This file may be distributed and/or modified under the conditions of
%% the LaTeX Project Public License, either version 1.2 of this license
@@ -17,7 +17,7 @@
\usedir{tex/latex/keyvaltable}
\preamble
-Copyright (C) 2016-2018 by Richard Grewe <r-g+tex@posteo.net>
+Copyright (C) 2016-2020 by Richard Grewe <r-g+tex@posteo.net>
This file may be distributed and/or modified under the conditions of
the LaTeX Project Public License, either version 1.2 of this license