% \iffalse meta-comment
%
% Copyright (C) 2016-2019 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 or (at your option) any later version.
% The latest version of this license is in:
%
%    http://www.latex-project.org/lppl.txt
%
% and version 1.2 or later is part of all distributions of LaTeX 
% version 1999/12/01 or later.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{keyvaltable.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{keyvaltable}
%<*package>
    [2019/03/17 v1.0 Package for filling tables using key-value lists]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{rgltxdoc}
\usepackage{etoc}
\setcounter{tocdepth}{2}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
% the following packages are additional for the examples
\usepackage{xintexpr}
\usepackage{makecell}
\usepackage{gensymb}% for \degree
\usepackage{tabularx}
\usepackage{longtable}
\usepackage{xspace}
\newcommand\thispackage{\pkgname{keyvaltable}\xspace}
\usepackage{keyvaltable}
\NewKeyValTable[
    showhead=false,headfmt={\bfseries\footnotesize},
    rowbg=black!7!white..black!3!white,
    showrules=false,
    shape=onepage]{GoalApproach}{
  id: align=r, default=(\alph{kvtRow}), head=\#;
  goal: align=X[l];
  approach: align={X[2,l]};
}
\begin{document}
  \DocInput{keyvaltable.dtx}
  \PrintChanges
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{0}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \changes{v0.1}{2016/03/13}{Initial version}
% \changes{v0.3b}{2018/11/01}{Package author's name change}
%
% \GetFileInfo{keyvaltable.dtx}
%
% \DoNotIndex{\newcommand,\newenvironment,\def,\gdef,\edef}
%
%
% \title{The \thispackage package\thanks{This document
%   corresponds to \thispackage~\fileversion, dated \filedate.
%   The package is available online at
%   \url{http://www.ctan.org/pkg/keyvaltable} and
%   \url{https://github.com/Ri-Ga/keyvaltable}.}}
% \author{Richard Grewe \\ \texttt{r-g+tex@posteo.net}}
%
% \maketitle
%
% \begin{abstract}\noindent
% The \thispackage package's main goal is to facilitate
% typesetting tables\ldots\medskip\\
% \begin{KeyValTable}{GoalApproach}
%   \Row{
%     goal={\ldots easily and yet still looking rather nicely},
%     approach={through horizontal rules and alternating row background
%       colors by default;}}
%   \Row{
%     goal={\ldots in a way that separates content from presentation},
%     approach={by table rows that are specified as lists of key-value
%       pairs, where the keys are column names and the corresponding
%       values are the content of the cell in this row in the respective
%       column;}}
%   \Row{
%     goal={\ldots with re-usable layout for tables of the same type},
%     approach={through named table types, of which each has a list of
%       columns as well as further properties such as the background
%       colors of rows; each column, in turn, has a name as well as
%       further properties such as the heading of the column and the
%       alignment of the column's content.}}
% \end{KeyValTable}
% \end{abstract}
%
% \etocmulticolstyle[2]{\section*{Contents}}
% \tableofcontents
% \clearpage
%
% \section{Usage}
%
% We start with a basic usage example. An explanation of the involved
% macros follows afterwards.\medskip
%
% \begin{LTXexample}[morekeywords={NewKeyValTable,Row,KeyValTable}]
% \NewKeyValTable{Recipe}{
%   amount:     align=r;
%   ingredient: align=l;
%   step:       align=X[l];
% }
% \begin{KeyValTable}{Recipe}
% \Row{amount=150g, ingredient=ice cream,
%   step=put into bowl}
% \Row{amount= 50g, ingredient=cherries,
%   step=heat up and add to bowl}
% \end{KeyValTable}
% \end{LTXexample}
% The example code first defines a new table type, |Recipe|, along with
% the columns that belong to this type. There are three columns
% (|amount|, |ingredient|, and |step|), whose specifications are separated
% with semicolons. After the separating |:|, for each column, the macro
% configures the column alignment using the |align| key. The alignments
% |r| (right) and |l| (left) are the standard |tabular| alignments; the
% |X[l]| alignment is provided by the \pkgname{tabu} package (see the
% documentation there), which is used by default for creating the
% tables.
%
% After the definition of the table type, the example creates a table of
% the newly defined type. For this, the example uses the |KeyValTable|
% environment and the |\Row| macro, once for each row. The parameter
% |Recipe| of the |KeyValTable| identifies the type of the table.
% Most notably, each row can now produced by a single macro in which the
% content of the individual cells can be specified by pairs such as
% |amount=150g|, which puts ``150g'' into the |amount| column of the
% respective row.
%
% The example above already shows that producing a rather nice-looking
% table -- including alternating row colors as well as horizontal rules
% -- without further ado. How the \thispackage package can be
% used in the general case and how its visual appearance can be
% customized is subject of the remainder of this section.
%
% \subsection{Table Type Definition}
%
% \NiceDescribeMacro{\NewKeyValTable}{\oarg{options}\marg{tname}\marg{colspecs}\oarg{headers}}
% Table types are defined via the |\NewKeyValTable| macro, where
% \begin{itemize}[noitemsep]
% \item \meta{tname} is the name of the table type,
% \item \meta{colspecs} is a semicolon-separated list of individual
%   column specifications,
%   and
% \item \meta{options}, if provided, specify table type options that
%   override the default table options; they must then be a
%   comma-separated list of \meta{property}|=|\meta{value} pairs;
%   the list of table options can be found at the introduction of the
%   |KeyValTable| environment on page~\pageref{page:table-options}.
% \item \meta{headers}, if provided, specifies custom table header rows.
%   This argument is further described in \cref{sec:colspan}.
%   If this argument is omitted, a single header row is produced
%   (unless |showhead=false| is provided as an option) and the
%   individual headers in this row are determined by \meta{colspec}.
% \end{itemize}
% Each column specification is of the form
% \begin{center}
%   \meta{colname}|:| \meta{property}|=|\meta{value}|,|
%   \meta{property}|=|\meta{value}|,|\ldots
% \end{center}
% In such a specification, \meta{colname} represents the name of the
% column. The \meta{property}|=|\meta{value} pairs configure certain
% properties of the column. The \meta{property} can be one of the
% following:
% \begin{KeyValTable}{KeyDesc}
% \Row{key=align,
%   desc={This property specifies the alignment of content in the
%     column.  The \meta{value} can be set to any column alignment
%     understood by the |tabu| environment of the \pkgname{tabu} package.
%     This particularly includes |l|, |c|, |r|, |p|, and |X|.},
%   default=l}
% \Row{key=default,
%   desc={This property specifies the default value of a cell in this
%     column, i.e., in case that a \cmd{\Row} does not provide content
%     for the cell.  By default (i.e., if unset for a column), this is
%     an empty string.},
%   default={\normalfont\itshape(empty)}}
% \Row{key=format,
%   desc={This property specifies a formatting macro for content of the
%     cell.  The macro can take one argument and is provided with the
%     content of the cell as its argument.
%     By default, the formatting macro takes the content as is
%     but puts a \cmd{\strut} before and after the content (to yield a
%     better vertical spacing).},
%   default=\cmd{\kvtStrutted}}
% \Row{key=head,
%   desc={This property specifies the content of the column's header
%     row. The default value for this property is the name of the
%     column.},
%   default={\normalfont\meta{colname}}}
% \Row{key=hidden,
%   desc={This property specifies whether a table column shall be
%     displayed or not. The \meta{value} for this property can be |true|
%     (to hide the cell; the default) or |false| (to display the
%     cell).},
%   default=false}
% \end{KeyValTable}
%
% \subsection{Typesetting Tables}\label{sec:typesetting-tables}
%
% The first possibility for typesetting a table using the
% \thispackage package, is via the |KeyValTable| environment,
% which the example at the beginning of this section shows.
% The second possibility is described in
% Section~\ref{sec:collected-tables}.
%
% \NiceDescribeEnv{KeyValTable}{\oarg{options}\marg{tname}}
% The |KeyValTable| environment creates a table of type \meta{tname}.
% The type \meta{tname} must have been created using |\NewKeyValTable|
% before. The environment itself already produces a table with the
% columns specified for the table type, produces a header row and some
% horizontal lines, and sets up background colors of rows.
%
% The \meta{options} override default configurations, if provided, and
% must then be a comma-separated list of \meta{property}|=|\meta{value}
% pairs. The following \meta{property} names are available:
% \begin{KeyValTable}{KeyDesc}
% \Row{key=shape\label{page:table-options},
%   desc={This property specifies the table's shape. For \meta{value},
%     the package currently supports |multipage| and |onepage| as well
%     as |tabular|, |tabularx|, and |longtable|.
%     In case of |multipage|, the table may span multiple pages and on
%     each page, the column header is repeated. In case of |onepage|,
%     the table does not split into multiple pages.
%     The remaining three values use the respective environment for
%     producing the table (see \cref{sec:AltTabEnv} for the effect).},
%   default=multipage}
% \Row{key=width,
%   desc={This property specifies the width of the table, if the
%     selected |shape| supports it (see \cref{sec:AltTabEnv}).},
%   default={\string\linewidth}}
% \Row{key=showhead,
%   desc={This property specifies whether the head row shall be shown.
%     The \meta{value} must be a Boolean (i.e., |true| or |false|),
%     where |true| specifies that the head row is shown and |false|
%     specifies that the head row is not shown.},
%   default=true}
% \Row{key=showrules,
%   desc={This property specifies whether top and bottom rules as well
%     as a rule below the head row are drawn (|true|) or not (|false|).},
%   default=true}
% \Row{key=headalign,
%   desc={This property specifies the alignment for header cells.
%     If left empty, each header cell receives the same alignment as the
%     respective column.},
%   default={\normalfont\itshape(empty)}}
% \Row{key=headfmt,
%   desc={This property specifies a format to be applied to all header
%     cells. By default, the property is empty, meaning that header
%     cells are formatted. Otherwise, the code provided as value to this
%     key is prepended to the text of the header cells.},
%   default={\normalfont\itshape(empty)}}
% \Row{key=headbg,
%   desc={This property specifies the background color of the head row.
%     The \meta{value} must be a single color specification that is
%     understood by the \pkgname{xcolor} package. The \meta{value} is
%     passed directly to the \cs{rowcolor} macro.},
%   default={black!14}}
% \Row{key=rowbg,
%   desc={This property specifies the background colors of content rows.
%     The format of the \meta{value} for this property must be
%     \meta{oddcolor}|..|\meta{evencolor}. The first row after the
%     header is colored with \meta{oddcolor}, the second row with
%     \meta{evencolor}, and so forth. Both colors must be understood by
%     the \pkgname{xcolor} package.},
%   default={white..black!10}}
% \end{KeyValTable}
% \vref{fig:TableOptionExamples} demonstrates the \meta{options} in
% examples.
% \begin{figure}
% \begin{LTXexample}[morekeywords={shape,showhead,rowbg}]
% \NewKeyValTable[shape=onepage,
%     showhead=false,
%     rowbg=blue!10..blue!15,
%   ]{TabOptions}{
%     opt: align=l, format=\texttt;
%     val: align=l, format=\texttt;}
% \begin{table}\centering
% \begin{KeyValTable}{TabOptions}
% \Row{opt=shape,  val=onepage}
% \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,headfmt}]
% \NewKeyValTable[showrules=false,headbg=blue!25,
%     headalign=c,headfmt=\bfseries,
%   ]{TabOptions2}{
%     opt: align=l, format=\texttt;
%     val: align=l, format=\texttt;}
% \begin{KeyValTable}{TabOptions2}
% \Row{opt=showrules, val=false}
% \Row{opt=headbg, val=blue!25}
% \Row{opt=headalign, val=c}
% \Row{opt=headfmt, val=\string\bfseries}
% \end{KeyValTable}
% \end{LTXexample}
% \caption{Examples for table options}
% \label{fig:TableOptionExamples}
% \end{figure}
%
%
% \NiceDescribeMacro{\Row}{\oarg{options}\marg{content}}
% A table row is produced by the |\Row| macro. The
% \meta{content} must be a comma-separated list of
% \meta{cname}|=|\meta{text} pairs. The \meta{cname} identifies a column
% that was registered for the table type \meta{tname}. The \meta{text}
% specifies the content of the cell in the respective column. Each
% column for which no \meta{text} is provided in \meta{content}, will
% result in a cell that is filled with the column's default value.
%
% The \meta{options} argument customizes row properties and is further
% explained in \cref{sec:RowOptions}.
%
% \subsection{Tables of Collected Rows}\label{sec:collected-tables}
%
% As an alternative to producing a table within a single environment,
% the \thispackage package offers a way to scatter individual
% rows throughout a document and display the full table later. This
% method can be useful when table rows are strongly connected to
% portions of text outside of the table. The method then allows
% specifying the rows together with the connected text rather than
% separately in the table environment.
% Table types for this method are defined via |\NewKeyValTable| as
% previously described.
%
% \NiceDescribeMacro{\AddKeyValRow}{\marg{tname}\marg{content}}
% A table row is produced by the
% |\AddKeyValRow| macro. The \meta{tname}
% identifies the table type and the \meta{content} provides the content
% of the cells in the row. The format of the \meta{content} is the same
% as for the |\Row| macro described in
% Section~\ref{sec:typesetting-tables}.
% 
% \NiceDescribeMacro{\ShowKeyValTable}{\oarg{options}\marg{tname}}
% A table of all the rows defined via |\AddKeyValRow| can be displayed
% by the |\ShowKeyValTable| macro. The
% parameters have the same meaning as for the |KeyValTable| environment.
% This macro resets the list of rows for the specified table type.
%
% \NiceDescribeEnv{KeyValTableContent}{\marg{tname}}
% For simplifying the addition of rows, the
% |KeyValTableContent| environment can be used. In this
% environment, the |\Row| macro can be used just like in the
% |KeyValTable| environment. The only difference is that the
% |KeyValTableContent| environment does not cause the table to be
% displayed. For displaying the content collected in
% |KeyValTableContent| environments, the |\ShowKeyValTable| macro can be
% used.
%
% The following example demonstrates the use, based on the previously
% defined |Recipe| table type.
% \begin{LTXexample}[morepreset=\NewKeyValTable{Recipe}{amount:align=r;ingredient:align=l;step:align=X[l]},morekeywords={AddKeyValRow,KeyValTableContent,ShowKeyValTable}]
% \AddKeyValRow{Recipe}{amount=3,
%      ingredient=balls of snow,
%      step=staple all 3 balls}
% \begin{KeyValTableContent}{Recipe}
% \Row{amount=1, ingredient=carrot,
%      step=stick into top ball}
% \Row{amount=2, ingredient=coffee beans,
%      step=put diagonally above carrot}
% \end{KeyValTableContent}
% \ShowKeyValTable{Recipe}
% \end{LTXexample}
%
% \subsection{Setting Global Defaults}
%
% \NiceDescribeMacro{\kvtSet}{\marg{options}}
% The \thispackage package allows changing the default values
% globally for the parameters of tables and columns. This can be done by
% using the |\kvtSet| macro.
%
% \begin{LTXexample}[morekeywords={kvtSet}]
% \kvtSet{headbg=red,default=?,align=r}
% \NewKeyValTable{Defaults}{x; y}
% \begin{KeyValTable}{Defaults}
% \Row{x=1}
% \Row{y=4}
% \end{KeyValTable}
% \end{LTXexample}
%
% Notice the use of the |\NewKeyValTable| in the example. Column
% properties, including the separating |:| can be omitted completely,
% making the definition of a table type very simple.
%
% \subsection{Row Numbering and Labeling}
%
% The mechanism of default column values enables a simple means for
% automatic row numbering. For this, one can use one of three row
% counters provided by the \thispackage package: |kvtRow|,
% |kvtTypeRow|, and |kvtTotalRow|. The counters are explained after the
% following example, which demonstrates the use for the case of the
% |kvtRow| counter.
%
% \begin{LTXexample}[morekeywords={thekvtRow,thekvtTypeRow}]
% \NewKeyValTable{Numbered1}{
%   line: align=r, head=\#,
%         default=\thekvtRow;
%   text: align=l, head=\textbf{Text}}
% \begin{KeyValTable}{Numbered1}
% \Row{text=First row}
% \Row{text=Second row}
% \end{KeyValTable}
% \end{LTXexample}
%
% \NiceDescribeCounter{kvtRow}{}
% The |kvtRow| counter counts the row in the \emph{current} table. The
% row number excludes the header row of the table. If the table spans
% multiple pages, the row number also excludes the repeated headings on
% subsequent pages.
%
% \NiceDescribeCounter{kvtTypeRow}{}
% The |kvtTypeRow| counter counts the rows in the current table and
% includes the number of rows of all previous tables of the same type.
%
% \NiceDescribeCounter{kvtTotalRow}{}
% The |kvtTotalRow| counter counts the rows in the current table and
% includes the number of rows of all previous tables produced using the
% \thispackage package.
%
% Row numbering can easily be combined with row labeling.
% The following example shows how the |format| column property can be
% used for this purpose.
% \begin{LTXexample}[morekeywords={kvtLabel}]
% \NewKeyValTable{Labeled}{
%   label: align=r, head=\textbf{\#},
%          format=\kvtLabel{kvtRow};
%   text:  align=l, head=\textbf{Text}}
% \begin{KeyValTable}{Labeled}
% \Row{text=First row, label=first}
% \Row{text=After row \ref{first}}
% \end{KeyValTable}
% \end{LTXexample}
%
% \NiceDescribeMacro{\kvtLabel}{\oarg{labelopts}\marg{counter}\marg{label}}
% The |\kvtLabel| macro shows the current value of the \meta{counter} --
% in particular |kvtRow|, |kvtTypeRow|, and |kvtTotalRow| -- and sets
% the \meta{label} to the value of \meta{counter}. When using the macro
% with the |format| property, only the first argument (\meta{counter})
% must be provided, as the above example shows. The second argument
% (\meta{label}) is provided by the respective cell content.
%
% The |\kvtLabel| macro should work well with packages that change the
% referencing, like \pkgname{cleveref} or \pkgname{varioref}. When using a
% package that adds an optional argument to the |\label| command (like
% \pkgname{cleveref} does), the \meta{labelopts} can be used to pass an
% optional argument to |\label|. This feature is demonstrated in
% \cref{sec:package-cleveref}.
%
%
% \subsection{Column Spanning}
% \label{sec:colspan}
%
% Combining multiple consecutive cells in a row to a single cell (aka
% column spanning) can serve several purposes.
% The \thispackage package supports the following purposes:
%
% \begin{enumerate}[noitemsep]
% \item grouping of columns through cells in the table's header that
%   span all cells in the group and assign a joint title to the group;
% \item individual combinations of cells in the table data.
% \end{enumerate}
%
% The remainder of this section describes how each of the purposes can
% be addressed in |KeyValTable| environments.
%
% \paragraph{Column groups in table headers}
%
% Column groups in table headers can be specified by the \meta{headers}
% parameter of |\NewKeyValTable|.
% The following two examples illustrate how this parameter can be used
% for specifying column groups.
% The first example produces a single header row in which two columns
% are grouped with a single header, one column has a normal header, and
% in which one column is not provided with a header.
% \begin{LTXexample}
% \NewKeyValTable{ColGroup}{
%   id:     align=r, default=\thekvtRow.;
%   amount: align=r; ingredient: align=l;
%   step:   align=X[l];
% }[
%   amount+ingredient: head=\textbf{ingredient};
%   step: head=\textbf{step}, align=l;
% ]
% \begin{KeyValTable}{ColGroup}
% \Row{amount=150g, ingredient=ice cream,
%   step=put into bowl}
% \Row{amount= 50g, ingredient=cherries,
%   step=heat up and add to bowl}
% \end{KeyValTable}
% \end{LTXexample}
%
% The second example shows how multiple header rows can be specified
% and, particularly, how the normal column headers can be displayed
% through the use of "|::|".
% \begin{LTXexample}[width=0.475\hsize]
% \NewKeyValTable{ColGroup2}{
%   date:   align=r, head=\textbf{date};
%   min/Berlin: align=r, head=min;
%   max/Berlin: align=r, head=max;
%   min/Paris:  align=r, head=min;
%   max/Paris:  align=r, head=max;
% }[
%   min/Berlin+max/Berlin+min/Paris+max/Paris:
%     head=\textbf{temperature}\\
%   min/Paris+max/Paris:   head=\textbf{Paris};
%   min/Berlin+max/Berlin: head=\textbf{Berlin}\\
%   ::
% ]
% \begin{KeyValTable}{ColGroup2}
% \Row{date=01.01.1970,
%      min/Berlin=0\degree C, max/Berlin=...}
% \end{KeyValTable}
% \end{LTXexample}
%
%
% The syntax for \meta{headers} is as
% follows:
% \begin{itemize}[noitemsep]
% \item \meta{headers} is a list, separated by "|\\|", where each
%   element in the list specifies the columns of a single header
%   \meta{row}.
% \item Each \meta{row}, in turn, is also a
%   list. The elements of this list are separated by "|;|" (as in the
%   columns specification of |\NewKeyValTable|) and each element
%   specifies a header \meta{cell}.
% \item Each \meta{cell} is of the form
%   \begin{center}
%     \meta{col}|+|\ldots|+|\meta{col}|:| \meta{property}|=|\meta{value}|,|
%     \meta{property}|=|\meta{value}|,|\ldots
%   \end{center}
%   where each \meta{col} is the name of a column.
%   The specified header cell then spans each of the listed columns.
%   The columns must be displayed consecutively, though not necessarily
%   in the same order in which they are specified in \meta{cell}.
% \item The \meta{property}|=|\meta{value} pairs configure certain
%   properties of the header cell. The \meta{property} can be one of the
%   following:
%   \begin{KeyValTable}{KeyDesc}
%   \Row{key=align,
%     desc={This property specifies the alignment of content in the
%       column.  The \meta{value} can be set to any column alignment
%       understood by the |tabu| environment of the \pkgname{tabu} package.
%       This particularly includes |l|, |c|, |r|, |p|, and |X|.},
%     default=c}
%   \Row{key=head,
%     desc={This property specifies the content of the column's header
%       row. The default value for this property is the name of the
%       column.}}
%   \end{KeyValTable}
% \end{itemize}
%
% \paragraph{Manual column spanning with \cmd{\multicolumn}}
% The |\multicolumn| macro can be used for the content of a cell.
% The effect of this is that a number of subsequent cells are spanned
% over with the content of the cell. The following example demonstrates
% the use.
% \begin{LTXexample}[width=0.475\hsize,morekeywords={multicolumn}]
% \NewKeyValTable{MultiCol}{
%   col1: align=l;
%   col2: align=l;
%   col3: align=l;}
% \begin{KeyValTable}{MultiCol}
%   \Row{col1=1, col2=\multicolumn{1}{r}{2}, col3=3}
%   \Row{col1=1, col2=\multicolumn{2}{c}{2+3}}
%   \Row{col1=\multicolumn{2}{c}{1+2}, col3=3}
%   \Row{col1=\multicolumn{3}{c}{1+2+3}}
% \end{KeyValTable}
% \end{LTXexample}
% A word of warning:
% The |\multicolumn| macro implicitly constrains the ordering of
% columns. For instance, in the above example, switching columns 2 and 3
% would lead to an error in the second row (because |col2| is the
% rightmost column and therefore cannot span two columns) and also in
% the third row (because |col1| spans two columns but the second, |col3|
% is not empty). Thus, column spanning via |\multicolumn| should be used
% with care.
%
% \subsection{Alternative Table Environments}
% \label{sec:AltTabEnv}
%
% Originally, the \thispackage package uses the \pkgname{tabu} package
% and |tabu|, resp. |longtabu| environments for typesetting the actual
% tables. Through the |shape| option of tables, the table environment
% used by \thispackage tables can be changed. \Vref{tab:TabEnv} compares
% the possible shapes/environments with regards to 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
% package(s) that must be loaded manually when the respective shapes are
% used.
% Examples can be found in \vref{fig:TableTypes}.
% \begin{table}[p]\centering
% \NewKeyValTable[shape=tabular,headfmt=\bfseries]{ShapeProps}{
%   shape: format=\texttt; env: format=\texttt, head=environment;
%   multipage: align=c;
%   Xcols: align=c, head=\texttt{X}-cols;
%   width: align=c;
%   packages: align=l;}
% \begin{KeyValTable}{ShapeProps}
% \Row{shape=onepage,   env=tabu,      multipage=no,  Xcols=yes, width=yes, packages={tabu}*}
% \Row{shape=multipage, env=longtabu,  multipage=yes, Xcols=yes, width=yes, packages={tabu*, longtable*}}
% \Row{shape=tabular,   env=tabular,   multipage=no,  Xcols=no,  width=no}
% \Row{shape=tabularx,  env=tabularx,  multipage=no,  Xcols=yes, width=yes, packages={tabularx}}
% \Row{shape=longtable, env=longtable, multipage=yes, Xcols=no,  width=no,  packages={longtable}}
% \end{KeyValTable}
% \smallskip\par\raggedright\footnotesize
% Packages marked with "*" only need to be loaded if automatic loading
% is not disabled via the |NoTabuPkg| option to the \thispackage
% package.
% \caption{Comparison of table shapes / environments}
% \label{tab:TabEnv}
% \end{table}
%
% \begin{figure}[p]
% \begin{LTXexample}[width=0.475\hsize,
%    morekeywords={tabular,longtable}]
% \NewKeyValTable[showrules=false]{ShapeNoX}{
%   id: align=l, default=\thekvtTypeRow;
%   l: align=l; c: align=c; r: align=r;}[
%   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}
% \end{KeyValTable}\\
% \begin{KeyValTable}[shape=longtable]{ShapeNoX}
%   \Row{l=left,   c=center,     r=right}
%   \Row{l=left-2, c=2-center-2, r=2-right}
% \end{KeyValTable}
% \end{LTXexample}
% \begin{LTXexample}[width=0.475\hsize,
%    morekeywords={tabularx,onepage,multipage}]
% \NewKeyValTable[showrules=false]{ShapeWithX}{
%   id: align=l, default=\thekvtTypeRow;
%   l: align=l; X: align=X; r: align=r;}[
%   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}
% \end{KeyValTable}\medskip\\
% \begin{KeyValTable}[shape=onepage]{ShapeWithX}
%   \Row{l=left,   X=expandable,   r=right}
%   \Row{l=left-2, X=expandable-2, r=2-right}
% \end{KeyValTable}
% \begin{KeyValTable}[shape=multipage]{ShapeWithX}
%   \Row{l=left,   X=expandable,   r=right}
%   \Row{l=left-2, X=expandable-2, r=2-right}
% \end{KeyValTable}
% \end{LTXexample}
% \caption{Examples for the shape option}
% \label{fig:TableTypes}
% \end{figure}
%
%
% \subsection{Special Row Formatting}\label{sec:RowOptions}
%
% Through the \meta{options} argument of the
%   |\Row|\oarg{options}\marg{content}
% and the
%   |\KeyValRow|\marg{tname}\oarg{options}\marg{content}
% macros, special options of the row can be configured.
% As with other option arguments of the \thispackage package, the
% options must be a comma-separated list of key-value pairs.
% The following table lists the supported option keys and their meaning.
%
% \begin{KeyValTable}{KeyDesc}
% \Row{key=hidden,
%   desc={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|.},
%   default=false}
% \Row{key=bg,
%   desc={This property specifies the background color for the
%     particular row. If left empty, the default color as determined by
%     the |rowbg| option of the table applies.},
%   default={\normalfont\itshape(empty)}}
% \Row{key=above,
%   desc={This property specifies extra vertical space above the row.
%     Note that this space is currently not colored with the row's
%     background color but with the page's background color.
%     The argument, if provided, is directly passed to \cmd{\vspace}.},
%   default={\normalfont\itshape(empty)}}
% \Row{key=below,
%   desc={Analogously to |above|, this property specifies extra vertical
%     space below the row.},
%   default={\normalfont\itshape(empty)}}
% \Row{key=around,
%   desc={This property is a short-hand for setting both, |above| and
%     |below|, to the same value.},
%   default={\normalfont\itshape(empty)}}
% \end{KeyValTable}
%
% The following example demonstrates the options.
% \begin{LTXexample}[morepreset=\NewKeyValTable{Recipe}{amount:align=r;ingredient:align=l;step:align=X[l]},morekeywords={hidden,above,bg}]
% \begin{KeyValTable}{Recipe}
% \Row{amount=150g, ingredient=ice cream,
%   step=put into bowl}
% \Row{amount= 50g, ingredient=cherries,
%   step=heat up and add to bowl}
% \Row[hidden]{amount=25g, ingredient=cream,
%   step=decorate on top}
% \Row[above=1ex,bg=red!10!white]{
%   step=serve with a smile}
% \end{KeyValTable}
% \end{LTXexample}
%
% \subsection{Rules Between Rows}
%
% Additional horizontal rules between rows can simply be added by
% placing the respective rule command between |\Row| commands.
% The following example demonstrates this possibility.
% \begin{LTXexample}[morepreset=\NewKeyValTable{Recipe}{amount:align=r;ingredient:align=l;step:align=X[l]},morekeywords={midrule}]
% \begin{KeyValTable}{Recipe}
% \Row{amount=150g, ingredient=ice cream,
%   step=put into bowl}
% \Row{amount= 50g, ingredient=cherries,
%   step=heat up and add to bowl}
% \midrule
% \Row{step=serve with a smile}
% \end{KeyValTable}
% \end{LTXexample}
%
%
% \section{Use with Other Packages}
%
% \subsection{Named References}\label{sec:package-cleveref}
%
% The |\kvtLabel| feature of the \thispackage package can be
% used together with named references, as provided by the
% \pkgname{cleveref} package. A name to a row label can be given by using
% the optional first argument to the |\kvtLabel| formatting macro and
% specifying the name to use using |\crefname|. The following example
% uses ``row'' for the optional argument and ``line'' for the displayed
% name of the reference.
% \begin{LTXexample}
% \usepackage{cleveref}
% \crefname{row}{line}{lines}
% \NewKeyValTable[headfmt=\bfseries]{NamedRef}{
%   label: align=r, head=Line,
%          format=\kvtLabel[row]{kvtRow};
%   text:  align=l, head=Text}
% \begin{KeyValTable}{NamedRef}
% \Row{text=First row, label=one}
% \Row{text=After \cref{one}}
% \end{KeyValTable}
% \end{LTXexample}
%
% \subsection{Computational Cells}
%
% The mechanism of cell formatting macros enables a simple means for
% automatically computing formulas contained in a column. This can be
% done, for instance using the \pkgname{xint} package and defining a
% custom format macro (here |\Math|) that takes over the computation.
% \begin{LTXexample}
% \usepackage{xintexpr}
% \newcommand\Math[1]{%
%    \xinttheexpr trunc(#1, 1)\relax}
% \NewKeyValTable{Calculating}{
%    type; value: align=r,format=\Math}
% \begin{KeyValTable}{Calculating}
% \Row{type=simple,   value=10+5.5}
% \Row{type=advanced, value=0.2*(9+2^8)}
% \end{KeyValTable}
% \end{LTXexample}
%
% \subsection{Cell Formatting}
%
% The \thispackage package can be used together with the
% \pkgname{makecell} package in at least two ways:
% \begin{enumerate}[noitemsep]
% \item formatting header cells using the |head| property of columns;
% \item formatting content cells using the |format| property of columns.
% \end{enumerate}
% The following example gives an impression.
% \begin{LTXexample}
% \usepackage{makecell}
% \renewcommand\theadfont{\bfseries}
% \renewcommand\theadalign{lt}
% \NewKeyValTable{Header}{
%    first:  head=\thead{short};
%    second: head=\thead{two\\ lines};}
% \begin{KeyValTable}{Header}
% \Row{first=just a, second=test}
% \end{KeyValTable}
% \end{LTXexample}
%
% \section{Related Packages}
%
% I'm not aware of any \LaTeX{} packages that pursue similar goals or
% provide similar functionality. The following \LaTeX{} packages provide
% loosely related functionalities to the \thispackage package.
%
% \begin{description}
% \item[\pkgname{ctable}:]
%   This package focuses on typesetting tables with captions and notes.
%   With this package, the specification of table content is quite
%   close to normal |tabular| environments, except that the package's
%   table creation is done via a macro, |\ctable|.
% \item[\pkgname{easytable}:]
%   This package provides an environment |TAB| which simplifies the
%   creation of tables with particular horizontal and vertical cell
%   alignments, rules around cells, and cell width distributions. In
%   that sense, the package aims at simpler table creation, like
%   \thispackage. However, the package does not pursue
%   separation of content from presentation or re-use of table layouts.
% \item[\pkgname{tabularkv}:]
%   Despite the similarity in the name, this package pursues a different
%   purpose. Namely, this package provides means for specifying table
%   options such as width and height through an optional key-value
%   argument to the |tabularkv| environment. This package does not use
%   a key-value like specification for the content of tables.
% \end{description}
%
% \section{Future Work}
%
% \begin{itemize}
% \item support for further table environments, such as
%   \pkgname{xltabular}: The existing code structure should make this
%   not too complicated. Particularly for \pkgname{xltabular},
%   a spurious "\verb!missing } inserted!" error occurs.
% \item improved row coloring that makes sure that the alternation
%   re-starts on continued pages of a table that spans several pages
% \end{itemize}
%
% \clearpage
%
% \StopEventually{}
%\iffalse
%<*package>
%\fi
%
% \section{Implementation}
% \addtocontents{toc}{\protect\setcounter{tocdepth}{0}}
%
% We use \pkgname{etoolbox} for some convenience macros that make the
% code more easily maintainable and use \pkgname{xkeyval} for options
% in key--value form. The \pkgname{trimspaces} package is used once for
% trimming spaces before a string comparison.
%    \begin{macrocode}
\RequirePackage{etoolbox}
\RequirePackage{xkeyval}
\RequirePackage{trimspaces}
%    \end{macrocode}
% We use \pkgname{booktabs} for nice horizontal lines and
% \pkgname{xcolor} for row coloring.
%    \begin{macrocode}
\PassOptionsToPackage{table}{xcolor}
\RequirePackage{xcolor}
\RequirePackage{booktabs}
%    \end{macrocode}
%
% \subsection{Setting Defaults}
%
% \begin{macro}{\kvtSet}
% The |\kvtSet|\marg{options} set the default options, which apply
% to all tables typeset with the package.
%    \begin{macrocode}
\newcommand\kvtSet[1]{\bgroup
  \def\kvt@@presetqueue{\egroup}
  \setkeys[kvt]{defaults}{#1}{}%
  \kvt@@presetqueue}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@lazypreset}
% The |\kvt@@lazypreset|\marg{family}\marg{head keys} macro collects a
% request collects a request for pre-setting \meta{head keys} in family
% key \meta{family}. Using this macro, one can avoid causing problems
% with using \pkgname{xkeyval}'s |\presetkeys| inside the \meta{function}
% defined for a key (e.g., via |\define@key|). The collected requests
% can be performed by expanding the |\kvt@@presetqueue| macro.
%    \begin{macrocode}
\newcommand\kvt@lazypreset[2]{%
  \appto\kvt@@presetqueue{\presetkeys[kvt]{#1}{#2}{}}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@addtableprop}
% The |\kvt@addtableprop|\marg{name}\marg{default} macro adds a new
% table option, named \meta{name} and with default value \meta{default}.
%    \begin{macrocode}
\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}{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@addchoicetableprop}
% The |\kvt@addchoicetableprop|\marg{name}\marg{default}\marg{choice}
% macro adds a new table option, named \meta{name} and with default
% value \meta{default} and possible values from the comma-separated
% list provided by \meta{choice}.
%    \begin{macrocode}
\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}{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@addbooltableprop}
% The |\kvt@addbooltableprop|\marg{name}\marg{default}
% macro adds a new table option, named \meta{name} and with default
% value \meta{default} and possible values being booleans (|true|,
% |false|).
%    \begin{macrocode}
\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}{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@addcolumnprop}
% The |\kvt@addcolumnprop|\marg{name}\marg{default} macro adds a new
% column option, named \meta{name} and with default value
% \meta{default}.
%    \begin{macrocode}
\newcommand\kvt@addcolumnprop[2]{%
%    \end{macrocode}
% The following makes the \meta{name} available as an option for
% |\kvtSet| for setting a global default value to this column option.
%    \begin{macrocode}
  \define@key[kvt]{defaults}{#1}{%
    \kvt@lazypreset{Column}{#1=##1}}%
  \presetkeys[kvt]{defaults}{#1=#2}{}%
%    \end{macrocode}
% The following makes the \meta{name} available as an option for
% the \meta{colspecs} of |\NewKeyValTable| for setting a default value
% to the particular column.
%    \begin{macrocode}
  \define@key[kvt]{Column}{#1}{%
    \csdef{kvt@col@#1@\kvt@@column}{##1}}%
  \presetkeys[kvt]{Column}{#1=#2}{}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@addchoicecolumnprop}
% The |\kvt@addchoicecolumnprop|\marg{name}\marg{initial}\marg{default}\marg{choice}
% macro adds a new column option, named \meta{name}, with initial value
% \meta{initial}, with default argument value \meta{default}, and
% possible values from the comma-separated list provided by
% \meta{choice}.
%    \begin{macrocode}
\newcommand\kvt@addchoicecolumnprop[4]{%
%    \end{macrocode}
% The following makes the \meta{name} available as an option for
% |\kvtSet| for setting a global default value to this column option.
%    \begin{macrocode}
  \define@choicekey[kvt]{defaults}{#1}{#4}[#3]{%
    \kvt@lazypreset{Column}{#1=##1}}%
  \presetkeys[kvt]{defaults}{#1=#2}{}%
%    \end{macrocode}
% The following makes the \meta{name} available as an option for
% the \meta{colspecs} of |\NewKeyValTable| for setting a default value
% to the particular column.
%    \begin{macrocode}
  \define@choicekey[kvt]{Column}{#1}{#4}[#3]%
    {\csdef{kvt@col@#1@\kvt@@column}{##1}}%
  \presetkeys[kvt]{Column}{#1=#2}{}%
}
%    \end{macrocode}
% \end{macro}
%
% The following are the known column properties and their defaults as
% well as the known table properties and their defaults.
% \changes{v0.2}{2016/05/21}{Added ``shape'' table option}
% \changes{v1.0}{2018/12/30}{Enabled default ``true'' for ``hidden''}
%    \begin{macrocode}
\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}
%    \end{macrocode}
% When adding further |shape| options below, ensure to also add a
% corresponding |\kvt@DefineStdTabEnv| counterpart further below in the
% code.
%    \begin{macrocode}
\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{}
%    \end{macrocode}
%
% \begin{macro}{\kvtTableOpt}
% The |\kvtTableOpt|\marg{optname} macro, inside a |KeyValTable|
% environment, expands to the value of the table option \meta{optname}.
%    \begin{macrocode}
\newcommand\kvtTableOpt[1]{\csname cmdkvt@Table@#1\endcsname}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvtStrutted}
% The |\kvtStrutted|\marg{arg} macro prefixes and suffixes
% the argument \meta{arg} with a |\strut|. When used for formatting
% cell content, this makes sure that there is some vertical space
% between the content of a cell and the top and bottom of the row.
% \changes{v0.3}{2016/06/06}{Fix for cells with vertical material}
%    \begin{macrocode}
\newcommand\kvtStrutted[1]{\strut #1\ifhmode\expandafter\strut\fi}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Declaring Key-Value Tables}
%
% \begin{macro}{\NewKeyValTable}
% The
% |\NewKeyValTable|\oarg{options}\marg{tname}\marg{colspecs}\oarg{headers}
% declares a new key-value table type, identified by the given
% \meta{tname}. The columns of the table type are specified by
% \meta{colspecs}. The optional \meta{options}, if given, override the
% default table options for tables of type \meta{tname}.
% \changes{v0.2}{2016/05/21}{Added table-type options}
% \changes{v1.0}{2019/02/03}{Added optional headers argument}
%    \begin{macrocode}
\newcommand\NewKeyValTable[3][]{%
  \@ifnextchar[%]
    {\kvt@NewKeyValTable{#1}{#2}{#3}}%
    {\kvt@NewKeyValTable{#1}{#2}{#3}[]}}
%    \end{macrocode}
% The
% |\kvt@NewKeyValTable|\marg{options}\marg{tname}\marg{colspecs}\oarg{headers}
% macro is an auxiliary macro used for parsing the fourth, optional
% argument of |\NewKeyValTable|.
%    \begin{macrocode}
\def\kvt@NewKeyValTable#1#2#3[#4]{%
%    \end{macrocode}
% First initialize the ``variables''.
%    \begin{macrocode}
  \csdef{kvt@options@#2}{#1}%
  \csdef{kvt@headings@#2}{}%
%    \end{macrocode}
% The following adds a zero-width column to the left of every table.
% This column serves the purpose of "holding" the code that
% \thispackage uses for formatting a row (e.g., parsing |\Row|
% arguments). This code is partly not expandable.
% The reason for not putting this code into the first actual colum of
% 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.
%    \begin{macrocode}
  \csedef{kvt@alignments@#2}{p{0pt}\expandonce\kvt@HackIntercolSpace}%
  \csdef{kvt@colkeys@#2}{}%
  \csdef{kvt@rowcount@#2}{0}%
  \csdef{kvt@rows@#2}{}%
  \csdef{kvt@headings@#2}{\kvt@defaultheader}
  \listadd\kvt@alltables{#2}%
%    \end{macrocode}
% Now parse \meta{colspecs}, a semicolon-separated list of individual
% column specifications, and add the columns to the table. Each
% |\do|\marg{colspec} takes the specification for a single column.
%    \begin{macrocode}
  \def\do##1{%
    \kvt@parsecolspec{#2}##1::\@undefined}%
  \kvt@dossvlist{#3}%
%    \end{macrocode}
% The following terminates the argument list of |\kvt@defaultheader|.
%    \begin{macrocode}
  \csappto{kvt@headings@#2}{{\@nil}}%
%    \end{macrocode}
% Finally, parse \meta{headers}, also a semicolon-separated list of
% individual column groups, where |\\| marks a new row of column groups.
% If \meta{headers} is omitted (or empty), then simply take the result
% of |\kvt@parsecolspec| as the header row.
%    \begin{macrocode}
  \ifstrempty{#4}
    {\csdef{kvt@headrowcount@#2}{1}}
    {\kvt@parseheadrows{#2}{#4}}%
}
%    \end{macrocode}
% The
% |\kvt@parsecolspec|\marg{tname}\meta{cname}|:|\meta{config}|:|\meta{empty}|\@undefined|
% takes a configuration \meta{config} for a column \meta{cname} in table
% \meta{tname} and adds the column with the configuration to the table.
%    \begin{macrocode}
\def\kvt@parsecolspec#1#2:#3:#4\@undefined{%
  \def\kvt@@column{#1@#2}%
  \setkeys[kvt]{Column}{#3}%
%    \end{macrocode}
% The following stores the column's properties. The column is only added
% if the |hidden| option is not set to |true|.
%    \begin{macrocode}
  \ifcsstring{kvt@col@hidden@#1@#2}{true}{}{%
    \cseappto{kvt@alignments@#1}{\csexpandonce{kvt@col@align@#1@#2}}%
%    \end{macrocode}
% Append the column heading to \cs{kvt@headings@\meta{tname}}, which
% collects arguments to |\kvt@defaultheader|. Hence, the appended tokens
% are enclosed in curly braces. If no |head| is specified for the
% column, \meta{cname} is used for the column head. Otherwise, the
% |head| value is used.
%    \begin{macrocode}
    \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}%
  }%
%    \end{macrocode}
% The following creates the column key that can be used by the row
% macros to set the content of the column's content in that row.
%    \begin{macrocode}
  \define@cmdkey[KeyValTable]{#1}{#2}[]{}%
  \presetkeys[KeyValTable]{#1}{#2}{}%
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\kvt@defaultheader}
% The |\kvt@defaultheader|\marg{head1}\ldots\marg{headn}|\@nil| macro,
% takes $n$ header cell titles, \meta{head1} to \meta{headn} and formats
% them based on the |headfmt| and |headalign| options.
% More precisely, when fully expanded, |\kvt@defaultheader| yields
% "\meta{rowcolor}|& |\meta{fmthead1}| & |\ldots| & |\meta{fmtheadn}|\tabularnewline|".
% In the above, \meta{rowcolor}=|\rowcolor{|\meta{headbg}|}|.
%    \begin{macrocode}
\newcommand\kvt@defaultheader{%
  \noexpand\rowcolor{\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}}
      {\noexpand\multicolumn{1}{\expandonce\cmdkvt@Table@headalign}
        {\expandonce\cmdkvt@Table@headfmt\unexpanded{#1}}}%
    \kvt@defaultheader@i}}
%    \end{macrocode}
% \begin{macro}{\kvt@ifnil}
% The |\kvt@ifnil|\marg{val}\marg{iftrue}\marg{iffalse} macro expands to
% \meta{iftrue} if \meta{val} is |\@nil|, and expands to \meta{iffalse}
% otherwise.
% Fixme: The |\relax| in the following is not fully ideal as it is not
% swallowed by the |\ifx| and therefore remains in the macro's
% expansion.
%    \begin{macrocode}
\newcommand\kvt@ifnil[1]{%
  \ifx\@nil#1\relax
    \expandafter\@firstoftwo\else
    \expandafter\@secondoftwo\fi}
%    \end{macrocode}
% \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|.
%    \begin{macrocode}
\newcommand\kvt@alltables{}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Custom Column Headers}
%
% \begin{macro}{\kvt@parseheadrows}
% The |\kvt@parseheadrows|\marg{tname}\marg{headers}
% macro parses the \meta{headers} argument of |\NewKeyValTable|.
%    \begin{macrocode}
\newcommand\kvt@parseheadrows[2]{%
  \csdef{kvt@@colgroups@#1}{}%
  \csdef{kvt@headrowcount@#1}{0}%
  \bgroup
  \def\kvt@@parseheadrows{}%
%    \end{macrocode}
% Now loop over \meta{headers} to split \meta{headers} by |\\|.
% Append each item, which specifies a single header row, to
% |\kvt@@parseheadrows| for subsequent parsing by |\kvt@parseheadrow|.
% If an item equals the special sequence "|::|", then the original
% header for the columns is added as header row.
%    \begin{macrocode}
  \def\do##1{%
    \def\kvt@@tmp{##1}\trim@post@space@in\kvt@@tmp%
    \expandafter\ifstrequal\expandafter{\kvt@@tmp}{::}
      {\appto\kvt@@parseheadrows{%
         \cseappto{kvt@@colgroups@#1}{%
           \csexpandonce{kvt@headings@#1}}}}
      {\appto\kvt@@parseheadrows{\kvt@parseheadrow{#1}{##1}}}%
%    \end{macrocode}
% Increment the header row counter for each |\\|-separated item of
% \meta{headers}.
%    \begin{macrocode}
    \appto\kvt@@parseheadrows{\csedef{kvt@headrowcount@#1}{%
      \the\numexpr\csuse{kvt@headrowcount@#1}+1\relax}}%
  }\kvt@dobrklist{#2}%
%    \end{macrocode}
% Finally, escape the inner group and overwrite the headings
% with the result of the parsing.
%    \begin{macrocode}
  \expandafter\egroup\kvt@@parseheadrows
  \csletcs{kvt@headings@#1}{kvt@@colgroups@#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@parseheadrow}
% The |\kvt@parseheadrow|\marg{tname}\marg{colspec} macro parses a
% single header row and appends the resulting table code to
% \cs{kvt@@colgroups@\meta{tname}}.
%    \begin{macrocode}
\newcommand\kvt@parseheadrow[2]{%
  \bgroup
%    \end{macrocode}
% First parse \meta{colspec}, populating the
% \cs{kvt@@colgrpof@\meta{colname}} macros that associate each column
% with the column group to which the column belongs.
%    \begin{macrocode}
  \def\do##1{\kvt@parsehdcolspec{#1}##1::\@undefined}%
  \kvt@dossvlist{#2}%
%    \end{macrocode}
% Initialize variables for the subsequent loop.
% The |\kvt@@tmpgrphd| macro collects the code for the cells of the
% current header row. The |\kvt@@span| counter specifies how many
% columns the current cell shall span.
% Finally, |\kvt@@curgrp| and |\kvt@@lastgrp| hold the name of the group
% in which the current column and, respectively, previous column are in.
% Each of the two macros is undefined if there is no such column group.
%    \begin{macrocode}
  \let\kvt@@tmpgrphd\@empty
  \kvt@@span\z@
  \undef\kvt@@curgrp \undef\kvt@@lastgrp
%    \end{macrocode}
% Next, loop over all displayed (non-hidden) columns stored in
% \cs{kvt@colkeys@\meta{tname}}. The following |\do|\marg{colname}
% collects (spanned) columns as specified in \meta{colspec}, in the
% ordering in which the table's columns are displayed. The spanned
% columns are stored in |\kvt@@tmpgrphd|.
%    \begin{macrocode}
  \def\do##1{\letcs\kvt@@curgrp{kvt@@colgrpof@##1}%
    \ifdefequal\kvt@@curgrp\kvt@@lastgrp
%    \end{macrocode}
% If the column group has not changed, simply increase the spanning
% counter.
%    \begin{macrocode}
      {\advance\kvt@@span\@ne}%
%    \end{macrocode}
% Otherwise, i.e., if the column group has changed, then conclude the
% previous column (if there was one) and reset the span to 1 (to count
% for the column in |\kvt@@curgrp|) and set |\kvt@@lastgrp| to the
% current one.
%    \begin{macrocode}
      {\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
            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}%
  \kvt@concludecolumn
%    \end{macrocode}
% Finally, conclude the whole header row and append the row to the
% overall list of rows, stored in \cs{kvt@@colgroups@\meta{tname}},
% while ending the current \hologo{TeX} group.
%    \begin{macrocode}
  \appto\kvt@@tmpgrphd{\tabularnewline}%
  \edef\do{\noexpand\csappto{kvt@@colgroups@#1}{%
    \noexpand\noexpand\noexpand\rowcolor{\noexpand\cmdkvt@Table@headbg}%
    \noexpand\unexpanded{\expandonce{\kvt@@tmpgrphd}}}}%
  \expandafter\egroup\do}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@@span}
% The counter |\kvt@@span| is used temporarily in macros for counting
% how many columns are spanned by column groups.
%    \begin{macrocode}
\newcount\kvt@@span
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@concludecolumn}
% The |\kvt@concludecolumn| macro appends a cell, potentially spanning
% multiple columns, to the row under construction (which is in
% |\kvt@@tmpgrphd|).
%    \begin{macrocode}
\newcommand\kvt@concludecolumn{%
%    \end{macrocode}
% The following conditional checks whether this is the first column
% group 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{&}%
  \ifdefvoid\kvt@@lastgrp{}{%
    \eappto\kvt@@tmpgrphd{\noexpand\multicolumn
      {\the\kvt@@span}
      {\expandonce\kvt@@extraalign
       \csexpandonce{kvt@@colgrp@align@\kvt@@lastgrp}}
      {\csexpandonce{kvt@@colgrp@head@\kvt@@lastgrp}}}%
%    \end{macrocode}
% Mark the column group as already used and concluded, such that another
% use of the same column group can be detected and raise an error.
%    \begin{macrocode}
    \cslet{kvt@@colgrpdone@\kvt@@lastgrp}{\@ne}}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@parsehdcolspec}
% The |\kvt@parsehdcolspec|\marg{tname}\meta{cname}|:|\meta{config}|:|\meta{empty}|\@undefined|
% macro parses a single header column (resp. column group), \meta{cname}.
% For a column group, \meta{cname} can consist of multiple,
% "+"-separated column names.
%    \begin{macrocode}
\def\kvt@parsehdcolspec#1#2:#3:#4\@undefined{%
%    \end{macrocode}
% First link the individual columns of a column group to the group.
% In this, ensure that no column is contained in more than one column
% group.
%    \begin{macrocode}
  \def\kvt@@colreg##1{%
    \ifinlistcs{##1}{kvt@colkeys@#1}{}
      {\kvt@error{Column `##1' referenced in column group `#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}
         {Check the fourth, optional argument of \string\NewKeyValTable
         and eliminate multiple occurrences of column `##1'.}}
      {\csdef{kvt@@colgrpof@##1}{#2}}%
  }\kvt@forpsvlist{\kvt@@colreg}{#2}%
%    \end{macrocode}
% Now parse the \meta{config} of the column, resp. column group.
%    \begin{macrocode}
  \def\kvt@@colgrp{#2}%
  \setkeys[kvt]{ColGroup}{#3}}
%    \end{macrocode}
% \end{macro}
%
% The following defines the options for header cells.
%    \begin{macrocode}
\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}{}%
%    \end{macrocode}
%
%
% \subsection{Row Numbering and Labeling}
%
% The following counters simplify row numbering in key-value tables.
% One can use a table-local counter (|kvtRow|), a table-type local
% counter (|kvtTypeRow|), and a global counter (|kvtTotalRow|).
%
% \begin{macro}{kvtRow}
% The |kvtRow| counter can be used by cells to get the current row
% number. This row number (in contrast to |taburow|) does not count
% table headers. That is, |kvtRow| provides the current \emph{content}
% row number, even in tables that are spread over multiple pages.
%    \begin{macrocode}
\newcounter{kvtRow}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{kvtTypeRow}
% The |kvtTypeRow| counter can be used by cells to get the current row
% number, including all previous rows of tables of the same type. This
% counter works together with the \cs{kvt@rowcount@\meta{tname}} macro,
% which keeps track of the individual row counts of the \meta{tname}
% type.
%    \begin{macrocode}
\newcounter{kvtTypeRow}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{kvtTotalRow}
% The |kvtTotalRow| counter can be used by cells to get the current row
% number, including all previous |KeyValTable| tables.
%    \begin{macrocode}
\newcounter{kvtTotalRow}
\setcounter{kvtTotalRow}{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvtLabel}
% The |\kvtLabel|\oarg{labelopts}\marg{counter}\marg{label} macro sets
% a label, named \meta{label}, for the current value of the \LaTeX{}
% counter named \meta{counter}.
% \changes{v0.2}{2016/05/22}{Added macro for row labeling}
% \changes{v0.3}{2016/06/09}{Robustified for use with, e.g., \pkgname{cleveref}}
%    \begin{macrocode}
\newcommand\kvtLabel[3][]{%
%    \end{macrocode}
% The following imitates a |\refstepcounter| in the sense of setting the
% current label, but it does not touch the \meta{counter} (in case
% someone added some custom hooks to them).
%    \begin{macrocode}
  \setcounter{kvt@LabelCtr}{\value{#2}}%
  \addtocounter{kvt@LabelCtr}{-1}%
  \refstepcounter{kvt@LabelCtr}%
%    \end{macrocode}
% Next, define the \meta{label} (if provided) and show the value of
% \meta{counter}.
%    \begin{macrocode}
  \ifstrempty{#3}{}{%
    \ifstrempty{#1}{\label{#3}}{\label[#1]{#3}}}%
  \csuse{the#2}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{kvt@LabelCtr}
% The |kvt@LabelCtr| counter is an auxiliary counter for setting labels,
% used by |\kvtLabel|.
%    \begin{macrocode}
\newcounter{kvt@LabelCtr}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Key-Value Table Content}
%
% \begin{environment}{KeyValTable}
% The |KeyValTable|\oarg{options}\marg{tname} environment encloses a new
% table whose type is identified by the given \meta{tname}. Table options
% can be overridden by providing \meta{options}.
%    \begin{macrocode}
\newenvironment{KeyValTable}[2][]{%
  \bgroup%
%    \end{macrocode}
% \begin{macro}{\Row}
% The |\Row|\oarg{options}\marg{content} macro is made available locally
% in the |KeyValTable| environment.
%    \begin{macrocode}
  \def\Row{\kvt@AddKeyValRow
    {\noalign\bgroup}{\expandafter\egroup\kvt@@row}{#2}}%
%    \end{macrocode}
% \end{macro}
%    \begin{macrocode}
  \kvt@SetOptions{#2}{#1}%
  \csuse{kvt@StartTable@\cmdkvt@Table@shape}{#2}%
}{%
  \csuse{kvt@EndTable@\cmdkvt@Table@shape}%
  \egroup}
%    \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}
% The |\kvt@SetOptions|\marg{tname}\marg{options} set the specific table
% options in the current environment, based on the options for table
% type \meta{tname} and the specific \meta{options}.
%    \begin{macrocode}
\newcommand\kvt@SetOptions[2]{%
  \bgroup\edef\kvt@@do{\egroup\noexpand%
    \setkeys[kvt]{Table}%
      {\csexpandonce{kvt@options@#1},\unexpanded{#2}}%
  }\kvt@@do}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Table Environment Code}
%
% \begin{macro}{\kvt@StartTabularlike}
% The
% |\kvt@StartTabularlike|\marg{env}\marg{tname}\marg{bLong}\marg{bTabu}\marg{bWidth}
% macro begins a table environment for the given table type \meta{tname}.
% The \meta{env} parameter specifies the concrete environment name.
% The parameters \meta{bLong}, \meta{bTabu}, and \meta{bWidth} are
% Boolean parameters (expecting value |true| or value |false|).
% They specify whether the table environment supports multi-page tables
% (\meta{bLong}), whether the environment is a \pkgname{tabu}
% environment (\meta{bTabu}), and whether the environment supports
% specifying the width of the table (\meta{bWidth}).
%    \begin{macrocode}
\newcommand\kvt@StartTabularlike[5]{%
%    \end{macrocode}
% The |\kvt@@recenttable| allows the |\AfterEndEnvironment| hook for
% |KeyValTable| to access the most recent table type.
%    \begin{macrocode}
  \gdef\kvt@@recenttable{#2}%
%    \end{macrocode}
% \changes{v1.0}{2019/02/18}{Implemented \texttt{showrules} option}
%    \begin{macrocode}
  \ifbool{kvt@Table@showrules}
    {\def\kvt@@rule##1{\csuse{##1rule}}}
    {\def\kvt@@rule##1{}}%
  \csuse{kvt@@patchenvend@#1}%
  \setcounter{kvtRow}{0}%
  \setcounter{kvtTypeRow}{\csuse{kvt@rowcount@#2}}%
%    \end{macrocode}
% In |\kvt@@do|, the start code for the environment, including the
% header rows, is gathered, with expansion to fill in all the table
% settings and options.
%    \begin{macrocode}
  \bgroup\edef\kvt@@do{\egroup
    \ifbool{#4}{}{\noexpand\kvt@dottedrowcolors
      {\ifbool{kvt@Table@showhead}
        {\the\numexpr\csuse{kvt@headrowcount@#2}+1\relax}
        {1}}%
      {\expandonce\cmdkvt@Table@rowbg}}%
%    \end{macrocode}
% \changes{v1.0}{2019/03/09}{Added \texttt{width} option}
%    \begin{macrocode}
    \expandafter\noexpand\csname #1\endcsname
      \ifbool{#5}
        {\ifbool{#4}
          {to \expandonce\cmdkvt@Table@width}
          {{\expandonce\cmdkvt@Table@width}}}
        {}%
      {\csexpandonce{kvt@alignments@#2}}%
    \noexpand\kvt@@rule{top}%
%    \end{macrocode}
% \changes{v0.3}{2016/06/05}{Added \texttt{showhead} option}
%    \begin{macrocode}
    \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}{}%
  }\kvt@@do}
%    \end{macrocode}
% \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.
%    \begin{macrocode}
\newcommand\kvt@stepcounters[1][1]{%
  \addtocounter{kvtRow}{#1}%
  \addtocounter{kvtTypeRow}{#1}%
  \addtocounter{kvtTotalRow}{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@DefineStdTabEnv}
% The
% |\kvt@DefineStdTabEnv|\oarg{shape}\marg{env}\marg{bLong}\marg{bTabu}\marg{bWidth}\marg{endpatch}
% macro defines the macros needed for the given \meta{shape} value.
% If \meta{shape} is omitted, \meta{env} (the name of the environment to
% use for the shape) is used as \meta{shape} value.
% The \meta{endpatch} parameter expects macro code that shall be run
% at the beginning of the |KeyValTable| environment to (locally) patch
% macros related to the end code of \meta{env} for ensuring
% that the bottom rule, |\kvt@@rule{bottom}|, is displayed.
% If \meta{endpatch} is empty, the rule is displayed via
% \cs{kvt@EndTable@\meta{shape}}. Otherwise,
% \cs{kvt@EndTable@\meta{shape}} equals \cs{end\meta{env}}.
% Environments such as |tabularx| require the latter to parse for the
% end of the environment.
% The parameters \meta{bLong}, \meta{bTabu}, and \meta{bWidth}
% are the same as for |\kvt@StartTabularlike|.
%
% Note: In the future, the macro could automatically add \meta{option}
% to the list of possible values for the |shape| option.
%    \begin{macrocode}
\newcommand\kvt@DefineStdTabEnv{\@dblarg\kvt@DefineStdTabEnv@i}
\newcommand\kvt@DefineStdTabEnv@i[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}}}
%    \end{macrocode}
% \end{macro}
%
% The following lines define the macros for the various table shapes /
% environments.
%    \begin{macrocode}
\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}{}
%    \end{macrocode}
%
% \begin{macro}{\kvt@dottedrowcolors}
% The |\kvt@dottedrowcolors|\marg{start-row}\marg{colors} sets up row
% colors using the |\rowcolors| macro of \pkgname{xcolor}.
% The \marg{colors} parameter expects arguments of the form
% "\meta{color1}|..|\meta{color2}" (the syntax used for the |rowbg|
% option. The row colors then alternate between \meta{color1} and
% \meta{color2}, starting with \meta{color1} in \meta{start-row}.
% This macro substitutes |\taburowcolors| for non-\pkgname{tabu}
% environments.
%    \begin{macrocode}
\newcommand\kvt@dottedrowcolors[2]{%
  \kvt@dottedrowcolors@i{#1}#2\@nil}
\def\kvt@dottedrowcolors@i#1#2..#3\@nil{%
%    \end{macrocode}
% Since |\rowcolors| expects its color arguments to specify the odd and
% even color, we swap arguments depending on the parity of
% \meta{start-row} to ensure \meta{color1} is applied to
% \meta{start-row}.
%    \begin{macrocode}
  \ifnumodd{#1}
    {\rowcolors{#1}{#2}{#3}}
    {\rowcolors{#1}{#3}{#2}}}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Environment-Independent Parts}
%
% The following block declares the known row options.
%    \begin{macrocode}
\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}}
%    \end{macrocode}
%
% \begin{macro}{\kvt@AddKeyValRow}
% The
% |\kvt@AddKeyValRow|\marg{pre}\marg{post}\marg{tname}\oarg{options}\marg{content}
% macro composes a row for the table of type \meta{tname} from the given
% \meta{content} and \meta{options}. The \meta{content} is a
% key-value list that specifies the content of the individual cells in
% the row. The result is returned in macro |\kvt@@row|.
% The arguments \meta{pre} and \meta{post} are expanded at the very
% beginning, resp.\@ end of the macro.
% They allow to control grouping (|\bgroup| and |\egroup|) as well as
% table placement via |\noalign|.
% \changes{v1.0}{2019/03/17}{Added \oarg{options}}
%    \begin{macrocode}
\newcommand\kvt@AddKeyValRow[3]{%
  #1%
%    \end{macrocode}
% It's essential that \meta{pre} above comes even before |\@ifnextchar|
% and, therefore, cannot be moved into |\kvt@AddKeyValRow@i|:
% The |\@ifnextchar| is not fully expandable and therefore any
% |\noalign| (in \meta{pre}) following |\@ifnextchar| would lead to
% "misplaced |\noalign|" errors.
%    \begin{macrocode}
  \@ifnextchar[%]
    {\kvt@AddKeyValRow@i{#2}{#3}}
    {\kvt@AddKeyValRow@i{#2}{#3}[]}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\kvt@AddKeyValRow@i}
% The
% |\kvt@AddKeyValRow@i|\marg{post}\marg{tname}\oarg{options}\marg{content}
% macro parses \meta{options} and evaluates the |hidden| option.
%    \begin{macrocode}
\def\kvt@AddKeyValRow@i#1#2[#3]#4{%
  \setkeys[kvt]{Row}{#3}%
  \ifbool{kvt@Row@hidden}
    {\let\kvt@@row\@empty #1}
    {\kvt@AddKeyValRow@ii{#1}{#2}{#4}}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\kvt@AddKeyValRow@ii}
% The
% |\kvt@AddKeyValRow@ii|\marg{post}\marg{tname}\marg{content}
% macro mainly processes \meta{content} as well as \meta{options}
% that have already been parsed by |\kvt@AddKeyValRow@i|.
%    \begin{macrocode}
\def\kvt@AddKeyValRow@ii#1#2#3{%
  \setkeys[KeyValTable]{#2}{#3}%
%    \end{macrocode}
% Initialize and first add the |\noalign| material to the row.
%    \begin{macrocode}
  \def\kvt@@row{}%
  \ifdefvoid\cmdkvt@Row@above{}{%
    \eappto\kvt@@row{\noexpand\noalign{\noexpand\vspace{%
      \expandonce\cmdkvt@Row@above}}}}%
  \ifdefvoid\cmdkvt@Row@bg{}{%
    \eappto\kvt@@row{\noexpand\rowcolor{\expandonce\cmdkvt@Row@bg}}}%
%    \end{macrocode}
% Place the |everyrow| hook after |\noalign|.
%    \begin{macrocode}
  \expandafter\appto\expandafter\kvt@@row\expandafter{\kvt@@everyrow}
%    \end{macrocode}
% The following loop uses |\do|\marg{cname} to append the content of
% all columns (in the given format and using the given default value),
% where each column value is in
% \cs{cmdKeyValTable@\meta{tname}@\meta{cname}}.
% Note that currently the default value is formatted using the given
% format macro -- a design decision.
% \changes{v1.0}{2019/02/03}{Added \cs{multicolumn} support}
%    \begin{macrocode}
  \kvt@@span=0\relax
  \def\do##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}}%
%    \end{macrocode}
% Separately also already create the formatted content.
%    \begin{macrocode}
    \edef\kvt@@fmtcell{\csexpandonce{kvt@col@format@#2@##1}{%
      \expandonce\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.
%    \begin{macrocode}
    \ifnumgreater\kvt@@span{0}
      {\advance\kvt@@span\m@ne
       \ifstrempty\kvt@@cell{\def\kvt@@fmtcell{}}{}}
      {\appto\kvt@@row{&}}%
%    \end{macrocode}
% Now check whether the cell itself spans multiple columns.
%    \begin{macrocode}
    \expandafter\kvt@CheckMulticolumn\kvt@@cell
      \relax\relax\relax\relax\@undefined{#2}{##1}%
    \expandafter\appto\expandafter\kvt@@row\expandafter{\kvt@@fmtcell}%
  }\dolistcsloop{kvt@colkeys@#2}%
%    \end{macrocode}
% Finally, add the concluding newline for the row as well as
% the vertical space after the row, if requested.
%    \begin{macrocode}
  \appto\kvt@@row{\tabularnewline}%
  \ifdefvoid\cmdkvt@Row@below{}{%
    \eappto\kvt@@row{\noexpand\noalign{\noexpand\vspace{%
      \expandonce\cmdkvt@Row@below}}}}%
%    \end{macrocode}
% At the very end of the expansion text, put \meta{post}.
%    \begin{macrocode}
  #1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@everyrow}
% The |\kvt@everyrow|\marg{code} registers \meta{code} to be included in
% the first (invisible) cell of every row.
%    \begin{macrocode}
\newcommand\kvt@everyrow[1]{\def\kvt@@everyrow{#1}}
\newcommand\kvt@@everyrow{}
%    \end{macrocode}
% \end{macro}
% Initialize the hook for every row to increment the row counters.
%    \begin{macrocode}
\kvt@everyrow{\kvt@stepcounters}%
%    \end{macrocode}
%
% \begin{macro}{\kvt@CheckMulticolumn}
% The
% |\kvt@CheckMulticolumn|\marg{arg1}\marg{arg2}\marg{arg3}\marg{arg4}|\@undefined|\linebreak[4]\marg{tname}\marg{colname}
% 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).
%    \begin{macrocode}
\def\kvt@CheckMulticolumn#1#2#3#4\@undefined#5#6{%
  \ifx#1\multicolumn
%    \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
%    \end{macrocode}
% Second, move the defined cell format to inside of the \meta{item}
% argument of |\multicolumn| rather than around the |\multicolumn|.
%    \begin{macrocode}
    \edef\kvt@@fmtcell{\unexpanded{\multicolumn{#2}{#3}}%
      {\csexpandonce{kvt@col@format@#5@#6}{\expandonce{#4}}}}%
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Collecting Key-Value Table Content}
%
% \begin{macro}{\ShowKeyValTable}
% The |\ShowKeyValTable|\oarg{options}\marg{tname} macro shows a table
% of type \meta{tname} with given \meta{options}. The rows must have
% been collected using |\Row| in |KeyValTableContent| environments or
% using |\AddKeyValRow|.
%    \begin{macrocode}
\newcommand\ShowKeyValTable[2][]{%
  \begin{KeyValTable}[#1]{#2}%
    \csuse{kvt@rows@#2}%
  \end{KeyValTable}%
  \csdef{kvt@rows@#2}{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\AddKeyValRow}
% The |\AddKeyValRow|\marg{tname}\oarg{options}\marg{content} adds a row
% with a given \meta{content} to the existing content for the next table
% of type \meta{tname} that is displayed with |\ShowKeyValTable|. The
% \meta{content} and \meta{options} parameters are the same as with
% |\kvt@AddKeyValRow|.
% The resulting row (|\kvt@@row|) is globally appended to
% \cs{kvt@rows@\meta{tname}}.
%    \begin{macrocode}
\newcommand\AddKeyValRow[1]{%
  \kvt@AddKeyValRow
    {\bgroup}
    {\csxappto{kvt@rows@#1}{\expandonce{\kvt@@row}}\egroup}
    {#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{KeyValTableContent}
% The |KeyValTableContent|\marg{tname} environment acts as a container
% in which rows can be specified without automatically being displayed.
% In this environment, rows can be specified via the
% |\Row|\marg{content} macro, which is supposedly shorter than using
% |\AddKeyValRow|\meta{tname}\meta{content}.
%    \begin{macrocode}
\newenvironment{KeyValTableContent}[1]{%
  \def\Row{\AddKeyValRow{#1}}}{}%
%    \end{macrocode}
% \end{environment}
%
%
% \subsection{Package Options}
%
% The \pkgname{tabu} is used by default for typesetting the tables,
% additionally with \pkgname{longtable} for tables that can span
% multiple pages.
% If the default packages are never used or the \pkgname{tabu} package
% shall be loaded manually, the |noTabuPkg| option can be used.
%    \begin{macrocode}
\define@boolkey[kvt]{PackageOptions}[kvt@@]{noTabuPkg}[true]{}
%    \end{macrocode}
%
% Next, set default package options and process them.
%    \begin{macrocode}
\ExecuteOptionsX[kvt]<PackageOptions>{%
  noTabuPkg=false,
}
\ProcessOptionsX[kvt]<PackageOptions>\relax
%    \end{macrocode}
%
% Finally, implement the outcome of the options parsing.
%    \begin{macrocode}
\ifbool{kvt@@noTabuPkg}{}{%
  \RequirePackage{longtable,tabu}}
%    \end{macrocode}
%
%
% \subsection{Auxiliary Code}
%
% \begin{macro}{\kvt@dossvlist}
% The |\kvt@dossvlist|\marg{list} macro parses a semicolon-separated
% list and runs |\do|\meta{item} for every element of the list.
%    \begin{macrocode}
\DeclareListParser{\kvt@dossvlist}{;}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@forpsvlist}
% The |\kvt@forpsvlist|\marg{handler}\marg{list} parses a `+'-separated list.
%    \begin{macrocode}
\DeclareListParser*{\kvt@forpsvlist}{+}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@dobrklist}
% The |\kvt@dobrklist|\marg{list} parses a `|\\|'-separated list.
%    \begin{macrocode}
\DeclareListParser{\kvt@dobrklist}{\\}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kvt@error}
% \begin{macro}{\kvt@warn}
%    \begin{macrocode}
\newcommand\kvt@error[2]{\PackageError{keyvaltable}{#1}{#2}}
\newcommand\kvt@warn[1]{\PackageWarning{keyvaltable}{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%\iffalse
%</package>
%\fi
% \Finale
\endinput
