From 9de5430526214561f7a4758932f732797f19aa02 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sat, 1 Jun 2019 20:58:00 +0000 Subject: keyvaltable (1jun19) git-svn-id: svn://tug.org/texlive/trunk@51288 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/latex/keyvaltable/keyvaltable.sty | 682 +++++++++++++++------ 1 file changed, 509 insertions(+), 173 deletions(-) (limited to 'Master/texmf-dist/tex/latex/keyvaltable') diff --git a/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty b/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty index 9da59f28813..de0350c02a6 100644 --- a/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty +++ b/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty @@ -20,81 +20,140 @@ %% \NeedsTeXFormat{LaTeX2e}[1999/12/01] \ProvidesPackage{keyvaltable} - [2019/03/17 v1.0 Package for filling tables using key-value lists] + [2019/05/11 v2.0 Package for filling tables using key-value lists] \RequirePackage{etoolbox} \RequirePackage{xkeyval} \RequirePackage{trimspaces} \PassOptionsToPackage{table}{xcolor} \RequirePackage{xcolor} \RequirePackage{booktabs} -\newcommand\kvtSet[1]{\bgroup - \def\kvt@@presetqueue{\egroup} - \setkeys[kvt]{defaults}{#1}{}% - \kvt@@presetqueue} +\DeclareListParser{\kvt@dossvlist}{;} +\DeclareListParser*{\kvt@forpsvlist}{+} +\DeclareListParser{\kvt@dobrklist}{\\} +\newcommand\kvt@error[2]{\PackageError{keyvaltable}{#1}{#2}} +\newcommand\kvt@warn[1]{\PackageWarning{keyvaltable}{#1}} +\newcommand\kvt@setkeys[2]{\setkeys[kvt]{#2}{#1}} +\newcommand\kvt@setcmdkeys[2]{% + \expandafter\kvt@setkeys\expandafter{#1}{#2}} +\newcommand\kvt@setcskeys[2]{% + \expandafter\kvt@setcmdkeys\expandafter{\csname #1\endcsname}{#2}} +\newcommand\kvt@colsetkeys[2]{\setkeys[KeyValTable]{#1}{#2}} +\newcommand\kvt@colsetcmdkeys[2]{% + \expandafter\kvt@colsetkeys\expandafter{#1}{#2}} +\newcommand\kvt@colsetcskeys[2]{% + \expandafter\kvt@colsetcmdkeys\expandafter{\csname #1\endcsname}{#2}} +\newcommand\kvtStrutted[2][\@firstofone]{% + \strut#1{#2}\ifhmode\expandafter\strut\fi} +\newcommand\kvtSet[1]{% + \kvt@setkeys{#1}{global,Table,Column}% + \ifdefvoid\kvt@@presetqueue{} + {\kvt@@presetqueue\undef\kvt@@presetqueue}} \newcommand\kvt@lazypreset[2]{% \appto\kvt@@presetqueue{\presetkeys[kvt]{#1}{#2}{}}} -\newcommand\kvt@addtableprop[2]{% - \define@key[kvt]{defaults}{#1}{% - \kvt@lazypreset{Table}{#1=##1}}% - \presetkeys[kvt]{defaults}{#1=#2}{}% - \define@cmdkey[kvt]{Table}{#1}{}% - \presetkeys[kvt]{Table}{#1=#2}{}} -\newcommand\kvt@addchoicetableprop[3]{% - \define@choicekey[kvt]{defaults}{#1}{#3}{% - \kvt@lazypreset{Table}{#1=##1}}% - \presetkeys[kvt]{defaults}{#1=#2}{}% - \define@choicekey[kvt]{Table}{#1}{#3}% - {\csdef{cmdkvt@Table@#1}{##1}}% - \presetkeys[kvt]{Table}{#1=#2}{}} -\newcommand\kvt@addbooltableprop[2]{% - \define@boolkey[kvt]{defaults}{#1}{% - \kvt@lazypreset{Table}{#1=##1}}% - \presetkeys[kvt]{defaults}{#1=#2}{}% - \define@boolkey[kvt]{Table}{#1}% - {\csdef{cmdkvt@Table@#1}{##1}}% - \presetkeys[kvt]{Table}{#1=#2}{}} -\newcommand\kvt@addcolumnprop[2]{% - \define@key[kvt]{defaults}{#1}{% - \kvt@lazypreset{Column}{#1=##1}}% - \presetkeys[kvt]{defaults}{#1=#2}{}% - \define@key[kvt]{Column}{#1}{% - \csdef{kvt@col@#1@\kvt@@column}{##1}}% - \presetkeys[kvt]{Column}{#1=#2}{}% -} -\newcommand\kvt@addchoicecolumnprop[4]{% - \define@choicekey[kvt]{defaults}{#1}{#4}[#3]{% - \kvt@lazypreset{Column}{#1=##1}}% - \presetkeys[kvt]{defaults}{#1=#2}{}% - \define@choicekey[kvt]{Column}{#1}{#4}[#3]% - {\csdef{kvt@col@#1@\kvt@@column}{##1}}% - \presetkeys[kvt]{Column}{#1=#2}{}% -} -\kvt@addtableprop{rowbg}{white..black!10} -\kvt@addtableprop{headbg}{black!14} -\kvt@addbooltableprop{showhead}{true} -\kvt@addbooltableprop{showrules}{true} -\kvt@addtableprop{headfmt}{} -\kvt@addtableprop{headalign}{} -\kvt@addtableprop{width}{\linewidth} -\kvt@addchoicetableprop{shape}{multipage}{% - multipage,onepage,tabular,longtable,tabularx} -\kvt@addcolumnprop{default}{} -\kvt@addcolumnprop{format}{\kvtStrutted} -\kvt@addcolumnprop{align}{l} -\kvt@addcolumnprop{head}{} -\kvt@addchoicecolumnprop{hidden}{false}{true}{false,true} -\kvtSet{} +\newcommand\kvt@keysetter[5]{% + \ifdefvoid{#1} + {\kvt@lazypreset{#2}{#3=#4}} + {#5}} \newcommand\kvtTableOpt[1]{\csname cmdkvt@Table@#1\endcsname} -\newcommand\kvtStrutted[1]{\strut #1\ifhmode\expandafter\strut\fi} +\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}{} +\define@boolkey[kvt]{Table}{showhead}{} +\define@boolkey[kvt]{Table}{showrules}{} +\define@cmdkey[kvt]{Table}{caption}{} +\define@cmdkey[kvt]{Table}{label}{} + +\define@choicekey[kvt]{Table}{shape} + {multipage,onepage,tabular,longtable,tabularx,xltabular,tabu,longtabu} + {\csdef{cmdkvt@Table@shape}{#1}} +\define@key[kvt]{Column}{default}{\kvt@colkeysetter{default}{#1}} +\define@key[kvt]{Column}{format}{\kvt@colkeysetter{format}{#1}} +\define@key[kvt]{Column}{align}{\kvt@colkeysetter{align}{#1}} +\define@key[kvt]{Column}{head}{\kvt@colkeysetter{head}{#1}} +\define@boolkey[kvt]{Column}{hidden}[true]{% + \kvt@colkeysetter{hidden}{#1}} +\newcommand\kvt@colkeysetter[2]{% + \kvt@keysetter{\kvt@@column}{Column}{#1}{#2}{% + \csdef{kvt@col@#1@\kvt@@column}{#2}}} +\newcommand\kvt@def@globalopt[2]{% + \define@key[kvt]{global}{#1/#2}{\kvt@lazypreset{#1}{#2={##1}}}} +\newcommand\kvt@def@globalopts[2]{% + \forcsvlist{\kvt@def@globalopt{#1}}{#2}} +\define@cmdkey[kvt]{ColGroup}{span}{% + \csdef{kvt@colgrp@span@\kvt@@colgrp}{#1}} +\define@cmdkey[kvt]{ColGroup}{align}{% + \csdef{kvt@colgrp@align@\kvt@@colgrp}{#1}} +\define@cmdkey[kvt]{ColGroup}{format}{% + \csdef{kvt@colgrp@format@\kvt@@colgrp}{#1}} +\kvt@def@globalopts{ColGroup}{align, format} +\define@cmdkey[kvt]{Layout}{headers}{% + \expandafter\kvt@parseheadrows\expandafter{\kvt@@tname}{#1}} +\define@cmdkey[kvt]{Layout}{colgroups}{% + \expandafter\kvt@parsecolgroups\expandafter{\kvt@@tname}{#1}} +\define@key[kvt]{HeadCell}{head}{% + \csdef{kvt@@hdcell@head@\kvt@@hdcell}{#1}} +\define@key[kvt]{HeadCell}{align}{% + \csdef{kvt@@hdcell@align@\kvt@@hdcell}{#1}} +\kvt@def@globalopts{HeadCell}{align} +\define@cmdkey[kvt]{Row}{bg}{} +\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}} +\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]{} +\kvt@def@globalopts{Row}{ + bg,hidden,below,above,around,style,uncounted, + expand,expandonce} +\kvtSet{% + rowbg=white..black!10, + headbg=black!14, + showhead=true, + showrules=true, + headformat=\@firstofone, + headalign=, + shape=multipage, + width=\linewidth, + caption={}, label={}, + default=, + format=\kvtStrutted, + align=l, + head=, + hidden=false, + Row/bg={}, + Row/hidden=false, + Row/above={}, + Row/below={}, + Row/uncounted=false, + Row/expand=false, + Row/expandonce=false, + ColGroup/align=c, + ColGroup/format=\kvtStrutted, + HeadCell/align=c, +} \newcommand\NewKeyValTable[3][]{% \@ifnextchar[%] {\kvt@NewKeyValTable{#1}{#2}{#3}}% {\kvt@NewKeyValTable{#1}{#2}{#3}[]}} \def\kvt@NewKeyValTable#1#2#3[#4]{% + \ifinlist{#2}{\kvt@alltables} + {\kvt@error{Table type with name '#2' already defined} + {Check '#2' for typos and check other uses of + \string\NewKeyValTable}}{}% \csdef{kvt@options@#2}{#1}% \csdef{kvt@headings@#2}{}% \csedef{kvt@alignments@#2}{p{0pt}\expandonce\kvt@HackIntercolSpace}% - \csdef{kvt@colkeys@#2}{}% + \csdef{kvt@allcolumns@#2}{}% + \csdef{kvt@displaycols@#2}{}% \csdef{kvt@rowcount@#2}{0}% \csdef{kvt@rows@#2}{}% \csdef{kvt@headings@#2}{\kvt@defaultheader} @@ -102,34 +161,46 @@ \def\do##1{% \kvt@parsecolspec{#2}##1::\@undefined}% \kvt@dossvlist{#3}% + \csdef{kvt@headrowcount@#2}{1}% \csappto{kvt@headings@#2}{{\@nil}}% - \ifstrempty{#4} - {\csdef{kvt@headrowcount@#2}{1}} - {\kvt@parseheadrows{#2}{#4}}% + \kvt@parselayout{#4}{#2}% } \def\kvt@parsecolspec#1#2:#3:#4\@undefined{% + \def\kvt@@column{#2}% + \trim@spaces@in\kvt@@column + \expandafter\kvt@parsecolspec@i\expandafter{\kvt@@column}{#1}{#3}} +\newcommand\kvt@parsecolspec@i[3]{\kvt@parsecolspec@ii{#2}{#1}{#3}} +\newcommand\kvt@parsecolspec@ii[3]{% \def\kvt@@column{#1@#2}% - \setkeys[kvt]{Column}{#3}% + \ifinlistcs{#2}{kvt@allcolumns@#1} + {\kvt@error{Column name '#2' declared more than once in table type + '#1'}{Check '#2' for typos; column names declared so far:% + \forlistcsloop{ }{kvt@allcolumns@#1}}}{}% + \listcsadd{kvt@allcolumns@#1}{#2}% + \kvt@setkeys{#3}{Column}% \ifcsstring{kvt@col@hidden@#1@#2}{true}{}{% \cseappto{kvt@alignments@#1}{\csexpandonce{kvt@col@align@#1@#2}}% \ifcsvoid{kvt@col@head@#1@#2}% {\csappto{kvt@headings@#1}{{#2}}}% {\cseappto{kvt@headings@#1}{{\csexpandonce{kvt@col@head@#1@#2}}}}% - \listcsadd{kvt@colkeys@#1}{#2}% + \listcsadd{kvt@displaycols@#1}{#2}% }% \define@cmdkey[KeyValTable]{#1}{#2}[]{}% + \define@key[KeyValTable]{#1}{#2*}{% + \csdef{cmdKeyValTable@#1@#2}{##1}% + \csdef{kvt@@noformat@#1@#2}{1}}% \presetkeys[KeyValTable]{#1}{#2}{}% -} + \undef\kvt@@column} \newcommand\kvt@defaultheader{% - \noexpand\rowcolor{\cmdkvt@Table@headbg}% + \noexpand\kvt@rowcolorornot{\cmdkvt@Table@headbg}% \kvt@defaultheader@i} \newcommand\kvt@defaultheader@i[1]{% \kvt@ifnil{#1}{\noexpand\tabularnewline}{% \unexpanded{&}% \ifdefvoid\cmdkvt@Table@headalign - {\expandonce\cmdkvt@Table@headfmt\unexpanded{#1}} + {\expandonce\cmdkvt@Table@headformat{\unexpanded{#1}}} {\noexpand\multicolumn{1}{\expandonce\cmdkvt@Table@headalign} - {\expandonce\cmdkvt@Table@headfmt\unexpanded{#1}}}% + {\expandonce\cmdkvt@Table@headformat{\unexpanded{#1}}}}% \kvt@defaultheader@i}} \newcommand\kvt@ifnil[1]{% \ifx\@nil#1\relax @@ -138,79 +209,145 @@ \newcommand\kvt@HackIntercolSpace{% @{\hspace{-.5\arrayrulewidth}}} \newcommand\kvt@alltables{} +\newcommand\kvt@parselayout[2]{% + \def\kvt@@tname{#2}% + \kvt@setkeys{#1}{Layout}% + \undef\kvt@@tname} +\newcommand\kvt@parsecolgroups[2]{% + \begingroup + \def\kvt@@result{}% + \def\do##1{\kvt@parsecolgroup{#1}##1::\@undefined}% + \kvt@dossvlist{#2}% + \expandafter\endgroup\kvt@@result} +\def\kvt@parsecolgroup#1#2:#3:#4\@undefined{% + \ifinlistcs{#2}{kvt@allcolumns@#1}{\kvt@error + {Name `#2' cannot be used for a column group in table type `#1', + as it is already used for a column} + {Check the \string\NewKeyValTable{#1} for + the names of known columns and check `#2' for a typo.}}{}% + \ifinlistcs{#2}{kvt@grpcolkeys@#1}{\kvt@error + {Name `#2' is used twice in table type `#1'} + {Check the \string\NewKeyValTable{#1} for typos in the names of + columns groups.}}{}% + \def\kvt@@colgrp{#2}% + \kvt@setkeys{#3}{ColGroup}% + \kvt@checkcolgroupcs{kvt@colgrp@span@\kvt@@colgrp}{#1}{#2}% + \eappto\kvt@@result{% + \noexpand\define@cmdkey[KeyValTable]{#1}{#2}{% + \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}}}}% + }% + }% + \noexpand\listcsadd{kvt@grpcolkeys@#1}{#2}}} +\newcommand\kvt@checkcolgroup[3]{% + \def\kvt@@psvdo##1{% + \ifinlistcs{##1}{kvt@allcolumns@#2}{}{\kvt@error + {Column `##1' referenced in column group `#3' not known + in table type `#2'} + {Check the \string\NewKeyValTable{#2} for + the names of known columns and check `##1' for a typo.}}% + \ifcsvoid{kvt@@incolgrp@##1}{}{\kvt@error + {Column `##1' used more than once in column group `#3' of table + type `#2'} + {Check `##1' for a typo.}}% + \csdef{kvt@@incolgrp@##1}{#2}% + }\kvt@forpsvlist{\kvt@@psvdo}{#1}% + \def\kvt@@colgrp@n{0}% + \let\kvt@@colgrp@first\relax + \def\kvt@@status{0}% + \def\kvt@@coldo##1{% + \ifcsvoid{kvt@@incolgrp@##1} + {\expandafter\ifcase\kvt@@status \or + \def\kvt@@status{2}\fi}% + {\expandafter\ifcase\kvt@@status + \def\kvt@@status{1}\def\kvt@@colgrp@first{##1}% + \or\or + \kvt@error{Column group `\kvt@@colgrp' must consist of only + consecutive columns, but it is not}% + {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}}% + }\forlistcsloop{\kvt@@coldo}{kvt@displaycols@#2}} +\newcommand\kvt@checkcolgroupcs[3]{% + \expandafter\expandafter\expandafter + \kvt@checkcolgroup + \expandafter\expandafter\expandafter{\csname #1\endcsname}{#2}{#3}} \newcommand\kvt@parseheadrows[2]{% - \csdef{kvt@@colgroups@#1}{}% - \csdef{kvt@headrowcount@#1}{0}% - \bgroup + \ifstrempty{#2}{}{\kvt@parseheadrows@i{#2}{#1}}} +\newcommand\kvt@parseheadrows@i[2]{% + \csdef{kvt@@custheadrows@#2}{}% + \csdef{kvt@headrowcount@#2}{0}% + \begingroup \def\kvt@@parseheadrows{}% \def\do##1{% \def\kvt@@tmp{##1}\trim@post@space@in\kvt@@tmp% \expandafter\ifstrequal\expandafter{\kvt@@tmp}{::} {\appto\kvt@@parseheadrows{% - \cseappto{kvt@@colgroups@#1}{% - \csexpandonce{kvt@headings@#1}}}} - {\appto\kvt@@parseheadrows{\kvt@parseheadrow{#1}{##1}}}% - \appto\kvt@@parseheadrows{\csedef{kvt@headrowcount@#1}{% - \the\numexpr\csuse{kvt@headrowcount@#1}+1\relax}}% - }\kvt@dobrklist{#2}% - \expandafter\egroup\kvt@@parseheadrows - \csletcs{kvt@headings@#1}{kvt@@colgroups@#1}} + \cseappto{kvt@@custheadrows@#2}{% + \csexpandonce{kvt@headings@#2}}}} + {\appto\kvt@@parseheadrows{\kvt@parseheadrow{#2}{##1}}}% + \appto\kvt@@parseheadrows{\csedef{kvt@headrowcount@#2}{% + \the\numexpr\csuse{kvt@headrowcount@#2}+1\relax}}% + }\kvt@dobrklist{#1}% + \expandafter\endgroup\kvt@@parseheadrows + \csletcs{kvt@headings@#2}{kvt@@custheadrows@#2}} \newcommand\kvt@parseheadrow[2]{% - \bgroup + \begingroup \def\do##1{\kvt@parsehdcolspec{#1}##1::\@undefined}% \kvt@dossvlist{#2}% \let\kvt@@tmpgrphd\@empty \kvt@@span\z@ - \undef\kvt@@curgrp \undef\kvt@@lastgrp - \def\do##1{\letcs\kvt@@curgrp{kvt@@colgrpof@##1}% - \ifdefequal\kvt@@curgrp\kvt@@lastgrp + \undef\kvt@@curhd \undef\kvt@@lasthd + \def\do##1{\letcs\kvt@@curhd{kvt@@hdcellof@##1}% + \ifdefequal\kvt@@curhd\kvt@@lasthd {\advance\kvt@@span\@ne}% {\ifnum\kvt@@span>\z@ \expandafter\kvt@concludecolumn\fi - \ifdefvoid\kvt@@curgrp{}{\ifcsdef{kvt@@colgrpdone@\kvt@@curgrp}{% - \kvt@error{Column group `\kvt@@curgrp' must consist of only + \ifdefvoid\kvt@@curhd{}{\ifcsdef{kvt@@hdcelldone@\kvt@@curhd}{% + \kvt@error{Header cell `\kvt@@curhd' must consist of only consecutive columns, but it is not}% - {Compare `|\kvt@@curgrp|' to the column ordering as specified - in `\string\NewKeyValTable{#1}'}}{}}% - \kvt@@span\@ne \let\kvt@@lastgrp\kvt@@curgrp}% - }\dolistcsloop{kvt@colkeys@#1}% + {Compare `\string\kvt@@curhd' to the column ordering as + specified in `\string\NewKeyValTable{#1}'}}{}}% + \kvt@@span\@ne \let\kvt@@lasthd\kvt@@curhd}% + }\dolistcsloop{kvt@displaycols@#1}% \kvt@concludecolumn \appto\kvt@@tmpgrphd{\tabularnewline}% - \edef\do{\noexpand\csappto{kvt@@colgroups@#1}{% - \noexpand\noexpand\noexpand\rowcolor{\noexpand\cmdkvt@Table@headbg}% + \edef\do{\noexpand\csappto{kvt@@custheadrows@#1}{% + \unexpanded{\noexpand\kvt@rowcolorornot{\cmdkvt@Table@headbg}}% \noexpand\unexpanded{\expandonce{\kvt@@tmpgrphd}}}}% - \expandafter\egroup\do} + \expandafter\endgroup\do} +\newcommand\kvt@rowcolorornot[1]{\ifstrempty{#1}{}{\rowcolor{#1}}} \newcount\kvt@@span \newcommand\kvt@concludecolumn{% \ifdefequal\kvt@@tmpgrphd\@empty {\let\kvt@@extraalign\kvt@HackIntercolSpace} {\let\kvt@@extraalign\@empty}% \appto\kvt@@tmpgrphd{&}% - \ifdefvoid\kvt@@lastgrp{}{% + \ifdefvoid\kvt@@lasthd{}{% \eappto\kvt@@tmpgrphd{\noexpand\multicolumn {\the\kvt@@span} {\expandonce\kvt@@extraalign - \csexpandonce{kvt@@colgrp@align@\kvt@@lastgrp}} - {\csexpandonce{kvt@@colgrp@head@\kvt@@lastgrp}}}% - \cslet{kvt@@colgrpdone@\kvt@@lastgrp}{\@ne}}} + \csexpandonce{kvt@@hdcell@align@\kvt@@lasthd}} + {\csexpandonce{kvt@@hdcell@head@\kvt@@lasthd}}}% + \cslet{kvt@@hdcelldone@\kvt@@lasthd}{\@ne}}} \def\kvt@parsehdcolspec#1#2:#3:#4\@undefined{% \def\kvt@@colreg##1{% - \ifinlistcs{##1}{kvt@colkeys@#1}{} - {\kvt@error{Column `##1' referenced in column group `#2' not known + \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.}}% - \ifcsmacro{kvt@@colgrpof@##1} - {\kvt@error{Column `##1' used in more than one column group} + \ifcsmacro{kvt@@hdcellof@##1} + {\kvt@error{Column `##1' used in more than one header cell} {Check the fourth, optional argument of \string\NewKeyValTable and eliminate multiple occurrences of column `##1'.}} - {\csdef{kvt@@colgrpof@##1}{#2}}% + {\csdef{kvt@@hdcellof@##1}{#2}}% }\kvt@forpsvlist{\kvt@@colreg}{#2}% - \def\kvt@@colgrp{#2}% - \setkeys[kvt]{ColGroup}{#3}} -\define@key[kvt]{ColGroup}{head}{% - \csdef{kvt@@colgrp@head@\kvt@@colgrp}{#1}} -\define@key[kvt]{ColGroup}{align}{% - \csdef{kvt@@colgrp@align@\kvt@@colgrp}{#1}} -\presetkeys[kvt]{ColGroup}{align=c}{}% + \def\kvt@@hdcell{#2}% + \kvt@setkeys{#3}{HeadCell}} \newcounter{kvtRow} \newcounter{kvtTypeRow} \newcounter{kvtTotalRow} @@ -224,38 +361,45 @@ \csuse{the#2}} \newcounter{kvt@LabelCtr} \newenvironment{KeyValTable}[2][]{% - \bgroup% \def\Row{\kvt@AddKeyValRow {\noalign\bgroup}{\expandafter\egroup\kvt@@row}{#2}}% \kvt@SetOptions{#2}{#1}% \csuse{kvt@StartTable@\cmdkvt@Table@shape}{#2}% }{% - \csuse{kvt@EndTable@\cmdkvt@Table@shape}% - \egroup} + \csuse{kvt@EndTable@\cmdkvt@Table@shape}} \AfterEndEnvironment{KeyValTable}{% \csdef{kvt@rowcount@\kvt@@recenttable}{\thekvtTypeRow}} \newcommand\kvt@SetOptions[2]{% - \bgroup\edef\kvt@@do{\egroup\noexpand% - \setkeys[kvt]{Table}% - {\csexpandonce{kvt@options@#1},\unexpanded{#2}}% + \begingroup\edef\kvt@@do{\endgroup\noexpand% + \kvt@setkeys{\csexpandonce{kvt@options@#1},\unexpanded{#2}}{Table}% }\kvt@@do} -\newcommand\kvt@StartTabularlike[5]{% +\newcommand\kvt@StartTabularlike[2]{% \gdef\kvt@@recenttable{#2}% + \metatblAtEnd{#1}{\kvt@@endhook}\let\kvt@@endhook\relax% \ifbool{kvt@Table@showrules} {\def\kvt@@rule##1{\csuse{##1rule}}} {\def\kvt@@rule##1{}}% - \csuse{kvt@@patchenvend@#1}% + \appto\kvt@@endhook{\kvt@@rule{bottom}} + \ifdefempty\cmdkvt@Table@caption{}{% + \metatblHasCaption{#1} + {\appto\kvt@@endhook{\rowcolor{white}% + \caption{\cmdkvt@Table@caption}}% + \ifdefempty\cmdkvt@Table@label{}{% + \appto\kvt@@endhook{\expandafter% + \label\expandafter{\cmdkvt@Table@label}}}} + {\kvt@warn{Caption lost, table environment '#1' + does not support captions.}}}% \setcounter{kvtRow}{0}% \setcounter{kvtTypeRow}{\csuse{kvt@rowcount@#2}}% - \bgroup\edef\kvt@@do{\egroup - \ifbool{#4}{}{\noexpand\kvt@dottedrowcolors + \begingroup\edef\kvt@@do{\endgroup + \metatblIsTabu{#1}{}{\noexpand\kvt@dottedrowcolors {\ifbool{kvt@Table@showhead} {\the\numexpr\csuse{kvt@headrowcount@#2}+1\relax} {1}}% {\expandonce\cmdkvt@Table@rowbg}}% \expandafter\noexpand\csname #1\endcsname - \ifbool{#5} - {\ifbool{#4} + \metatblHasWidth{#1} + {\metatblIsTabu{#1} {to \expandonce\cmdkvt@Table@width} {{\expandonce\cmdkvt@Table@width}}} {}% @@ -264,51 +408,120 @@ \ifbool{kvt@Table@showhead} {\csuse{kvt@headings@#2}\noexpand\kvt@@rule{mid}} {}% - \ifbool{#4} - {\noexpand\taburowcolors 2{\expandonce\cmdkvt@Table@rowbg}}{}% - \ifbool{#3}{\noexpand\endhead}{}% + \metatblIsTabu{#1} + {\noexpand\kvt@taburowcolors{\expandonce\cmdkvt@Table@rowbg}}{}% + \metatblIsLong{#1}{\noexpand\endhead}{}% }\kvt@@do} -\newcommand\kvt@stepcounters[1][1]{% - \addtocounter{kvtRow}{#1}% - \addtocounter{kvtTypeRow}{#1}% - \addtocounter{kvtTotalRow}{#1}} -\newcommand\kvt@DefineStdTabEnv{\@dblarg\kvt@DefineStdTabEnv@i} -\newcommand\kvt@DefineStdTabEnv@i[6][]{% - \expandafter\newcommand\csname kvt@StartTable@#1\endcsname[1]{% - \kvt@StartTabularlike{#2}{##1}{#3}{#4}{#5}}% - \csedef{kvt@EndTable@#1}{% - \ifstrempty{#6}{\noexpand\kvt@@rule{bottom}}{}% - \expandafter\noexpand\csname end#2\endcsname}% - \ifstrempty{#6}{}{\csdef{kvt@@patchenvend@#2}{#6}}} -\kvt@DefineStdTabEnv{tabular}{false}{false}{false}{} -\kvt@DefineStdTabEnv{longtable}{true}{false}{false}{} -\kvt@DefineStdTabEnv{tabularx}{false}{false}{true}{% - \preto\TX@endtabularx{\toks@\expandafter{\the\toks@ - \kvt@@rule{bottom}}}} -\kvt@DefineStdTabEnv{xltabular}{true}{false}{true}{% - \preto\XLT@ii@TX@endtabularx{\toks@\expandafter{\the\toks@ - \kvt@@rule{bottom}}}} -\kvt@DefineStdTabEnv[onepage]{tabu}{false}{true}{true}{} -\kvt@DefineStdTabEnv[multipage]{longtabu}{true}{true}{true}{} \newcommand\kvt@dottedrowcolors[2]{% - \kvt@dottedrowcolors@i{#1}#2\@nil} + \ifstrempty{#2}{}{\kvt@dottedrowcolors@i{#1}#2\@nil}} \def\kvt@dottedrowcolors@i#1#2..#3\@nil{% \ifnumodd{#1} {\rowcolors{#1}{#2}{#3}} {\rowcolors{#1}{#3}{#2}}} -\define@cmdkey[kvt]{Row}{bg}{}% -\define@boolkey[kvt]{Row}{hidden}[true]{}% -\define@cmdkey[kvt]{Row}{below}{} -\define@cmdkey[kvt]{Row}{above}{} -\define@cmdkey[kvt]{Row}{around}{% - \def\cmdkvt@Row@above{#1}\def\cmdkvt@Row@below{#1}} +\newcommand\kvt@taburowcolors[1]{% + \ifstrempty{#1}{}{\taburowcolors{#1}}} +\newcommand\kvt@DefineStdTabEnv{\@dblarg\kvt@DefineStdTabEnv@i} +\newcommand\kvt@DefineStdTabEnv@i[2][]{% + \expandafter\newcommand\csname kvt@StartTable@#1\endcsname[1]{% + \kvt@StartTabularlike{#2}{##1}}% + \csedef{kvt@EndTable@#1}{% + \expandafter\noexpand\csname end#2\endcsname}} +\newcommand\kvt@DefineDualTabEnv[3]{% + \expandafter\newcommand\csname kvt@StartTable@#1\endcsname[1]{% + \kvt@ifhasXcolumns{##1} + {\csedef{kvt@EndTable@#1}{% + \expandafter\noexpand\csname end#3\endcsname}% + \kvt@StartTabularlike{#3}{##1}% + }{\csedef{kvt@EndTable@#1}{% + \expandafter\noexpand\csname end#2\endcsname}% + \kvt@StartTabularlike{#2}{##1}}}} +\newcommand\kvt@ifhasXcolumns[1]{% + \expandafter\expandafter\expandafter\metatbl@ifhasXcolumns + \expandafter\expandafter\expandafter{% + \csname kvt@alignments@#1\endcsname}} +\kvt@DefineStdTabEnv{tabular} +\kvt@DefineStdTabEnv{longtable} +\kvt@DefineStdTabEnv{tabularx} +\kvt@DefineStdTabEnv{xltabular} +\kvt@DefineStdTabEnv{tabu} +\kvt@DefineStdTabEnv{longtabu} +\define@boolkey[metatbl]{EnvProp}{isLong}{\metatbl@boolprop{isLong}{#1}} +\define@boolkey[metatbl]{EnvProp}{isTabu}{\metatbl@boolprop{isTabu}{#1}} +\define@boolkey[metatbl]{EnvProp}{hasWidth}{% + \metatbl@boolprop{hasWidth}{#1}} +\define@boolkey[metatbl]{EnvProp}{hasCaption}{% + \metatbl@boolprop{hasCaption}{#1}} +\define@cmdkey[metatbl]{EnvProp}{packages}{\metatbl@setprop{pkg}{#1}} +\define@key[metatbl]{EnvProp}{atEnd}{\metatbl@setprop[1]{atEnd}{#1}} +\newrobustcmd\metatblRegisterEnv[2]{% + \edef\metatbl@@envname{#1}% + \setkeys[metatbl]{EnvProp}{#2}} +\newcommand\metatbl@setprop[3][0]{% + \expandafter\newcommand + \csname metatbl@EnvProp@#2@\metatbl@@envname\endcsname[#1]{#3}} +\newcommand\metatbl@boolprop[2]{% + \providebool{metatbl@EnvProp@#1@\metatbl@@envname}% + \setbool{metatbl@EnvProp@#1@\metatbl@@envname}{#2}} +\newcommand\metatblIsLong[1]{\ifbool{metatbl@EnvProp@isLong@#1}} +\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\metatblUsePackage[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}}% + \docsvlist{#1}} +\newcommand\metatblAtEnd[2]{% #1=env-name, #2=code + \csname metatbl@EnvProp@atEnd@#1\endcsname{#2}} +\newcommand\metatbl@csnamearg[2]{% + \expandafter\expandafter\expandafter#1% + \expandafter\expandafter\expandafter{\csname#2\endcsname}} +\metatblRegisterEnv{tabular}{% + isLong=false, hasWidth=false, isTabu=false, hasCaption=false, + packages={}, + atEnd={\preto\endtabular{#1}}, +} +\metatblRegisterEnv{tabularx}{% + isLong=false, hasWidth=true, isTabu=false, hasCaption=false, + packages=tabularx, + atEnd={% + \preto\TX@endtabularx{\toks@\expandafter{\the\toks@#1}}% + \preto\XLT@i@TX@endtabularx{\toks@\expandafter{\the\toks@#1}}}, +} +\metatblRegisterEnv{longtable}{% + isLong=true, hasWidth=false, isTabu=false, hasCaption=true, + packages={longtable}, + atEnd={\preto\endlongtable{#1}}, +} +\metatblRegisterEnv{xltabular}{% + isLong=true, hasWidth=true, isTabu=false, hasCaption=true, + packages=xltabular, + atEnd={\preto\XLT@ii@TX@endtabularx{\toks@\expandafter{\the\toks@#1}}}, +} +\metatblRegisterEnv{tabu}{% + isLong=false, hasWidth=true, isTabu=true, hasCaption=false, + packages={tabu}, + atEnd={\preto\endtabular{#1}}, +} +\metatblRegisterEnv{longtabu}{% + isLong=true, hasWidth=true, isTabu=true, hasCaption=true, + packages={tabu,longtable}, + atEnd={\preto\endlongtable{#1}}, +} +\newrobustcmd\metatbl@ifhasXcolumns[1]{% + \begingroup + \def\metatbl@@branch{\@secondoftwo}% + \def\NC@rewrite@X{\def\metatbl@@branch{\@firstoftwo}\NC@find}% + \@mkpream{#1}% + \expandafter\endgroup\metatbl@@branch} \newcommand\kvt@AddKeyValRow[3]{% #1% \@ifnextchar[%] {\kvt@AddKeyValRow@i{#2}{#3}} {\kvt@AddKeyValRow@i{#2}{#3}[]}} \def\kvt@AddKeyValRow@i#1#2[#3]#4{% - \setkeys[kvt]{Row}{#3}% + \kvt@setkeys{#3}{Row}% \ifbool{kvt@Row@hidden} {\let\kvt@@row\@empty #1} {\kvt@AddKeyValRow@ii{#1}{#2}{#4}}} @@ -320,36 +533,152 @@ \expandonce\cmdkvt@Row@above}}}}% \ifdefvoid\cmdkvt@Row@bg{}{% \eappto\kvt@@row{\noexpand\rowcolor{\expandonce\cmdkvt@Row@bg}}}% - \expandafter\appto\expandafter\kvt@@row\expandafter{\kvt@@everyrow} + \ifbool{kvt@Row@uncounted}{}{% + \appto\kvt@@row{\noalign{\kvt@stepcounters}}}% \kvt@@span=0\relax \def\do##1{% \ifcsvoid{cmdKeyValTable@#2@##1} {\letcs\kvt@@cell{kvt@col@default@#2@##1}} - {\letcs\kvt@@cell{cmdKeyValTable@#2@##1}}% - \edef\kvt@@fmtcell{\csexpandonce{kvt@col@format@#2@##1}{% + {\letcs\kvt@@cell{cmdKeyValTable@#2@##1}% + \ifbool{kvt@Row@expandonce} + {\expandafter\let\expandafter\kvt@@cell\kvt@@cell}{}% + \ifbool{kvt@Row@expand} + {\protected@edef\kvt@@cell{\kvt@@cell}}{}}% + \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}% \ifnumgreater\kvt@@span{0} {\advance\kvt@@span\m@ne \ifstrempty\kvt@@cell{\def\kvt@@fmtcell{}}{}} {\appto\kvt@@row{&}}% \expandafter\kvt@CheckMulticolumn\kvt@@cell - \relax\relax\relax\relax\@undefined{#2}{##1}% + \relax\relax\relax\relax\@undefined \expandafter\appto\expandafter\kvt@@row\expandafter{\kvt@@fmtcell}% - }\dolistcsloop{kvt@colkeys@#2}% + }\dolistcsloop{kvt@displaycols@#2}% \appto\kvt@@row{\tabularnewline}% \ifdefvoid\cmdkvt@Row@below{}{% \eappto\kvt@@row{\noexpand\noalign{\noexpand\vspace{% \expandonce\cmdkvt@Row@below}}}}% #1} -\newcommand\kvt@everyrow[1]{\def\kvt@@everyrow{#1}} -\newcommand\kvt@@everyrow{} -\kvt@everyrow{\kvt@stepcounters}% -\def\kvt@CheckMulticolumn#1#2#3#4\@undefined#5#6{% +\newcommand\kvt@stepcounters[1][1]{% + \addtocounter{kvtRow}{#1}% + \addtocounter{kvtTypeRow}{#1}% + \addtocounter{kvtTotalRow}{#1}} +\def\kvt@CheckMulticolumn#1#2#3#4\@undefined{% \ifx#1\multicolumn \kvt@@span=#2\relax \advance\kvt@@span\m@ne \edef\kvt@@fmtcell{\unexpanded{\multicolumn{#2}{#3}}% - {\csexpandonce{kvt@col@format@#5@#6}{\expandonce{#4}}}}% + {\expandonce\kvt@@formatter{\expandonce{#4}}}}% \fi} +\newcommand\kvtNewRowStyle[2]{% + \ifcsundef{kvt@@rowstyle@#1} + {\csdef{kvt@@rowstyle@#1}{#2}} + {\kvt@error{Row style '#1' is already defined}{Use + \string\kvtRenewRowStyle\space to change an existing style.}}} +\newcommand\kvtRenewRowStyle[2]{% + \ifcsundef{kvt@@rowstyle@#1} + {\kvt@error{Row style '#1' is not defined} + {Use \string\kvtNewRowStyle\space to define a new row style.}} + {\csdef{kvt@@rowstyle@#1}{#2}}} +\newcommand\kvt@UseRowStyle[1]{% + \ifcsundef{kvt@@rowstyle@#1} + {\kvt@error{Row style '#1' is not defined} + {Use \string\kvtNewRowStyle\space to define a new row style.}} + {\kvt@setcskeys{kvt@@rowstyle@#1}{Row}}} +\newcommand\kvt@UseRowStyles[1]{% + \kvt@xkv@disablepreset[kvt]{Row}{% + \forcsvlist\kvt@UseRowStyle{#1}}} +\newcommand\kvt@xkv@disablepreset[3][KV]{% + \ifnumgreater{\XKV@depth}{1} + {#3} + {\kvt@xkv@savepreset{#1}{#2}{h}% + \kvt@xkv@savepreset{#1}{#2}{t}% + #3% + \kvt@xkv@restorepreset{#1}{#2}{h}% + \kvt@xkv@restorepreset{#1}{#2}{t}}} +\newcommand\kvt@xkv@savepreset[3]{% + \csletcs{kvt@@saved@preset#3}{XKV@#1@#2@preset#3}% + \csundef{XKV@#1@#2@preset#3}} +\newcommand\kvt@xkv@restorepreset[3]{% + \csletcs{XKV@#1@#2@preset#3}{kvt@@saved@preset#3}} +\newcommand\NewCollectedTable[2]{% + \ifcsvoid{kvt@@tnameof@#1} + {\csgdef{kvt@@tnameof@#1}{#2}} + {\kvt@error{Name '#1' for a row collection is already defined} + {Check for other \string\NewCollectedTable{#1}.}}} +\newcommand\CollectRow[3][]{% + \ifcsvoid{kvt@@tnameof@#2} + {\kvt@error{No row collection with name '#2' defined} + {Use \string\NewCollectedTable in the preamble to define it.}} + {% + \begingroup + \kvt@setkeys{#1}{Row}% + \kvt@colsetcskeys{kvt@@tnameof@#2}{#3}% + \endgroup + \kvt@protected@write\@auxout{\string\kvt@RecordedRow{#1}{#2}{% + \kvt@coldefaults{#2}% + #3}}% + }} +\newcommand\kvt@protected@write[2]{\protected@write{#1} + {\def\do##1{\def##1{\string##1}}% + \dolistloop{\kvt@@writeprotected@cmds}% + \forlistloop{\kvt@writeprotect@fmt}{\kvt@@numberformatters}} + {#2}} +\newcommand\kvt@writeprotect@fmt[1]{% + \csletcs{kvt@@fmt@#1}{#1}% + \csdef{#1}##1{% + \ifcsdef{kvt@@c@##1} + {\expandafter\string\csname#1\endcsname{##1}} + {\csname kvt@@fmt@#1\endcsname{##1}}}} +\newcommand\kvtDeclareTableMacros[1]{% + \forcsvlist{\listadd\kvt@@writeprotected@cmds}{#1}} +\newcommand\kvt@@writeprotected@cmds{} +\newcommand\kvtDeclareTableCounters[1]{% + \def\do##1{\cslet{kvt@@c@##1}\@ne}% + \docsvlist{#1}} +\newcommand\kvtDeclareCtrFormatters[1]{% + \def\do##1{\listeadd\kvt@@numberformatters{% + \expandafter\@gobble\string##1}}% + \docsvlist{#1}} +\newcommand\kvt@@numberformatters{} +\kvtDeclareTableMacros{\thekvtRow,\thekvtTypeRow,\thekvtTotalRow} +\kvtDeclareTableCounters{kvtRow,kvtTypeRow,kvtTotalRow} +\kvtDeclareCtrFormatters{\arabic,\alph,\Alph,\roman,\Roman,\fnsymbol} +\newcommand\kvt@coldefaults[1]{% + \kvt@coldefaults@i{\csuse{kvt@@tnameof@#1}}} +\newcommand\kvt@coldefaults@i[1]{% + \forlistcsloop{\kvt@coldefault{#1}}{kvt@displaycols@#1}} +\newcommand\kvt@coldefault[2]{\ifcsvoid{kvt@col@default@#1@#2}{}{% + #2={\csuse{kvt@col@default@#1@#2}},}} +\newcommand\kvt@RecordedRow[3]{% + \csgappto{kvt@@rowsof@#2}{\Row[{#1}]{#3}}} +\newcommand\ShowCollectedTable[2][]{% + \ifcsvoid{kvt@@tnameof@#2} + {\kvt@error{No row collection with name '#2' defined} + {Use \string\NewCollectedTable in the preamble to define it.}} + {\ifcsvoid{kvt@@rowsof@#2} + {\kvt@warn{No row data available for name '#2'. + A LaTeX rerun might be needed^^M + for the row data to be available}% + \kvt@tableofcname{#2}{#1}{???\tabularnewline}}% + {\kvt@tableofcname{#2}{#1}{\csuse{kvt@@rowsof@#2}}}}} +\newcommand\kvt@tableof[3]{% + \begin{KeyValTable}[{#2}]{#1}% + #3% + \end{KeyValTable}} +\newcommand\kvt@tableofcname[1]{\expandafter + \kvt@tableofcname@i\expandafter{\csname kvt@@tnameof@#1\endcsname}} +\newcommand\kvt@tableofcname@i[1]{\expandafter + \kvt@tableof\expandafter{#1}} +\newcommand\ShowKeyValTableFile[3][]{% + \IfFileExists{#3} + {\begin{KeyValTable}[{#1}]{#2}\@@input#3 \end{KeyValTable}}% + {\kvt@error{No KeyValTable file '#3'} + {Check whether the file really exists or whether there is a + typo in the argument '#3'}}} \newcommand\ShowKeyValTable[2][]{% \begin{KeyValTable}[#1]{#2}% \csuse{kvt@rows@#2}% @@ -357,23 +686,30 @@ \csdef{kvt@rows@#2}{}} \newcommand\AddKeyValRow[1]{% \kvt@AddKeyValRow - {\bgroup} - {\csxappto{kvt@rows@#1}{\expandonce{\kvt@@row}}\egroup} + {\begingroup} + {\csxappto{kvt@rows@#1}{\expandonce{\kvt@@row}}\endgroup} {#1}} \newenvironment{KeyValTableContent}[1]{% \def\Row{\AddKeyValRow{#1}}}{}% -\define@boolkey[kvt]{PackageOptions}[kvt@@]{noTabuPkg}[true]{} +\define@cmdkey[kvt]{PackageOptions}[kvt@@pkg@]{compat}{} \ExecuteOptionsX[kvt]{% - noTabuPkg=false, + compat=2.0, } \ProcessOptionsX[kvt]\relax -\ifbool{kvt@@noTabuPkg}{}{% - \RequirePackage{longtable,tabu}} -\DeclareListParser{\kvt@dossvlist}{;} -\DeclareListParser*{\kvt@forpsvlist}{+} -\DeclareListParser{\kvt@dobrklist}{\\} -\newcommand\kvt@error[2]{\PackageError{keyvaltable}{#1}{#2}} -\newcommand\kvt@warn[1]{\PackageWarning{keyvaltable}{#1}} +\newcommand\kvt@IfVersion[2]{% + \ifdimcomp{\kvt@@pkg@compat pt}{#1}{#2pt}} +\kvt@IfVersion{<}{2.0}{% + \metatblRequire{tabu,longtabu} + \kvt@DefineStdTabEnv[onepage]{tabu} + \kvt@DefineStdTabEnv[multipage]{longtabu} +}{% + \metatblRequire{tabularx,longtable,xltabular} + \kvt@DefineDualTabEnv{onepage}{tabular}{tabularx} + \kvt@DefineDualTabEnv{multipage}{longtable}{xltabular} +} +\kvt@IfVersion{<}{2.0}{% + \let\kvt@parselayout=\kvt@parseheadrows +}{} \endinput %% %% End of file `keyvaltable.sty'. -- cgit v1.2.3