diff options
author | Karl Berry <karl@freefriends.org> | 2020-02-21 22:54:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-02-21 22:54:25 +0000 |
commit | 8c001b9ec06abf4a378fbe9fd81bde3e5343d6c1 (patch) | |
tree | 38b64b09487f20a4b4235b8222f92114e9da3af6 /Master/texmf-dist/source | |
parent | ee6d6cebcf0c8b850920001a6420f42c156050b0 (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.dtx | 705 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins | 4 |
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 |