texlive[65416] Master/texmf-dist: keyvaltable (31dec22)

commits+karl at tug.org commits+karl at tug.org
Sat Dec 31 21:42:18 CET 2022


Revision: 65416
          http://tug.org/svn/texlive?view=revision&revision=65416
Author:   karl
Date:     2022-12-31 21:42:17 +0100 (Sat, 31 Dec 2022)
Log Message:
-----------
keyvaltable (31dec22)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/keyvaltable/README.md
    trunk/Master/texmf-dist/doc/latex/keyvaltable/keyvaltable.pdf
    trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx
    trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins
    trunk/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty

Modified: trunk/Master/texmf-dist/doc/latex/keyvaltable/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/keyvaltable/README.md	2022-12-31 20:41:57 UTC (rev 65415)
+++ trunk/Master/texmf-dist/doc/latex/keyvaltable/README.md	2022-12-31 20:42:17 UTC (rev 65416)
@@ -3,7 +3,7 @@
 
 Copyright (C) 2016-2020 Richard Grewe
 
-Released under the [LaTeX Project Public License](http://www.latex-project.org/lppl/) version 1.2 or later
+Released under the [LaTeX Project Public License](http://www.latex-project.org/lppl/) version 1.3c or later
 
 ## Purpose
 
@@ -52,19 +52,15 @@
 
 To build the documentation of the `keyvaltable` package, you additionally
 need the following classes and packages (including their dependencies)
-* ltxdoc
-* idxlayout
-* xcolor
-* showexpl
-* enumitem
-* xkeyval
-* booktabs
-* longtable
-* tabu
-* etoolbox
-* hypdoc
+* rgltxdoc
+* etoc
+* amssymb, gensymb, fontawesome
+* xspace
 * xintexpr
-* makecell
+* makecell, cellspace
+* tabularx, longtable, xltabular, tabu
+* filecontents
+* datatool, csvsimple
 
 as well as
 * pdflatex

Modified: trunk/Master/texmf-dist/doc/latex/keyvaltable/keyvaltable.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx	2022-12-31 20:41:57 UTC (rev 65415)
+++ trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.dtx	2022-12-31 20:42:17 UTC (rev 65416)
@@ -3,16 +3,16 @@
 % Copyright (C) 2016-2020 by Richard Grewe <r-g+tex at posteo.net>
 % -------------------------------------------------------
 %
-% This file may be distributed and/or modified under the
-% conditions of the LaTeX Project Public License, either version 1.2
+% Thie file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
 % of this license or (at your option) any later version.
-% The latest version of this license is in:
+% The latest version of this license is in
+%    https://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008 or later.
 %
-%    http://www.latex-project.org/lppl.txt
+% This file has the LPPL maintenance status "maintained".
 %
-% and version 1.2 or later is part of all distributions of LaTeX
-% version 1999/12/01 or later.
-%
 % \fi
 %
 % \iffalse
@@ -22,7 +22,7 @@
 %<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
 %<package>\ProvidesPackage{keyvaltable}
 %<*package>
-    [2020/04/05 v2.2 Package for filling tables using key-value lists]
+    [2020/08/09 v2.3 Package for filling tables using key-value lists]
 %</package>
 %
 %<*driver>
@@ -37,7 +37,7 @@
 \newcommand\thispackage{\pkgname{keyvaltable}\xspace}
 % the following packages are additional for the examples
 \usepackage{xintexpr}
-\usepackage{makecell}
+\usepackage{makecell,cellspace}
 \usepackage{gensymb}% for \degree
 \usepackage{tabularx,longtable,xltabular,tabu}
 \usepackage{filecontents}
@@ -57,11 +57,13 @@
 %
 \usepackage{fontawesome}
 \makeatletter
-\newcommand\NiceText[2]{%
+\newenvironment{NiceText}[2]{%
   \medskip\par\noindent
-  \rgltxdoc at inmargin{\smash{\textcolor{#1}{\Large#2}}}{\quad}}
-\newcommand\NiceNote{\NiceText{DarkBlue}{\faInfoCircle}}
-\newcommand\NiceTipp{\NiceText{Gold}{\faLightbulbO}}
+  \rgltxdoc at inmargin{\smash{\textcolor{#1}{\large#2}}}{\quad}%
+  \ignorespaces}{\medskip\par\noindent}
+\newenvironment{NiceNote}{\NiceText{DarkBlue}{\faInfoCircle}}{\endNiceText}
+\newenvironment{NiceTipp}{\NiceText{DarkBlue}{\faLightbulbO}}{\endNiceText}
+\newenvironment{NiceWarn}{\NiceText{DarkBlue}{\faWarning}}{\endNiceText}
 %    \end{macrocode}
 \makeatother
 %
@@ -186,10 +188,12 @@
 % used in the general case and how its visual appearance can be
 % customized is subject of the remainder of this documentation.
 %
-% \NiceTipp{To quickly sketch a table type, one can even omit properties
-% of columns and just list their names, separated by semicolons, as the
-% following example shows. All columns then get the default alignment:
-% |l|.}
+% \begin{NiceTipp}
+%   To quickly sketch a table type, one can even omit properties
+%   of columns and just list their names, separated by semicolons, as the
+%   following example shows. All columns then get the default alignment:
+%   |l|.
+% \end{NiceTipp}
 % \begin{LTXexample}
 % \NewKeyValTable{Recipe}{amount;ingredient;step}
 % \begin{KeyValTable}{Recipe}
@@ -234,12 +238,14 @@
 %   the cell.  Initially (i.e., if unset for a column), this is an
 %   empty string.
 %
-% \NiceDescribeKey{format}{vals=\vmeta{single argument macro}, init=\cmd{\kvtStrutted}}
+% \NiceDescribeKey{format}{vals=\vmeta{single argument macro}, init=\vmeta{"identity"}}
 %   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. Initially, the format is defined to take
-%   the content as is but puts a \cmd{\strut} before and after the
-%   content (to yield a better vertical row spacing).
+%   the content as is.\footnote{Prior to version~2.3 of \thispackage,
+%   the initial format setting was to put \cmd{\strut} before and after
+%   the content to yield a better vertical row spacing in some
+%   situations. See also \cref{sec:VertSpacing}.}
 %
 % \NiceDescribeKey{head}{vals=\vmeta{content}, init=\vmeta{colname}}
 %   This property specifies the \meta{content} of the column's header
@@ -455,7 +461,7 @@
 % \begin{LTXexample}[morekeywords={thekvtRow,thekvtTypeRow}]
 % \NewKeyValTable[headformat=\textbf]{Numbered}{
 %   line: align=r, head=\#,
-%         format=\kvtStrutted[\textbf],
+%         format=\textbf,
 %         default=\thekvtRow;
 %   text: align=l, head=Text}
 % \begin{KeyValTable}{Numbered}
@@ -491,7 +497,7 @@
 %
 % \begin{LTXexample}[morekeywords={uncounted},
 %   morepreset={\NewKeyValTable[headformat=\textbf]{Numbered}{
-%     line: align=r,head=\#,format=\kvtStrutted[\textbf],default=\thekvtRow;
+%     line: align=r,head=\#,format=\textbf,default=\thekvtRow;
 %     text: align=l,head=Text}}]
 % \begin{KeyValTable}{Numbered}
 % \Row{text=First row}
@@ -542,10 +548,12 @@
 %
 % \subsection{Referencing in Collected Rows}\label{sec:referencing}
 %
-% The example in \cref{sec:collected} illustrates well a situation in
-% which referencing the locations in the document at which rows are
-% collected. The following example augments the original example to
-% achieve exactly this.
+% The previous sections show examples of referencing row numbers.
+% In tables of collected rows, it may be desirable to reference the
+% point in the document at which a row was collected.
+% The example in \cref{sec:collected} illustrates such a situation.
+% In the following, we augment that example by references to section and
+% page numbers.
 %
 % \begin{LTXexample}[width=0.5\hsize,morekeywords={NewCollectedTable,CollectRow,ShowCollectedTable}]
 % \NewKeyValTable{Notes2}{
@@ -566,14 +574,35 @@
 % Lorem ipsum dolor sit amet, \ldots
 % \end{LTXexample}
 %
-% The \thispackage package is carefully designed to take the values of
-% counters such as the page counter and the section counter from the
-% point in the document where |\CollectRow| is used.
-% At the same time, the table row counters are taken from the point
-% inside the respective table. This applies to |\thekvtRow| as well as
-% to |\arabic{kvtRow}| and other counter formats.
-% For customizing this behavior, the following three macros can be used.
+% The above example demonstrates that the correct section number is
+% referenced. Since the whole example is contained on a single page, the
+% example does not demonstrate that the page number (|\thepage|) in the
+% "where" column actually references the page in the document on which
+% the |\CollectRow| takes place. Note that the correct page will be
+% produced even when the |\CollectRow| is placed in a float, such as a
+% figure or table.
+% \begin{NiceWarn}
+%   \hologo{LaTeX} internally implements a special treatment of
+%   |\thepage| to make page references possible. For this reason, using
+%   something like |\arabic{page}| to produce the page number will
+%   presumably not work correctly.
+% \end{NiceWarn}
 %
+% The \thispackage package
+% \begin{itemize}[nosep]
+% \item takes the values of row counters (like |\thekvtRow|) from the
+%   position of \emph{the row in the table}
+%   but
+% \item takes the values of other counters such as the page counter and
+%   the section counter from the \emph{point in the document where
+%   \cmd{\CollectRow} is used}.
+% \end{itemize}
+% This takes into account that counter values can be obtained via
+% \cmd{\the\meta{ctrname}} (like |\thekvtRow| or |\thepage|) as well as
+% via macros like |\arabic|, |\roman| etc.
+% The following macros allow for declaring additional counters and
+% formatting macros to be taken into account by \thispackage.
+%
 % \NiceDescribeMacros{2}
 %   {\kvtDeclareTableMacros}{\marg{macro-list}}
 %   {\kvtDeclareTableCounters}{\marg{counter-list}}
@@ -663,8 +692,9 @@
 % value |true| hides the rules and the value |false| causes the rules to
 % be drawn.
 % Note that both properties only affect the rules that \thispackage
-% produces automatically; rules manually added, e.g., via |\hline| or
-% |\midrule| are not affected by the properties.
+% produces automatically; rules manually added, e.g., via |\hline|,
+% |\midrule|, or |\MidRule| (see Section~\ref{sec:rules}) are not
+% affected by the properties.
 %
 % \NiceDescribeKey{headalign}{vals={\vmeta{empty} or \vmeta{coltype}}, init=\vmeta{empty}}
 % This property specifies the alignment for header cells.  If left
@@ -783,11 +813,13 @@
 % \end{KeyValTable}
 % \end{LTXexample}
 %
-% \NiceNote{The \meta{options} in |\kvtNewTableStyle| can be left empty.
-% In this case, the table style does not have any effect on the appearance
-% of tables. However, the style can already be used for "tagging" tables
-% and table types, while the final options for the style can be
-% configured at a later point in time.}
+% \begin{NiceNote}
+%   The \meta{options} in |\kvtNewTableStyle| can be left
+%   empty.  In this case, the table style does not have any effect on the
+%   appearance of tables. However, the style can already be used for
+%   "tagging" tables and table types, while the final options for the
+%   style can be configured at a later point in time.
+% \end{NiceNote}
 %
 % Even without table styles, the appearance of the previous
 % |KeyValTable| can be used again through the following option.
@@ -807,19 +839,8 @@
 %
 % Column appearance is configured through the parameters |align|,
 % |head|, |format|, and |default| of columns in |\NewKeyValTable|.
-% For the |format|, the following macro exists to ensure proper height
-% and depth of rows even if the content itself is more narrow.
 %
-% \NiceDescribeMacro{\kvtStrutted}{\oarg{inner}\marg{arg}}
-% This macro places a |\strut| before \meta{arg} and a |\strut| after
-% \meta{arg}. This has the effect that the first and last row of
-% \meta{arg} obtain a "natural" height and depth even if their content
-% is smaller.
-% The second |\strut| is omitted when it would cause a new line to be
-% produced.
-% See \cref{sec:row-numbering} for an example.
 %
-%
 % \subsection{Row Appearance}\label{sec:RowOptions}
 %
 % Through the \meta{options} argument of the
@@ -871,20 +892,11 @@
 %   cells is then set to the values of the table's |headalign|,
 %   |headbg|, and |headformat| properties.
 %
-% \NiceDescribeKeys{3}
-%   {above}{vals=\vmeta{dimension}, init=\vmeta{empty}}
-%   {below}{vals=\vmeta{dimension}, init=\vmeta{empty}}
-%   {around}{vals=\vmeta{dimension}, init=\vmeta{empty}}
-%   These properties specify extra vertical space above and,
-%   respectively, below the row. The |around| property is a short-hand
-%   for setting both, |above| and |below|, to the same value.
-%     Note that the vertical 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 |\vspace|.
-%
-% \NiceNote{Initial values for all row options can be set with
+% \begin{NiceNote}
+%   Initial values for all row options can be set with
 %   |\kvtSet{Row/|\meta{option}|=|\meta{value}|}| (see also
-%   \cref{sec:kvtSet}).}
+%   \cref{sec:kvtSet}).
+% \end{NiceNote}
 %
 % The following example demonstrates some of the options.
 % \begin{LTXexample}[morepreset=\RecipePreset,morekeywords={hidden,above,bg,format}]
@@ -900,6 +912,58 @@
 % \end{KeyValTable}
 % \end{LTXexample}
 %
+%
+% \subsubsection{Vertical Row Size \& Spacing}\label{sec:VertSpacing}
+%
+% When rows are narrow or appear to be narrow, extra spacing above and
+% below can be configured. There are (at least) three options for this.
+%
+% The first option is to use the following |\Row| options.
+% \NiceDescribeKeys{3}
+%   {above}{vals=\vmeta{dimension}, init=\vmeta{empty}}
+%   {below}{vals=\vmeta{dimension}, init=\vmeta{empty}}
+%   {around}{vals=\vmeta{dimension}, init=\vmeta{empty}}
+%   These properties specify extra vertical space above and,
+%   respectively, below the row. The |around| property is a short-hand
+%   for setting both, |above| and |below|, to the same value.
+%     Note that the vertical 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 |\vspace|.
+%
+% The second option is to use the row |format| or a column's |format|
+% property to insert |\strut| macros around cell content.
+% For the |format|, the following macro exists.
+%
+% \NiceDescribeMacro{\kvtStrutted}{\oarg{inner}\marg{arg}}
+% This macro places a |\strut| before \meta{arg} and a |\strut| after
+% \meta{arg}. This has the effect that the first and last row of
+% \meta{arg} obtain a "natural" height and depth even if their content
+% is smaller.
+% The second |\strut| is omitted when it would cause a new line to be
+% produced.
+% See \cref{sec:row-numbering} for an example.
+%
+% The third option is using the \pkgname{cellspace} package and its
+% column alignments (e.g., |Sl| instead of |l|) along with the configurable dimensions |\cellspacetoplimit| and |\cellspacebottomlimit|.
+% The following example shows the second and the third option.
+%
+% \begin{LTXexample}[morekeywords={cellspace,kvtStrutted,cellspacetoplimit}]
+% \usepackage{cellspace}
+% \setlength{\cellspacetoplimit}{3pt}
+% \NewKeyValTable{VertSpacing}{
+%   normal;
+%   struts: format=\kvtStrutted;
+%   cellspace: align=Sl;
+% }
+% \begin{KeyValTable}{VertSpacing}
+% \Row{normal=normal size}
+% \Row{normal=\large Large}
+% \Row{struts=\large Large}
+% \Row{cellspace=\large Large}
+% \end{KeyValTable}
+% \end{LTXexample}
+%
+%
 % \subsubsection{Row Styles}
 %
 % Rather than specifying properties for individual rows, \thispackage
@@ -935,30 +999,87 @@
 % \end{KeyValTable}
 % \end{LTXexample}
 %
-% \NiceNote{The \meta{row-options} in |\kvtNewRowStyle| can be left empty.
-% In this case, the row style does not have any effect on the appearance
-% of rows. However, the style can already be used for "tagging" rows and
-% the final options for the style can be configured at a later point in
-% time.}
+% \begin{NiceNote}
+%   The \meta{row-options} in |\kvtNewRowStyle| can be left empty.
+%   In this case, the row style does not have any effect on the appearance
+%   of rows. However, the style can already be used for "tagging" rows and
+%   the final options for the style can be configured at a later point in
+%   time.
+% \end{NiceNote}
 %
 %
-% \subsubsection{Rules Between Rows}
+% \subsubsection{Rules Between Rows}\label{sec:rules}
 %
-% 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=\RecipePreset,morekeywords={midrule}]
+% For placing additional horizontal rules between rows, the
+% \thispackage package provides the following two macros that are
+% available in |KeyValTable| environments.
+%
+% \NiceDescribeMacro{\MidRule}{\oarg{width}}
+% This macro puts a horizontal rule over the full width of the table,
+% with line width \meta{width}. The macro puts the same vertical
+% spacing above and below the rule, just like |\midrule| of the
+% \pkgname{booktabs} package. The difference to |\midrule| is that row
+% colors (as specified by the |rowbg| property) are respected.
+% The following example demonstrates the use of |\MidRule|.
+%
+% \begin{LTXexample}[morepreset=\RecipePreset,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
+% \MidRule
 % \Row{step=serve with a smile}
 % \end{KeyValTable}
 % \end{LTXexample}
 %
+% \NiceDescribeMacro{\CMidRule}{\oarg{width}\marg{columns}}
+% This macro puts horizontal rules below each of the columns in the
+% comma-separated list \meta{columns}. This comma-separated list can
+% also contain names of column groups. The rules all have line width
+% \meta{width}. The outcome is similar to what a set of |\cmidrule|'s
+% would produce, except that row colors are respected and that column
+% indexes need not be counted.
+% The following example demonstrates the use of |\CMidRule|.
 %
+% \begin{LTXexample}[morekeywords={CMidRule}]
+% \NewKeyValTable[headformat=\textbf]{Prices}{
+%   part; min: align=r; max: align=r}[
+%   headers={min+max: head=price},
+%   colgroups={price: span=min+max}]
+% \begin{KeyValTable}{Prices}
+% \Row{part=engine, min=2500\$, max=3000\$}
+% \Row{part=tires, min=500\$, max=700\$}
+% \CMidRule[2pt]{price}
+% \Row{part=$\Sigma$, min=3000\$, max=3700\$}
+% \end{KeyValTable}
+% \end{LTXexample}
+%
+% The following macros are provided for general use, in
+% normal table environments.
+% \newcommand\kvtparg[1]{\texttt{(}\meta{#1}\texttt{)}}%
+% \NiceDescribeMacros{4}
+%   {\kvtRuleTop}{\oarg{width}\marg{color2}}
+%   {\kvtRuleBottom}{\oarg{width}\marg{color1}}
+%   {\kvtRuleMid}{\oarg{width}\marg{color1}\marg{color2}}
+%   {\kvtRuleCMid}{\oarg{width}\kvtparg{trim}\marg{a-b}\marg{color1}\marg{color2}}
+% These macros are replacements for the macros |\toprule|,
+% |\bottomrule|, |\midrule|, and |\cmidrule| of the \pkgname{booktabs}
+% package, which do not integrate well with background colors of rows.
+% The arguments \meta{color1} and \meta{color2} take the background
+% color above and, respectively, below the rule.
+%
+% Note that while multiple |\cmidrule|s can follow each other and
+% produce rules at the same horizontal position, this is not possible
+% with |\kvtRuleCMid|. Instead, if multiple |\kvtRuleCMid|s are desired,
+% one can use the following macro:
+% \NiceDescribeMacro{\kvtRulesCMid}{\oarg{width}\marg{rlist}\marg{color1}\marg{color2}}
+% In this macro, \meta{rlist} is a comma-separated list of
+% "\kvtparg{trim}\marg{a-b}" pairs, where each \meta{trim} is optional.
+% Consider the \pkgname{booktabs} documentation for more information
+% about \meta{trim}.
+%
+%
 % \subsection{Cell Appearance}
 %
 % Individual cells can be formatted by using the respective
@@ -1043,23 +1164,23 @@
 % 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{Headers2}{
-%   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;
-% }[headers={
-%   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{LTXexample}[width=0.5\hsize]
+% \NewKeyValTable[headformat=\textbf,headalign=c]
+%   {Headers2}{
+%     date: align=r, head=date;
+%     Berlin/min: align=r, head=min;
+%     Berlin/max: align=r, head=max;
+%     Paris/min:  align=r, head=min;
+%     Paris/max:  align=r, head=max;
+%   }[headers={
+%     Berlin/min+Berlin/max+Paris/min+Paris/max:
+%       head=temperature\\
+%     Paris/min+Paris/max: head=Paris, underline;
+%     Berlin/min+Berlin/max: head=Berlin, underline\\
+%     ::}]
 % \begin{KeyValTable}{Headers2}
 % \Row{date=01.01.1970,
-%      min/Berlin=0\degree C, max/Berlin=...}
+%      Berlin/min=0\degree C, Berlin/max=...}
 % \end{KeyValTable}
 % \end{LTXexample}
 %
@@ -1100,7 +1221,12 @@
 %   The initial value for this property is the column specification,
 %   i.e., "\meta{col}|+|\ldots|+|\meta{col}".
 %
+% \NiceDescribeKey{underline}{vals={true,false}, init=false, def=true}
+%   This property specifies whether the header cell shall be underlined,
+%   to visually indicate that the columns in the header cell form a
+%   logical group.
 %
+%
 % \subsection{Column Spanning}
 %
 % The \thispackage package supports column spanning via "column
@@ -1123,7 +1249,7 @@
 %   step=put into bowl}
 % \Row{amount= 50g, ingredient=cherries,
 %   step=heat up and add to bowl}
-% \midrule
+% \MidRule
 % \Row{all=serve with a smile}
 % \end{KeyValTable}
 % \end{LTXexample}
@@ -1145,14 +1271,16 @@
 %
 % \NiceDescribeKeys{2}
 %   {align}{vals={\vmeta{alignment-letter},\vmeta{empty}}, init=c}
-%   {format}{vals=\vmeta{single argument macro}, init=\cmd\kvtStrutted}
+%   {format}{vals=\vmeta{single argument macro}, init=\vmeta{"identity"}}
 % These properties are analogous to the respective properties of normal
 % columns. The only difference is that the initial column alignment of
 % column groups is "|c|" while the alignment of normal columns is "|l|".
 %
-% \NiceNote{Initial values for all the |align| and |format| options can be
+% \begin{NiceNote}
+%   Initial values for all the |align| and |format| options can be
 %   set with |\kvtSet|, via the |ColGroup/align| and, respectively
-%   |ColGroup/format| keys (see also \cref{sec:kvtSet}).}
+%   |ColGroup/format| keys (see also \cref{sec:kvtSet}).
+% \end{NiceNote}
 %
 %
 % \subsubsection{Manual Column Spanning}
@@ -1285,11 +1413,11 @@
 % \begin{KeyValTable}{ShapeProps}
 % \Row{shape=onepage,   env=tabular/tabularx,    multipage=no,  caption=no,  Xcols=yes, width=yes, align=v, packages=tabularx}
 % \Row{shape=multipage, env=longtable/xltabular, multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={longtable, xltabular}}
-% \midrule
+% \MidRule
 % \noalign{\footnotesize with package option |compat=1.0|:}
 % \Row{shape=onepage,   env=tabu,      multipage=no,  caption=no,  Xcols=yes, width=yes, align=v, packages=tabu}
 % \Row{shape=multipage, env=longtabu,  multipage=yes, caption=yes, Xcols=yes, width=yes, align=h, packages={tabu, longtable}}
-% \midrule
+% \MidRule
 % \Row{                 env=tabular,   multipage=no,  caption=no,  Xcols=no,  width=no,  align=v}
 % \Row{                 env=tabularx,  multipage=no,  caption=no,  Xcols=yes, width=yes, align=v, packages={tabularx}}
 % \Row{                 env=longtable, multipage=yes, caption=yes, Xcols=no,  width=no,  align=h, packages={longtable}}
@@ -1539,9 +1667,8 @@
 % \item support for different headers on the first page vs.\@ on
 %   subsequent pages of a multipage table; support configurable spacing
 %   between and above/below header rows
-% \item support for more flexibility with regards to captions position
-%   (top vs.\@ bottom) and distinct captions on first/middle/last page
-%   of the table.
+% \item support for more flexibility with regards to specifying
+%   distinct captions on first/middle/last page of the table.
 % \item improved row coloring that makes sure that the alternation
 %   re-starts on continued pages of a table that spans several pages
 % \item rerun detection for recorded rows (possibly via
@@ -1573,11 +1700,14 @@
 \RequirePackage{xkeyval}
 \RequirePackage{trimspaces}
 %    \end{macrocode}
-% We use \pkgname{booktabs} for nice horizontal lines and
-% \pkgname{xcolor} for row coloring.
+% We use \pkgname{booktabs} for nice horizontal lines,
+% \pkgname{colortbl} for row coloring, and \pkgname{xcolor} for color
+% names. To avoid package option clashes with \pkgname{xcolor}, we
+% load it at the end of the preamble..
+% \changes{v2.3}{2020/06/13}{Delayed loading of \pkgname{xcolor}}
 %    \begin{macrocode}
-\PassOptionsToPackage{table}{xcolor}
-\RequirePackage{xcolor}
+\RequirePackage{colortbl}
+\AtBeginDocument{\@ifpackageloaded{xcolor}{}{\RequirePackage{xcolor}}}
 \RequirePackage{booktabs}
 %    \end{macrocode}
 %
@@ -1928,6 +2058,8 @@
   \csdef{kvt@@hdcell at head@\kvt@@hdcell}{#1}}
 \define at key[kvt]{HeadCell}{align}{%
   \csdef{kvt@@hdcell at align@\kvt@@hdcell}{#1}}
+\define at boolkey[kvt]{HeadCell}{underline}[true]{%
+  \csdef{kvt@@hdcell at underline@\kvt@@hdcell}{#1}}
 \kvt at def@globalopts{HeadCell}{align}
 %    \end{macrocode}
 %
@@ -1982,6 +2114,7 @@
 % The following sets the default values for the options. This is done
 % only after the package is otherwise completely processed, to ensure
 % that all features are already defined/registered at that point.
+% \changes{v2.3}{2020/07/30}{Removed \cmd{\kvtStrutted} from default format}
 %    \begin{macrocode}
 \AtEndOfPackage{\kvtSet{%
   rowbg=white..black!10,
@@ -1997,7 +2130,7 @@
 % Column options
 %    \begin{macrocode}
   default=,
-  format=\kvtStrutted,
+  format=\@firstofone,
   align=l,
   head=,
   hidden=false,
@@ -2009,7 +2142,7 @@
   Row/expand=false,
   Row/expandonce=false,
   ColGroup/align=c,
-  ColGroup/format=\kvtStrutted,
+  ColGroup/format=\@firstofone,
   HeadCell/align=c,
 }}
 %    \end{macrocode}
@@ -2066,6 +2199,7 @@
   \csdef{kvt at alignments@#2}{}%
   \csdef{kvt at allcolumns@#2}{}%
   \csdef{kvt at displaycols@#2}{}%
+  \csdef{kvt at ndisplaycols@#2}{0}%
   \csdef{kvt at rowcount@#2}{0}%
   \csdef{kvt at rows@#2}{}%
   \csdef{kvt at headings@#2}{\kvt at defaultheader}%
@@ -2137,6 +2271,8 @@
       {\csappto{kvt at headings@#1}{{#2}}}%
       {\cseappto{kvt at headings@#1}{{\csexpandonce{kvt at col@head@#1@#2}}}}%
     \listcsadd{kvt at displaycols@#1}{#2}%
+    \csedef{kvt at ndisplaycols@#1}{%
+      \the\numexpr\csuse{kvt at ndisplaycols@#1}+1\relax}%
   }%
 %    \end{macrocode}
 % The following creates the column key that can be used by the row
@@ -2263,6 +2399,11 @@
   \kvt at setkeys{#3}{ColGroup}%
   \kvt at checkcolgroupcs{kvt at colgrp@span@#1@#2}{#1}{#2}%
 %    \end{macrocode}
+% Store the result of |\kvt at checkcolgroupcs| for later use.
+%    \begin{macrocode}
+  \csxdef{kvt at colgrp@first@#1@#2}{\kvt@@colgrp at first}%
+  \csxdef{kvt at colgrp@count@#1@#2}{\kvt@@colgrp at n}%
+%    \end{macrocode}
 % The following defines the |\Row| key for \meta{cgname}, as an
 % abbreviation for setting the value of the first displayed column of
 % \meta{cgname} (|\kvt@@colgrp at first| to a |\multicolumn| that spans the
@@ -2484,8 +2625,11 @@
 %    \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.
+% current header row.
+% The |\kvt@@tmpunderline| macro collects the rules (|\cmidrule|-like)
+% from header cells, in an \pkgname{etoolbox} list.
+% The |\kvt@@span| counter specifies how many columns the current cell
+% shall span.
 % Finally, |\kvt@@curhd| and |\kvt@@lasthd| hold the name of the
 % header cell in which the current column and, respectively, previous
 % column are in.  Each of the two macros is undefined if there is no
@@ -2492,7 +2636,9 @@
 % such header cell.
 %    \begin{macrocode}
   \let\kvt@@tmpgrphd\@empty
-  \kvt@@span\z@
+  \let\kvt@@tmpunderlines\@empty
+  \letcs\kvt@@tmpncols{kvt at ndisplaycols@#1}%
+  \kvt@@span\z@ \kvt@@coln\@ne
   \undef\kvt@@curhd \undef\kvt@@lasthd
   \kvt at def@atseconduse\kvt@@switchcol{\appto\kvt@@tmpgrphd{&}}%
 %    \end{macrocode}
@@ -2521,6 +2667,7 @@
             consecutive columns, but it is not}%
            {Compare `\string\kvt@@curhd' to the column ordering as
            specified in `\string\NewKeyValTable{#1}'}}{}}%
+       \advance\kvt@@coln\kvt@@span\relax
        \kvt@@span\@ne \let\kvt@@lasthd\kvt@@curhd}%
   }\dolistcsloop{kvt at displaycols@#1}%
   \kvt at concludehdcolumn
@@ -2530,6 +2677,12 @@
 % while ending the current \hologo{TeX} group.
 %    \begin{macrocode}
   \appto\kvt@@tmpgrphd{\tabularnewline}%
+  \ifdefempty\kvt@@tmpunderlines{}{%
+    \eappto\kvt@@tmpgrphd{%
+      \noexpand\kvtRule at cmid{\noexpand\cmidrulewidth}
+        {\expandonce\kvt@@tmpunderlines}
+        {\expandonce\cmdkvt at Table@headbg}
+        {\expandonce\cmdkvt at Table@headbg}}}%
   \edef\do{\noexpand\csappto{kvt@@custheadrows@#1}{%
     \unexpanded{\noexpand\kvt at rowcolorornot{\cmdkvt at Table@headbg}}%
     \noexpand\unexpanded{\expandonce{\kvt@@tmpgrphd}}}}%
@@ -2563,7 +2716,7 @@
 % collecting counterparts. Header rows as well as manually inserted
 % rows, including those produced by macros like |\midrule| in a
 % |longtable| environment, are not counted (as opposed by the internal
-% counter of |\rowcolors|.
+% counter of |\rowcolors|).
 %    \begin{macrocode}
 \newcount\kvt@@bodyrow
 %    \end{macrocode}
@@ -2572,8 +2725,11 @@
 % \begin{macro}{\kvt@@span}
 % The counter |\kvt@@span| is used temporarily in macros for counting
 % how many columns are spanned by column groups.
+% The counter |\kvt@@coln| is used temporarily in macros for counting
+% column indexes.
 %    \begin{macrocode}
 \newcount\kvt@@span
+\newcount\kvt@@coln
 %    \end{macrocode}
 % \end{macro}
 %
@@ -2591,6 +2747,18 @@
       {\noexpand\cmdkvt at Table@headformat
         {\csexpandonce{kvt@@hdcell at head@\kvt@@lasthd}}}}%
 %    \end{macrocode}
+% The following adds a pair of trim and spanned columns to
+% |\kvt@@tmpunderlines| for later drawing all the horizontal rules that
+% underline column groups.
+% A rule is trimmed left if it's not the first column and
+% a rule is trimmed right if it's not the last column.
+%    \begin{macrocode}
+    \ifcsstring{kvt@@hdcell at underline@\kvt@@lasthd}{true}
+      {\listeadd\kvt@@tmpunderlines{%
+        {\ifnumgreater{\kvt@@coln}{1}{l}{}%
+          \ifnumless{\kvt@@coln+\kvt@@span-1}{\kvt@@tmpncols}{r}{}}%
+        {\the\kvt@@coln-\the\numexpr\kvt@@coln+\kvt@@span-1\relax}}}{}%
+%    \end{macrocode}
 % Mark the header cell as already used and concluded, such that another
 % use of the same header cell can be detected and raise an error.
 %    \begin{macrocode}
@@ -2701,6 +2869,330 @@
 %    \end{macrocode}
 % \end{macro}
 %
+%
+% \subsection{Rules}
+%
+% This section exists because drawing rules with proper spacing and
+% proper consideration of row background colors requires some effort.
+% \changes{v2.3}{2020/08/09}{Made rules aware of row background colors}
+%
+% \begin{macro}{\kvt at RuleTop}
+% The |\kvt at RuleTop| macro produces a |\kvtRuleTop| rule that fits with
+% the header background color or, if no headers are shown, the
+% alternating row background colors.
+%    \begin{macrocode}
+\newcommand\kvt at RuleTop{\noalign{%
+  \edef\kvt@@do{\noexpand\kvtRuleTop{\ifbool{kvt at Table@showhead}
+    {\expandonce\cmdkvt at Table@headbg}{\expandonce\kvt@@bgcolor at odd}}}%
+  \expandafter}\kvt@@do}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt at RuleBottom}
+% The |\kvt at RuleBottom| macro produces a |\kvtRuleBottom| rule that fits
+% with the alternating row background colors.
+%    \begin{macrocode}
+\newcommand\kvt at RuleBottom{\noalign{%
+  \edef\kvt@@do{\noexpand\kvtRuleBottom{\ifnumodd{\the\kvt@@bodyrow}
+    {\expandonce\kvt@@bgcolor at odd}{\expandonce\kvt@@bgcolor at even}}}%
+  \expandafter}\kvt@@do}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt at RuleMid}
+% The |\kvt at RuleMid|\oarg{wd} macro produces a |\kvtRuleMid| rule that
+% fits with the alternating row background colors.
+%    \begin{macrocode}
+\newcommand\kvt at RuleMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvt at RuleMid@i}{\kvt at RuleMid@i[\lightrulewidth]}}
+\long\def\kvt at RuleMid@i[#1]{%
+  \edef\kvt@@do{\unexpanded{\ifnum0=`{\fi}\kvtRuleMid[{#1}]}%
+    \ifnumodd{\the\kvt@@bodyrow}
+    {{\expandonce\kvt@@bgcolor at odd}{\expandonce\kvt@@bgcolor at even}}
+    {{\expandonce\kvt@@bgcolor at even}{\expandonce\kvt@@bgcolor at odd}}}%
+  \kvt@@do}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt at RuleSubHead}
+% The |\kvt at RuleSubHead| macro is very similar to |\kvt at RuleMid|.
+% The latter is to be placed between body rows of a table.
+% The former is to be placed between the header row(s) and the body
+% rows.
+%    \begin{macrocode}
+\newcommand\kvt at RuleSubHead{\noalign{%
+  \edef\kvt@@do{\noexpand\kvtRuleMid
+    {\expandonce\cmdkvt at Table@headbg}{\expandonce\kvt@@bgcolor at odd}}%
+  \expandafter}\kvt@@do}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvt at RuleCMid}
+% The |\kvt at RuleCMid|\marg{tname}\oarg{wd}\marg{cglist} macro draws a
+% set of horizontal rules for a given comma-separated list of names of
+% columns and/or column groups, \meta{cglist}.
+%    \begin{macrocode}
+\newcommand\kvt at RuleCMid[1]{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvt at RuleCMid@i{#1}}
+               {\kvt at RuleCMid@i{#1}[\cmidrulewidth]}}
+\long\def\kvt at RuleCMid@i#1[#2]#3{%
+  \let\kvt@@rules\@empty
+  \def\kvt@@do##1{%
+    \ifcsdef{kvt at colgrp@first@#1@##1}
+      {\kvt at RuleCMid@cg{#1}{##1}}
+      {\kvt at RuleCMid@cc{#1}{##1}{1}}}%
+  \forcsvlist\kvt@@do{#3}%
+%    \end{macrocode}
+% The above collected the second argument of |\kvtRule at cmid| in
+% |\kvt@@rules|. The remaining lines now add the remaining arguments.
+%    \begin{macrocode}
+  \edef\kvt@@rules{\unexpanded{\ifnum0=`{\fi}\kvtRule at cmid}%
+    {\unexpanded{#2}}%
+    {\expandonce\kvt@@rules}
+    \ifnumodd{\the\kvt@@bodyrow}
+      {{\expandonce\kvt@@bgcolor at odd}{\expandonce\kvt@@bgcolor at even}}
+      {{\expandonce\kvt@@bgcolor at even}{\expandonce\kvt@@bgcolor at odd}}}%
+  \kvt@@rules}
+%    \end{macrocode}
+% The |\kvt at RuleCMid@cg|\marg{tname}\marg{colgrp} macro
+% takes the first column of \meta{colgrp} and column count of this
+% column group and passes them on to |\kvt at RuleCMid@c|.
+%    \begin{macrocode}
+\newcommand\kvt at RuleCMid@cg[2]{\bgroup%
+  \edef\kvt@@do{\egroup
+    \unexpanded{\kvt at RuleCMid@c{#1}}%
+      {\csuse{kvt at colgrp@first@#1@#2}}
+      {\csuse{kvt at colgrp@count@#1@#2}}}%
+  \kvt@@do}
+%    \end{macrocode}
+% The |\kvt at RuleCMid@c|\marg{tname}\marg{cname}\marg{count}
+% macro determines the index $a$ of column \meta{cname} and adds a rule
+% from this column to $a+\meta{count}-1$.
+% The |\kvt at RuleCMid@cc| macro takes the same arguments but additionally
+% checks whether \meta{cname} is a valid column name.
+%    \begin{macrocode}
+\newcommand\kvt at RuleCMid@cc[3]{%
+  \ifinlistcs{#2}{kvt at allcolumns@#1}
+    {\ifinlistcs{#2}{kvt at displaycols@#1}
+      {\kvt at RuleCMid@c{#1}{#2}{#3}}
+%    \end{macrocode}
+% Rules below known but hidden columns are silently skipped by the below
+% line.
+%    \begin{macrocode}
+      {}}
+    {\kvt at error
+      {Column or column group `#2' for `\string\CMidRule'
+       not known in table type `#1'}
+      {Check the \string\NewKeyValTable{#1} for
+       the names of known columns and check `#2' for a typo.}}}
+\newcommand\kvt at RuleCMid@c[3]{%
+%    \end{macrocode}
+% Find index of column \meta{cname} and store it in |\@tempcnta|.
+% Fixme: Column indexes could also be precomputed.
+%    \begin{macrocode}
+  \@tempcnta\z@
+  \def\do##1{\advance\@tempcnta\@ne
+    \ifstrequal{#2}{##1}{\listbreak}{}}%
+  \dolistcsloop{kvt at displaycols@#1}%
+%    \end{macrocode}
+% Now add new rule pair (trim and columns) to the list stored in
+% |\kvt@@rules|.
+%    \begin{macrocode}
+  \listeadd\kvt@@rules{%
+    {\ifnumgreater{\@tempcnta}{1}{l}{}%
+     \ifnumless{\@tempcnta+#3-1}{\csuse{kvt at ndisplaycols@#1}}{r}{}}%
+    {\the\@tempcnta-\the\numexpr\@tempcnta+#3-1\relax}}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \paragraph{Candidate for separate package.}
+% The following macros are independent of the remaining \thispackage
+% macros and could be factored out into their own small macro package
+% (|kvtrule|?) as a solution to reoccurring questions about row colors
+% with \pkgname{booktabs} (e.g.,
+% \url{https://tex.stackexchange.com/questions/177202/booktabs-and-row-color}).
+%
+% The macros below act as alternatives to rule macros of the
+% \pkgname{booktabs} package.
+% The \pkgname{booktabs} rule macros draw horizontal rules with some
+% spacing above and below the rule. Their spacing does not take into
+% account row colors.
+% The replacement macro allow specifying the row color above
+% (\meta{c-above}) and below (\meta{c-below}) of rule.
+%
+% \begin{macro}{\kvtRuleTop}
+% The |\kvtRuleTop|\oarg{wd}\marg{c-below} macro acts as a replacement
+% macro for \pkgname{booktabs}'s |\toprule|\oarg{wd} macro.
+%    \begin{macrocode}
+\newcommand\kvtRuleTop{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleTop at i}{\kvtRuleTop at i[\heavyrulewidth]}}
+\long\def\kvtRuleTop at i[#1]#2{\ifnum0=`{\fi}%
+  \specialrule{#1}{\abovetopsep}{0pt}%
+  \kvtRule at ColorRule{#2}{2\belowrulesep}{0pt}{-\belowrulesep}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvtRuleBottom}
+% The |\kvtRuleBottom|\oarg{wd}\marg{c-above} macro acts as a
+% replacement for \pkgname{booktabs}'s |\bottomrule|\oarg{wd} macro.
+%    \begin{macrocode}
+\newcommand\kvtRuleBottom{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleBottom at i}{\kvtRuleBottom at i[\heavyrulewidth]}}
+\long\def\kvtRuleBottom at i[#1]#2{\ifnum0=`{\fi}%
+  \kvtRule at ColorRule{#2}{\aboverulesep}{0pt}{0pt}%
+  \specialrule{#1}{0pt}{\belowbottomsep}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvtRuleMid}
+% The |\kvtRuleMid|\oarg{wd}\marg{c-above}\marg{c-below} macro acts as a
+% replacement for \pkgname{booktabs}'s |\midrule|\oarg{wd} macro.
+%    \begin{macrocode}
+\newcommand\kvtRuleMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleMid at i}{\kvtRuleMid at i[\lightrulewidth]}}
+\long\def\kvtRuleMid at i[#1]#2#3{\ifnum0=`{\fi}%
+  \kvtRule at ColorRule{#2}{\aboverulesep}{0pt}{0pt}%
+  \specialrule{#1}{0pt}{0pt}%
+%    \end{macrocode}
+% For some reason, without the doubling of |\belowrulesep| below,
+% there is a white space below the |\specialrule|. (Fixme?)
+%    \begin{macrocode}
+  \kvtRule at ColorRule{#3}{2\belowrulesep}{0pt}{-\belowrulesep}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvtRuleCMid}
+% The
+% |\kvtRuleCMid|\oarg{wd}|(|\meta{trim}|)|\marg{a-b}\marg{c-above}\marg{c-below}
+% macro acts as a replacement for \pkgname{booktabs}'s
+% |\cmidrule|\oarg{wd}|(|\meta{trim}|)|\marg{a-b} macro.
+%    \begin{macrocode}
+\newcommand\kvtRuleCMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleCMid at i}{\kvtRuleCMid at i[\cmidrulewidth]}}
+\long\def\kvtRuleCMid at i[#1]{%
+  \@ifnextchar({\kvtRuleCMid at ii{#1}}{\kvtRuleCMid at ii{#1}()}}
+\long\def\kvtRuleCMid at ii#1(#2)#3{\ifnum0=`{\fi}%
+  \kvtRule at cmid{#1}{{#2}{#3}}}
+%    \end{macrocode}
+% The
+% |\kvtRule at cmid|\marg{wd}\marg{r-list}\marg{c-above}\marg{c-below}
+% macro does the actual work.
+% The \meta{r-list} parameter is a \pkgname{etoolbox} list of pairs
+% "\marg{trim}\marg{a-b}".
+%    \begin{macrocode}
+\newcommand\kvtRule at cmid[4]{%
+%    \end{macrocode}
+% The "\meta{wd}/2" (i.e., |#1/2|) occurring twice below "splits" the
+% later rule vertically into the upper half (on \meta{c-above}
+% background) and the lower half (on \meta{c-below} background).
+%    \begin{macrocode}
+  \kvtRule at ColorRule{#3}
+    {\the\dimexpr\aboverulesep+#1/2\relax}
+    {0pt}
+    {\the\dimexpr-#1/2\relax}%
+%    \end{macrocode}
+% Draw the "below" color already here such that the rule can be drawn in
+% the middle on top of the "above" and "below" color.
+%    \begin{macrocode}
+  \kvtRule at ColorRule{#4}
+    {\the\dimexpr\belowrulesep+#1/2\relax}{0pt}
+    {\the\dimexpr-\belowrulesep-#1\relax}%
+%    \end{macrocode}
+% Now collect the rules to be drawn in a single macro |\kvt@@rules|.
+%    \begin{macrocode}
+  \noalign{%
+    \let\kvt@@rules\@empty%
+    \def\kvt@@do##1{\appto\kvt@@rules{\kvtRule at cmid@i{#1}##1}}%
+    \forlistloop\kvt@@do{#2}%
+    \expandafter}%
+  \kvt@@rules
+%    \end{macrocode}
+% In the spacing below, cancel out the negative spacing from
+% |\kvtRule at cmid@i|.
+%    \begin{macrocode}
+  \noalign{\vskip\dimexpr\belowrulesep+#1\relax}}
+%    \end{macrocode}
+%
+% The |\kvtRule at cmid@i|\marg{wd}\marg{trim}\marg{a-b} macro produces a
+% single |\cmidrule|-like rule from a set of such rules. The arguments
+% are the same as for |\cmidrule|.
+%    \begin{macrocode}
+\newcommand\kvtRule at cmid@i[3]{%
+%    \end{macrocode}
+% The following three lines locally inject zero |\aboverulesep| into
+% |\cmidrule|. Due to grouping within |\@cmidrule|, this is not possible
+% for |\belowrulesep|; hence, we have to fix |\belowrulesep| in the
+% |\vskip| later in this macro.
+% Note that the |\noalign| started below is ended within |\@cmidrule|.
+%    \begin{macrocode}
+  \noalign{\ifnum0=`}\fi
+    \aboverulesep=0pt\relax
+    \@cmidrule[#1](#2){#3}%
+%    \end{macrocode}
+% The imitates the code from |\xcmidrule| for when further |\cmidrule|s
+% follow. It additionally cancels out the superfluous |\belowrulesep| as
+% described before.
+%    \begin{macrocode}
+  \noalign{%
+    \vskip-\dimexpr #1+\belowrulesep\relax
+    \global\@lastruleclass\@ne}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvtRulesCMid}
+% The |\kvtRulesCMid|\oarg{width}\marg{r-list}\marg{color1}\marg{color2}
+% macro is the user interface for |\kvtRule at cmid| with multiple rules.
+% Here, \meta{r-list} is a comma-separated list of optional trim (in
+% parentheses) and column range -- and the code below essentially just
+% transforms this syntax into the syntax expected by |\kvtRule at cmid|.
+%    \begin{macrocode}
+\newcommand\kvtRulesCMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRulesCMid at i}{\kvtRulesCMid at i[\cmidrulewidth]}}
+\long\def\kvtRulesCMid at i[#1]#2#3#4{%
+  \let\kvt@@rules\@empty
+  \forcsvlist\kvtRulesCMid at ii{#2}%
+  \ifnum0=`{\fi\expandafter}\expandafter
+  \kvtRulesCMid at v\expandafter{\kvt@@rules}{#1}{#3}{#4}}
+\newcommand\kvtRulesCMid at ii[1]{\kvtRulesCMid at iii#1\@undefined}
+\newcommand\kvtRulesCMid at iii{%
+  \@ifnextchar({\kvtRulesCMid at iv}{\kvtRulesCMid at iv()}}
+\long\def\kvtRulesCMid at iv(#1)#2\@undefined{%
+  \listadd\kvt@@rules{{#1}{#2}}}
+\newcommand\kvtRulesCMid at v[4]{\kvtRule at cmid{#2}{#1}{#3}{#4}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvtRule at ColorRule}
+% The |\kvtRule at ColorRule|\marg{color}\marg{wd}\marg{above}\marg{below}
+% macro draws a full-width horizontal table rule of width \meta{wd} in
+% color \meta{color} and spacing \meta{above} above and \meta{below}
+% below the rule.
+% If \meta{color} is empty, the current background color is used.
+%    \begin{macrocode}
+\newcommand\kvtRule at ColorRule[4]{%
+  \ifstrempty{#1}
+    {\noalign{\expandafter\vskip\the\dimexpr #2+#3+#4\relax}}
+    {\kvtRule at SaveRuleColor
+     \arrayrulecolor{#1}%
+     \specialrule{#2}{#3}{#4}%
+     \kvtRule at RestoreRuleColor}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kvtRule at SaveRuleColor}
+% \begin{macro}{\kvtRule at RestoreRuleColor}
+% These macros save and, respectively, restore the current rule color,
+% as provided by the \pkgname{colortbl} package in |\CT at arc@|.
+%    \begin{macrocode}
+\newcommand\kvtRule at SaveRuleColor{%
+  \noalign{\global\let\kvt@@ctarc\CT at arc@}}
+\newcommand\kvtRule at RestoreRuleColor{%
+  \noalign{\global\let\CT at arc@\kvt@@ctarc}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
 % \subsection{Key-Value Table Content}
 %
 % \begin{environment}{KeyValTable}
@@ -2716,6 +3208,8 @@
 %    \begin{macrocode}
   \def\Row{\kvt at AddKeyValRow
     {\noalign\bgroup}{\expandafter\egroup\kvt@@row}{#2}}%
+  \def\MidRule{\kvt at RuleMid}%
+  \def\CMidRule{\kvt at RuleCMid{#2}}%
 %    \end{macrocode}
 % \end{macro}
 %    \begin{macrocode}
@@ -2825,7 +3319,7 @@
 % \begin{macro}{\metatblHasCaption}
 % \begin{macro}{\metatblCanVAlign}
 % \begin{macro}{\metatblCanHAlign}
-% All macros in the following block expect three arguments,
+% The following macros all expect the three arguments
 %   \marg{env-name}\marg{iftrue}\marg{iffalse}.
 % The macro
 % |\metatblRegistered|
@@ -3000,10 +3494,10 @@
   \let\kvt@@endhook\@empty
   \let\kvt@@prehook\@empty
   \ifbool{kvt at Table@showrules}
-    {\def\kvt@@rule##1{\csuse{##1rule}}}
+    {\def\kvt@@rule##1{\csuse{kvt at Rule##1}}}
     {\def\kvt@@rule##1{}}%
-  \appto\kvt@@prehook{\kvt@@rule{top}}%
-  \appto\kvt@@endhook{\kvt@@rule{bottom}}%
+  \appto\kvt@@prehook{\kvt@@rule{Top}}%
+  \appto\kvt@@endhook{\kvt@@rule{Bottom}}%
 %    \end{macrocode}
 % The following saves the row counter value for the table type globally,
 % such that subsequent tables of the same \meta{tname} can start counting
@@ -3039,12 +3533,17 @@
          {Consider placing the KeyValTable environment inside a 'table'
           environment and use the \string\caption\space macro inside.}}}%
   \ifdefstring{\cmdkvt at Table@captionpos}{t}
-    {\let\kvt@@caption at headmain\kvt@@caption at main\let\kvt@@caption at footmain\@empty
-     \let\kvt@@caption at headalt\kvt@@caption at alt  \let\kvt@@caption at footalt\@empty}
-    {\let\kvt@@caption at footmain\kvt@@caption at main\let\kvt@@caption at headmain\@empty
-     \let\kvt@@caption at footalt\kvt@@caption at alt  \let\kvt@@caption at headalt\@empty}%
+    {\let\kvt@@caption at headmain\kvt@@caption at main
+     \let\kvt@@caption at footmain\@empty
+     \let\kvt@@caption at headalt\kvt@@caption at alt
+     \let\kvt@@caption at footalt\@empty}
+    {\let\kvt@@caption at footmain\kvt@@caption at main
+     \let\kvt@@caption at headmain\@empty
+     \let\kvt@@caption at footalt\kvt@@caption at alt
+     \let\kvt@@caption at headalt\@empty}%
   \ifbool{kvt at Table@showhead}
-    {\eappto\kvt@@prehook{\csuse{kvt at headings@#2}\noexpand\kvt@@rule{mid}}}
+    {\eappto\kvt@@prehook{\csuse{kvt at headings@#2}%
+      \noexpand\kvt@@rule{SubHead}}}
     {}%
 %    \end{macrocode}
 % The following lines perform some checks before the table environment
@@ -3161,8 +3660,11 @@
 % If \meta{colors} is empty, then no row colors are setup.
 %    \begin{macrocode}
 \newcommand\kvt at setrowcolors[1]{%
-  \ifstrempty{#1}{}{\kvt at setrowcolors@i#1\@nil}}
+  \ifstrempty{#1}{\kvt at setrowcolors@ii{}{}}
+                 {\kvt at setrowcolors@i#1\@nil}}
 \def\kvt at setrowcolors@i#1..#2\@nil{%
+  \kvt at setrowcolors@ii{#1}{#2}}
+\newcommand\kvt at setrowcolors@ii[2]{%
   \def\kvt@@bgcolor at odd{#1}%
   \def\kvt@@bgcolor at even{#2}}
 %    \end{macrocode}
@@ -3271,7 +3773,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% The following lines define the macros for the various table 
+% The following lines define the macros for the various table
 % environments.
 %    \begin{macrocode}
 \kvt at RegisterBackend{tabular}
@@ -3350,9 +3852,9 @@
 % enabled for the row's cells.
 %    \begin{macrocode}
   \ifdefvoid\cmdkvt at Row@align
-    {\let\kvt@@rowmkmulticolumn\@empty}
+    {\def\kvt@@rowmkmulticolumn{\kvt at unicolumn}}
     {\edef\kvt@@rowmkmulticolumn{%
-       \noexpand\multicolumn{1}{\expandonce\cmdkvt at Row@align}}}%
+       \noexpand\kvt at multicolumn{1}{\expandonce\cmdkvt at Row@align}}}%
 %    \end{macrocode}
 % The following defines a macro
 % |\kvt@@cellfmtbuilder|\marg{cmd}\marg{csname}.
@@ -3361,7 +3863,7 @@
 % row formatting options.
 % Through this "builder" macro, the row format options need only be
 % considered once and the column format options can then be included
-% when the displayed columns are iterated over. 
+% when the displayed columns are iterated over.
 %    \begin{macrocode}
   \ifcsvoid{cmdkvt at Row@format!}
     {\edef\kvt@@cellfmtbuilder##1##2{%
@@ -3440,7 +3942,7 @@
 %    \begin{macrocode}
        \ifcsvoid{kvt@@noformat@#2@##1}
          {\kvt@@cellfmtbuilder\kvt@@formatter{kvt@@curcolformat}}%
-         {\let\kvt@@formatter\@firstofone}%
+         {\let\kvt@@formatter\kvt at unicolumn}%
        \csundef{kvt@@noformat@#2@##1}%
        \edef\kvt@@fmtcell{\expandafter\expandonce\expandafter{%
          \expandafter\kvt@@formatter\expandafter{%
@@ -3490,11 +3992,15 @@
 % Note that the alternative of avoiding the conditional (|\ifdefequal|)
 % in the above code and using |\@firstofone| instead of |\@empty| for a
 % noop in \meta{cmd} does not work:
-% Using `|\expandonce|\marg{cmd}\marg{arg}' would expand to
-% `|\unexpanded\expandafter{\@firstofone}|' and produces the error
-% `Argument of |\@firstofone| has an extra |}|'.
-% Using `|\expandonce{|\meta{cmd}\marg{arg}|}|' would expand to
-% `|\unexpanded|\marg{arg}' and, thus, prevent expansion of \meta{arg}.
+% \begin{itemize}[nosep]
+% \item Using `|\expandonce|\marg{cmd}\marg{arg}' would, by definition
+%   of |\expandonce|, expand to
+%   `|\unexpanded\expandafter{\@firstofone}|' and produces the error
+%   `Argument of |\@firstofone| has an extra |}|'.
+% \item Using `|\expandonce{|\meta{cmd}\marg{arg}|}|' would expand to
+%   `|\unexpanded|\marg{arg}' and, thus, prevent expansion of
+%   \meta{arg}.
+% \end{itemize}
 % \end{macro}
 %
 % \begin{macro}{\kvt at stepcounters}
@@ -3597,10 +4103,28 @@
 % cell formatting has been applied.
 %    \begin{macrocode}
   \def\kvt@@cell{#3}%
-  \def\kvt@@mkmulticolumn{\multicolumn{#2}{#1}}}
+  \def\kvt@@mkmulticolumn{\kvt at multicolumn{#2}{#1}}}
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\kvt at unicolumn}
+% \begin{macro}{\kvt at multicolumn}
+% The |\kvt at unicolumn|\marg{content} macro is the central macro for
+% creating a "normal" (non-multicolumn) cell holding the given
+% \meta{content}.
+% Analogously, the macro
+% |\kvt at multicolumn|\marg{align}\marg{n}\marg{content}
+% is the central macro for creating a multi-column cell with
+% \meta{content}.
+% The two macros are only meant to improve code legibility and to
+% simplify certain future modifications.
+%    \begin{macrocode}
+\newcommand\kvt at unicolumn[1]{#1}
+\newcommand\kvt at multicolumn[3]{\multicolumn{#1}{#2}{#3}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \subsubsection{Table and Row Styles}
 %
 % The following are the user macros.
@@ -3614,10 +4138,12 @@
 % specifying \meta{row-options} directly in the optional argument of
 % |\Row|. The macro fails if \meta{name} is already declared as a row
 % style.
+%    \begin{macrocode}
+\newcommand\kvtNewRowStyle{\kvt at NewStyle{row}{\kvtRenewRowStyle}}
+%    \end{macrocode}
 % The |\kvtRenewRowStyle|\marg{name}\marg{row-options} macro re-defines
 % an already existing row style with new \meta{row-options}.
 %    \begin{macrocode}
-\newcommand\kvtNewRowStyle{\kvt at NewStyle{row}{\kvtRenewRowStyle}}
 \newcommand\kvtRenewRowStyle{\kvt at RenewStyle{row}{\kvtNewRowStyle}}
 %    \end{macrocode}
 % \end{macro}
@@ -3632,10 +4158,12 @@
 % specifying \meta{options} directly in the optional argument of
 % a |KeyValTable| environment or of a |\NewKeyValTable|. The macro fails
 % if \meta{name} is already declared as a table style.
+%    \begin{macrocode}
+\newcommand\kvtNewTableStyle{\kvt at NewStyle{table}{\kvtRenewTableStyle}}
+%    \end{macrocode}
 % The |\kvtRenewTableStyle|\marg{name}\marg{options} macro re-defines
 % an already existing table style with new \meta{options}.
 %    \begin{macrocode}
-\newcommand\kvtNewTableStyle{\kvt at NewStyle{table}{\kvtRenewTableStyle}}
 \newcommand\kvtRenewTableStyle{\kvt at RenewStyle{table}{\kvtNewTableStyle}}
 %    \end{macrocode}
 % \end{macro}
@@ -3778,8 +4306,8 @@
 %
 % \begin{macro}{\CollectRow}
 % The |\CollectRow|\oarg{options}\marg{cname}\marg{content} writes a
-% |\kvt at RecordedRow| entry to the aux file. Fragile parts of
-% \meta{content} are protected through |\protected at write|.
+% |\kvt at RecordedRow| entry to the aux file, protecting fragile parts of
+% \meta{content} through |\protected at write|.
 % \changes{v2.0}{2019/04/09}{Added the macro}
 %    \begin{macrocode}
 \newcommand\CollectRow[3][]{%

Modified: trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins	2022-12-31 20:41:57 UTC (rev 65415)
+++ trunk/Master/texmf-dist/source/latex/keyvaltable/keyvaltable.ins	2022-12-31 20:42:17 UTC (rev 65416)
@@ -1,16 +1,23 @@
 %%
 %% Copyright (C) 2016-2020 by Richard Grewe <r-g+tex at 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.
+%% This file may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3c
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%%    https://www.latex-project.org/lppl.txt
+%% and version 1.3c or later is part of all distributions of LaTeX
+%% version 2008 or later.
 %%
+%% This file has the LPPL maintenance status "maintained".
+%%
+%% As this file contains legal notices, it is NOT PERMITTED to modify
+%% this file in any way that the legal information placed into
+%% generated files is changed (i.e., the files generated when the
+%% original file is executed). This restriction does not apply if
+%% (parts of) the content is reused in a different WORK producing its
+%% own generated files.
+%%
 \input docstrip.tex
 \keepsilent
 
@@ -19,15 +26,22 @@
 
 Copyright (C) 2016-2020 by Richard Grewe <r-g+tex at 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:
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3c
+of this license or (at your option) any later version.
+The latest version of this license is in
+   https://www.latex-project.org/lppl.txt
+and version 1.3c or later is part of all distributions of LaTeX
+version 2008 or later.
 
-   http://www.latex-project.org/lppl.txt
+This file has the LPPL maintenance status "maintained".
 
-and version 1.2 or later is part of all distributions of LaTeX version
-1999/12/01 or later.
+As this file contains legal notices, it is NOT PERMITTED to modify
+this file in any way that the legal information placed into
+generated files is changed (i.e., the files generated when the
+original file is executed). This restriction does not apply if
+(parts of) the content is reused in a different WORK producing its
+own generated files.
 
 \endpreamble
 

Modified: trunk/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty	2022-12-31 20:41:57 UTC (rev 65415)
+++ trunk/Master/texmf-dist/tex/latex/keyvaltable/keyvaltable.sty	2022-12-31 20:42:17 UTC (rev 65416)
@@ -8,25 +8,32 @@
 %% 
 %% Copyright (C) 2016-2020 by Richard Grewe <r-g+tex at 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:
+%% This file may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3c
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%%    https://www.latex-project.org/lppl.txt
+%% and version 1.3c or later is part of all distributions of LaTeX
+%% version 2008 or later.
 %% 
-%%    http://www.latex-project.org/lppl.txt
+%% This file has the LPPL maintenance status "maintained".
 %% 
-%% and version 1.2 or later is part of all distributions of LaTeX version
-%% 1999/12/01 or later.
+%% As this file contains legal notices, it is NOT PERMITTED to modify
+%% this file in any way that the legal information placed into
+%% generated files is changed (i.e., the files generated when the
+%% original file is executed). This restriction does not apply if
+%% (parts of) the content is reused in a different WORK producing its
+%% own generated files.
 %% 
 \NeedsTeXFormat{LaTeX2e}[1999/12/01]
 \ProvidesPackage{keyvaltable}
-    [2020/04/05 v2.2 Package for filling tables using key-value lists]
+    [2020/08/09 v2.3 Package for filling tables using key-value lists]
 
 \RequirePackage{etoolbox}
 \RequirePackage{xkeyval}
 \RequirePackage{trimspaces}
-\PassOptionsToPackage{table}{xcolor}
-\RequirePackage{xcolor}
+\RequirePackage{colortbl}
+\AtBeginDocument{\@ifpackageloaded{xcolor}{}{\RequirePackage{xcolor}}}
 \RequirePackage{booktabs}
 \newcommand\kvt at DeclareTrimListParser{%
   \@ifstar{\kvt at DeclareTrimListParser@i{*}}
@@ -152,6 +159,8 @@
   \csdef{kvt@@hdcell at head@\kvt@@hdcell}{#1}}
 \define at key[kvt]{HeadCell}{align}{%
   \csdef{kvt@@hdcell at align@\kvt@@hdcell}{#1}}
+\define at boolkey[kvt]{HeadCell}{underline}[true]{%
+  \csdef{kvt@@hdcell at underline@\kvt@@hdcell}{#1}}
 \kvt at def@globalopts{HeadCell}{align}
 \define at cmdkey[kvt]{Row}{bg}{}
 \define at cmdkey[kvt]{Row}{format}{}
@@ -189,7 +198,7 @@
   width=\linewidth,
   captionpos=b,
   default=,
-  format=\kvtStrutted,
+  format=\@firstofone,
   align=l,
   head=,
   hidden=false,
@@ -201,7 +210,7 @@
   Row/expand=false,
   Row/expandonce=false,
   ColGroup/align=c,
-  ColGroup/format=\kvtStrutted,
+  ColGroup/format=\@firstofone,
   HeadCell/align=c,
 }}
 \newcommand\NewKeyValTable[3][]{%
@@ -218,6 +227,7 @@
   \csdef{kvt at alignments@#2}{}%
   \csdef{kvt at allcolumns@#2}{}%
   \csdef{kvt at displaycols@#2}{}%
+  \csdef{kvt at ndisplaycols@#2}{0}%
   \csdef{kvt at rowcount@#2}{0}%
   \csdef{kvt at rows@#2}{}%
   \csdef{kvt at headings@#2}{\kvt at defaultheader}%
@@ -249,6 +259,8 @@
       {\csappto{kvt at headings@#1}{{#2}}}%
       {\cseappto{kvt at headings@#1}{{\csexpandonce{kvt at col@head@#1@#2}}}}%
     \listcsadd{kvt at displaycols@#1}{#2}%
+    \csedef{kvt at ndisplaycols@#1}{%
+      \the\numexpr\csuse{kvt at ndisplaycols@#1}+1\relax}%
   }%
   \define at cmdkey[KeyValTable]{#1}{#2}[]{}%
   \define at key[KeyValTable]{#1}{#2*}{%
@@ -296,6 +308,8 @@
   \def\kvt@@colgrp{#2}%
   \kvt at setkeys{#3}{ColGroup}%
   \kvt at checkcolgroupcs{kvt at colgrp@span@#1@#2}{#1}{#2}%
+  \csxdef{kvt at colgrp@first@#1@#2}{\kvt@@colgrp at first}%
+  \csxdef{kvt at colgrp@count@#1@#2}{\kvt@@colgrp at n}%
   \eappto\kvt@@result{%
     \noexpand\define at cmdkey[KeyValTable]{#1}{#2}{%
       \ifdefvoid\kvt@@colgrp at first{}{%
@@ -372,7 +386,9 @@
   \def\do##1{\kvt at parsehdcolspec{#1}##1::\@undefined}%
   \kvt at dossvlist{#2}%
   \let\kvt@@tmpgrphd\@empty
-  \kvt@@span\z@
+  \let\kvt@@tmpunderlines\@empty
+  \letcs\kvt@@tmpncols{kvt at ndisplaycols@#1}%
+  \kvt@@span\z@ \kvt@@coln\@ne
   \undef\kvt@@curhd \undef\kvt@@lasthd
   \kvt at def@atseconduse\kvt@@switchcol{\appto\kvt@@tmpgrphd{&}}%
   \def\do##1{\letcs\kvt@@curhd{kvt@@hdcellof@##1}%
@@ -384,10 +400,17 @@
             consecutive columns, but it is not}%
            {Compare `\string\kvt@@curhd' to the column ordering as
            specified in `\string\NewKeyValTable{#1}'}}{}}%
+       \advance\kvt@@coln\kvt@@span\relax
        \kvt@@span\@ne \let\kvt@@lasthd\kvt@@curhd}%
   }\dolistcsloop{kvt at displaycols@#1}%
   \kvt at concludehdcolumn
   \appto\kvt@@tmpgrphd{\tabularnewline}%
+  \ifdefempty\kvt@@tmpunderlines{}{%
+    \eappto\kvt@@tmpgrphd{%
+      \noexpand\kvtRule at cmid{\noexpand\cmidrulewidth}
+        {\expandonce\kvt@@tmpunderlines}
+        {\expandonce\cmdkvt at Table@headbg}
+        {\expandonce\cmdkvt at Table@headbg}}}%
   \edef\do{\noexpand\csappto{kvt@@custheadrows@#1}{%
     \unexpanded{\noexpand\kvt at rowcolorornot{\cmdkvt at Table@headbg}}%
     \noexpand\unexpanded{\expandonce{\kvt@@tmpgrphd}}}}%
@@ -397,6 +420,7 @@
   \expandafter\rowcolor\expandafter{#1}}}
 \newcount\kvt@@bodyrow
 \newcount\kvt@@span
+\newcount\kvt@@coln
 \newcommand\kvt at concludehdcolumn{%
   \kvt@@switchcol
   \ifdefvoid\kvt@@lasthd{}{%
@@ -405,6 +429,11 @@
       {\csexpandonce{kvt@@hdcell at align@\kvt@@lasthd}}
       {\noexpand\cmdkvt at Table@headformat
         {\csexpandonce{kvt@@hdcell at head@\kvt@@lasthd}}}}%
+    \ifcsstring{kvt@@hdcell at underline@\kvt@@lasthd}{true}
+      {\listeadd\kvt@@tmpunderlines{%
+        {\ifnumgreater{\kvt@@coln}{1}{l}{}%
+          \ifnumless{\kvt@@coln+\kvt@@span-1}{\kvt@@tmpncols}{r}{}}%
+        {\the\kvt@@coln-\the\numexpr\kvt@@coln+\kvt@@span-1\relax}}}{}%
     \cslet{kvt@@hdcelldone@\kvt@@lasthd}{\@ne}}}
 \def\kvt at parsehdcolspec#1#2:#3:#4\@undefined{%
   \kvt at checkcolspecempty{#4}{header cell}{#2}%
@@ -433,9 +462,141 @@
     \ifstrempty{#1}{\label{#3}}{\label[#1]{#3}}}%
   \csuse{the#2}}
 \newcounter{kvt at LabelCtr}
+\newcommand\kvt at RuleTop{\noalign{%
+  \edef\kvt@@do{\noexpand\kvtRuleTop{\ifbool{kvt at Table@showhead}
+    {\expandonce\cmdkvt at Table@headbg}{\expandonce\kvt@@bgcolor at odd}}}%
+  \expandafter}\kvt@@do}
+\newcommand\kvt at RuleBottom{\noalign{%
+  \edef\kvt@@do{\noexpand\kvtRuleBottom{\ifnumodd{\the\kvt@@bodyrow}
+    {\expandonce\kvt@@bgcolor at odd}{\expandonce\kvt@@bgcolor at even}}}%
+  \expandafter}\kvt@@do}
+\newcommand\kvt at RuleMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvt at RuleMid@i}{\kvt at RuleMid@i[\lightrulewidth]}}
+\long\def\kvt at RuleMid@i[#1]{%
+  \edef\kvt@@do{\unexpanded{\ifnum0=`{\fi}\kvtRuleMid[{#1}]}%
+    \ifnumodd{\the\kvt@@bodyrow}
+    {{\expandonce\kvt@@bgcolor at odd}{\expandonce\kvt@@bgcolor at even}}
+    {{\expandonce\kvt@@bgcolor at even}{\expandonce\kvt@@bgcolor at odd}}}%
+  \kvt@@do}
+\newcommand\kvt at RuleSubHead{\noalign{%
+  \edef\kvt@@do{\noexpand\kvtRuleMid
+    {\expandonce\cmdkvt at Table@headbg}{\expandonce\kvt@@bgcolor at odd}}%
+  \expandafter}\kvt@@do}
+\newcommand\kvt at RuleCMid[1]{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvt at RuleCMid@i{#1}}
+               {\kvt at RuleCMid@i{#1}[\cmidrulewidth]}}
+\long\def\kvt at RuleCMid@i#1[#2]#3{%
+  \let\kvt@@rules\@empty
+  \def\kvt@@do##1{%
+    \ifcsdef{kvt at colgrp@first@#1@##1}
+      {\kvt at RuleCMid@cg{#1}{##1}}
+      {\kvt at RuleCMid@cc{#1}{##1}{1}}}%
+  \forcsvlist\kvt@@do{#3}%
+  \edef\kvt@@rules{\unexpanded{\ifnum0=`{\fi}\kvtRule at cmid}%
+    {\unexpanded{#2}}%
+    {\expandonce\kvt@@rules}
+    \ifnumodd{\the\kvt@@bodyrow}
+      {{\expandonce\kvt@@bgcolor at odd}{\expandonce\kvt@@bgcolor at even}}
+      {{\expandonce\kvt@@bgcolor at even}{\expandonce\kvt@@bgcolor at odd}}}%
+  \kvt@@rules}
+\newcommand\kvt at RuleCMid@cg[2]{\bgroup%
+  \edef\kvt@@do{\egroup
+    \unexpanded{\kvt at RuleCMid@c{#1}}%
+      {\csuse{kvt at colgrp@first@#1@#2}}
+      {\csuse{kvt at colgrp@count@#1@#2}}}%
+  \kvt@@do}
+\newcommand\kvt at RuleCMid@cc[3]{%
+  \ifinlistcs{#2}{kvt at allcolumns@#1}
+    {\ifinlistcs{#2}{kvt at displaycols@#1}
+      {\kvt at RuleCMid@c{#1}{#2}{#3}}
+      {}}
+    {\kvt at error
+      {Column or column group `#2' for `\string\CMidRule'
+       not known in table type `#1'}
+      {Check the \string\NewKeyValTable{#1} for
+       the names of known columns and check `#2' for a typo.}}}
+\newcommand\kvt at RuleCMid@c[3]{%
+  \@tempcnta\z@
+  \def\do##1{\advance\@tempcnta\@ne
+    \ifstrequal{#2}{##1}{\listbreak}{}}%
+  \dolistcsloop{kvt at displaycols@#1}%
+  \listeadd\kvt@@rules{%
+    {\ifnumgreater{\@tempcnta}{1}{l}{}%
+     \ifnumless{\@tempcnta+#3-1}{\csuse{kvt at ndisplaycols@#1}}{r}{}}%
+    {\the\@tempcnta-\the\numexpr\@tempcnta+#3-1\relax}}}
+\newcommand\kvtRuleTop{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleTop at i}{\kvtRuleTop at i[\heavyrulewidth]}}
+\long\def\kvtRuleTop at i[#1]#2{\ifnum0=`{\fi}%
+  \specialrule{#1}{\abovetopsep}{0pt}%
+  \kvtRule at ColorRule{#2}{2\belowrulesep}{0pt}{-\belowrulesep}}
+\newcommand\kvtRuleBottom{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleBottom at i}{\kvtRuleBottom at i[\heavyrulewidth]}}
+\long\def\kvtRuleBottom at i[#1]#2{\ifnum0=`{\fi}%
+  \kvtRule at ColorRule{#2}{\aboverulesep}{0pt}{0pt}%
+  \specialrule{#1}{0pt}{\belowbottomsep}}
+\newcommand\kvtRuleMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleMid at i}{\kvtRuleMid at i[\lightrulewidth]}}
+\long\def\kvtRuleMid at i[#1]#2#3{\ifnum0=`{\fi}%
+  \kvtRule at ColorRule{#2}{\aboverulesep}{0pt}{0pt}%
+  \specialrule{#1}{0pt}{0pt}%
+  \kvtRule at ColorRule{#3}{2\belowrulesep}{0pt}{-\belowrulesep}}
+\newcommand\kvtRuleCMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRuleCMid at i}{\kvtRuleCMid at i[\cmidrulewidth]}}
+\long\def\kvtRuleCMid at i[#1]{%
+  \@ifnextchar({\kvtRuleCMid at ii{#1}}{\kvtRuleCMid at ii{#1}()}}
+\long\def\kvtRuleCMid at ii#1(#2)#3{\ifnum0=`{\fi}%
+  \kvtRule at cmid{#1}{{#2}{#3}}}
+\newcommand\kvtRule at cmid[4]{%
+  \kvtRule at ColorRule{#3}
+    {\the\dimexpr\aboverulesep+#1/2\relax}
+    {0pt}
+    {\the\dimexpr-#1/2\relax}%
+  \kvtRule at ColorRule{#4}
+    {\the\dimexpr\belowrulesep+#1/2\relax}{0pt}
+    {\the\dimexpr-\belowrulesep-#1\relax}%
+  \noalign{%
+    \let\kvt@@rules\@empty%
+    \def\kvt@@do##1{\appto\kvt@@rules{\kvtRule at cmid@i{#1}##1}}%
+    \forlistloop\kvt@@do{#2}%
+    \expandafter}%
+  \kvt@@rules
+  \noalign{\vskip\dimexpr\belowrulesep+#1\relax}}
+\newcommand\kvtRule at cmid@i[3]{%
+  \noalign{\ifnum0=`}\fi
+    \aboverulesep=0pt\relax
+    \@cmidrule[#1](#2){#3}%
+  \noalign{%
+    \vskip-\dimexpr #1+\belowrulesep\relax
+    \global\@lastruleclass\@ne}}
+\newcommand\kvtRulesCMid{\noalign{\ifnum0=`}\fi
+  \@ifnextchar[{\kvtRulesCMid at i}{\kvtRulesCMid at i[\cmidrulewidth]}}
+\long\def\kvtRulesCMid at i[#1]#2#3#4{%
+  \let\kvt@@rules\@empty
+  \forcsvlist\kvtRulesCMid at ii{#2}%
+  \ifnum0=`{\fi\expandafter}\expandafter
+  \kvtRulesCMid at v\expandafter{\kvt@@rules}{#1}{#3}{#4}}
+\newcommand\kvtRulesCMid at ii[1]{\kvtRulesCMid at iii#1\@undefined}
+\newcommand\kvtRulesCMid at iii{%
+  \@ifnextchar({\kvtRulesCMid at iv}{\kvtRulesCMid at iv()}}
+\long\def\kvtRulesCMid at iv(#1)#2\@undefined{%
+  \listadd\kvt@@rules{{#1}{#2}}}
+\newcommand\kvtRulesCMid at v[4]{\kvtRule at cmid{#2}{#1}{#3}{#4}}
+\newcommand\kvtRule at ColorRule[4]{%
+  \ifstrempty{#1}
+    {\noalign{\expandafter\vskip\the\dimexpr #2+#3+#4\relax}}
+    {\kvtRule at SaveRuleColor
+     \arrayrulecolor{#1}%
+     \specialrule{#2}{#3}{#4}%
+     \kvtRule at RestoreRuleColor}}
+\newcommand\kvtRule at SaveRuleColor{%
+  \noalign{\global\let\kvt@@ctarc\CT at arc@}}
+\newcommand\kvtRule at RestoreRuleColor{%
+  \noalign{\global\let\CT at arc@\kvt@@ctarc}}
 \newenvironment{KeyValTable}[2][]{%
   \def\Row{\kvt at AddKeyValRow
     {\noalign\bgroup}{\expandafter\egroup\kvt@@row}{#2}}%
+  \def\MidRule{\kvt at RuleMid}%
+  \def\CMidRule{\kvt at RuleCMid{#2}}%
   \kvt at SetOptions{#2}{#1}%
   \ifbool{kvt at TableEnv@resume*}{}
     {\gdef\kvt@@lastenvopt{#1}}%
@@ -537,10 +698,10 @@
   \let\kvt@@endhook\@empty
   \let\kvt@@prehook\@empty
   \ifbool{kvt at Table@showrules}
-    {\def\kvt@@rule##1{\csuse{##1rule}}}
+    {\def\kvt@@rule##1{\csuse{kvt at Rule##1}}}
     {\def\kvt@@rule##1{}}%
-  \appto\kvt@@prehook{\kvt@@rule{top}}%
-  \appto\kvt@@endhook{\kvt@@rule{bottom}}%
+  \appto\kvt@@prehook{\kvt@@rule{Top}}%
+  \appto\kvt@@endhook{\kvt@@rule{Bottom}}%
   \appto\kvt@@endhook{\noalign{%
     \csxdef{kvt at rowcount@#2}{\thekvtTypeRow}%
     \csxdef{kvt@@rowcountlast}{\thekvtRow}}}%
@@ -567,12 +728,17 @@
          {Consider placing the KeyValTable environment inside a 'table'
           environment and use the \string\caption\space macro inside.}}}%
   \ifdefstring{\cmdkvt at Table@captionpos}{t}
-    {\let\kvt@@caption at headmain\kvt@@caption at main\let\kvt@@caption at footmain\@empty
-     \let\kvt@@caption at headalt\kvt@@caption at alt  \let\kvt@@caption at footalt\@empty}
-    {\let\kvt@@caption at footmain\kvt@@caption at main\let\kvt@@caption at headmain\@empty
-     \let\kvt@@caption at footalt\kvt@@caption at alt  \let\kvt@@caption at headalt\@empty}%
+    {\let\kvt@@caption at headmain\kvt@@caption at main
+     \let\kvt@@caption at footmain\@empty
+     \let\kvt@@caption at headalt\kvt@@caption at alt
+     \let\kvt@@caption at footalt\@empty}
+    {\let\kvt@@caption at footmain\kvt@@caption at main
+     \let\kvt@@caption at headmain\@empty
+     \let\kvt@@caption at footalt\kvt@@caption at alt
+     \let\kvt@@caption at headalt\@empty}%
   \ifbool{kvt at Table@showhead}
-    {\eappto\kvt@@prehook{\csuse{kvt at headings@#2}\noexpand\kvt@@rule{mid}}}
+    {\eappto\kvt@@prehook{\csuse{kvt at headings@#2}%
+      \noexpand\kvt@@rule{SubHead}}}
     {}%
   \ifdefvoid{\cmdkvt at Table@valign}{}{\metatblCanVAlign{#1}{}
     {\undef{\cmdkvt at Table@valign}%
@@ -621,8 +787,11 @@
   \noalign{\parbox{0pt}{\vskip\baselineskip}}%
   \caption}
 \newcommand\kvt at setrowcolors[1]{%
-  \ifstrempty{#1}{}{\kvt at setrowcolors@i#1\@nil}}
+  \ifstrempty{#1}{\kvt at setrowcolors@ii{}{}}
+                 {\kvt at setrowcolors@i#1\@nil}}
 \def\kvt at setrowcolors@i#1..#2\@nil{%
+  \kvt at setrowcolors@ii{#1}{#2}}
+\newcommand\kvt at setrowcolors@ii[2]{%
   \def\kvt@@bgcolor at odd{#1}%
   \def\kvt@@bgcolor at even{#2}}
 \newcommand\kvt at userowcolors{\ifnumodd{\the\kvt@@bodyrow}
@@ -697,9 +866,9 @@
     {\appto\kvt@@row{\kvt at userowcolors}}
     {\eappto\kvt@@row{\noexpand\rowcolor{\expandonce\cmdkvt at Row@bg}}}%
   \ifdefvoid\cmdkvt at Row@align
-    {\let\kvt@@rowmkmulticolumn\@empty}
+    {\def\kvt@@rowmkmulticolumn{\kvt at unicolumn}}
     {\edef\kvt@@rowmkmulticolumn{%
-       \noexpand\multicolumn{1}{\expandonce\cmdkvt at Row@align}}}%
+       \noexpand\kvt at multicolumn{1}{\expandonce\cmdkvt at Row@align}}}%
   \ifcsvoid{cmdkvt at Row@format!}
     {\edef\kvt@@cellfmtbuilder##1##2{%
        \noexpand\edef##1####1{%
@@ -739,7 +908,7 @@
             {\protected at edef\kvt@@cell{\kvt@@cell}}{}}%
        \ifcsvoid{kvt@@noformat@#2@##1}
          {\kvt@@cellfmtbuilder\kvt@@formatter{kvt@@curcolformat}}%
-         {\let\kvt@@formatter\@firstofone}%
+         {\let\kvt@@formatter\kvt at unicolumn}%
        \csundef{kvt@@noformat@#2@##1}%
        \edef\kvt@@fmtcell{\expandafter\expandonce\expandafter{%
          \expandafter\kvt@@formatter\expandafter{%
@@ -780,7 +949,9 @@
 \newcommand\kvt at SetMulticolumn[3]{%
   \kvt@@span=#2\relax \advance\kvt@@span\m at ne
   \def\kvt@@cell{#3}%
-  \def\kvt@@mkmulticolumn{\multicolumn{#2}{#1}}}
+  \def\kvt@@mkmulticolumn{\kvt at multicolumn{#2}{#1}}}
+\newcommand\kvt at unicolumn[1]{#1}
+\newcommand\kvt at multicolumn[3]{\multicolumn{#1}{#2}{#3}}
 \newcommand\kvtNewRowStyle{\kvt at NewStyle{row}{\kvtRenewRowStyle}}
 \newcommand\kvtRenewRowStyle{\kvt at RenewStyle{row}{\kvtNewRowStyle}}
 \newcommand\kvtNewTableStyle{\kvt at NewStyle{table}{\kvtRenewTableStyle}}



More information about the tex-live-commits mailing list.