texlive[53166] Master: kvsetkeys split from oberdiek (18dec19)

commits+karl at tug.org commits+karl at tug.org
Wed Dec 18 00:22:25 CET 2019


Revision: 53166
          http://tug.org/svn/texlive?view=revision&revision=53166
Author:   karl
Date:     2019-12-18 00:22:24 +0100 (Wed, 18 Dec 2019)
Log Message:
-----------
kvsetkeys split from oberdiek (18dec19)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/tlpsrc/collection-latex.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/kvsetkeys/
    trunk/Master/texmf-dist/doc/latex/kvsetkeys/README.md
    trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys-example.tex
    trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys.pdf
    trunk/Master/texmf-dist/source/latex/kvsetkeys/
    trunk/Master/texmf-dist/source/latex/kvsetkeys/kvsetkeys.dtx
    trunk/Master/texmf-dist/tex/generic/kvsetkeys/
    trunk/Master/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty
    trunk/Master/tlpkg/tlpsrc/kvsetkeys.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex/kvsetkeys/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/kvsetkeys/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/kvsetkeys/README.md	2019-12-17 23:22:24 UTC (rev 53166)
@@ -0,0 +1,11 @@
+# kvsetkeys
+
+kvsetkeys package for LaTeX
+
+
+Package kvsetkeys provides kvsetkeys, a variant
+of package keyval's \cs{setkeys}. It allows to specify
+a handler that deals with unknown options. Active commas and equal
+signs may be used (e.g. see babel's shorthands) and
+only one level of curly braces is removed from the values.
+


Property changes on: trunk/Master/texmf-dist/doc/latex/kvsetkeys/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys-example.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys-example.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys-example.tex	2019-12-17 23:22:24 UTC (rev 53166)
@@ -0,0 +1,93 @@
+%%
+%% This is file `kvsetkeys-example.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% kvsetkeys.dtx  (with options: `example')
+%% 
+%% This is a generated file.
+%% 
+%% Project: kvsetkeys
+%% Version: 2019/12/15 v1.18
+%% 
+%% Copyright (C)
+%%    2006, 2007, 2009-2012 Heiko Oberdiek
+%%    2016-2019 Oberdiek Package Support Group
+%% 
+%% This work 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. This version of this license is in
+%%    https://www.latex-project.org/lppl/lppl-1-3c.txt
+%% and the latest version of this license is in
+%%    https://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of
+%% LaTeX version 2005/12/01 or later.
+%% 
+%% This work has the LPPL maintenance status "maintained".
+%% 
+%% The Current Maintainers of this work are
+%% Heiko Oberdiek and the Oberdiek Package Support Group
+%% https://github.com/ho-tex/kvsetkeys/issues
+%% 
+%% 
+%% The Base Interpreter refers to any `TeX-Format',
+%% because some files are installed in TDS:tex/generic//.
+%% 
+%% This work consists of the main source file kvsetkeys.dtx
+%% and the derived files
+%%    kvsetkeys.sty, kvsetkeys.pdf, kvsetkeys.ins, kvsetkeys.drv,
+%%    kvsetkeys-example.tex, kvsetkeys-test1.tex,
+%%    kvsetkeys-test2.tex, kvsetkeys-test3.tex,
+%%    kvsetkeys-test4.tex.
+%% 
+\documentclass{article}
+\usepackage[T1]{fontenc}
+\usepackage{kvsetkeys}
+\usepackage{keyval}
+
+\makeatletter
+\newcommand*{\tag}[2][]{%
+  % #1: attributes
+  % #2: tag name
+  \begingroup
+    \toks@={}%
+    \let\@endslash\@empty
+    \kvsetkeys{tag}{#1}%
+    \texttt{%
+      \textless #2\the\toks@\@endslash\textgreater
+    }%
+  \endgroup
+}
+\kv at set@family at handler{tag}{%
+  % #1: key
+  % #2: value
+  \toks@\expandafter{%
+    \the\toks@
+    \space
+    #1=\string"#2\string"%
+  }%
+}
+\define at key{tag}{/}[]{%
+  \def\@endslash{/}%
+}
+\makeatother
+
+\begin{document}
+\begin{tabbing}
+  \mbox{}\qquad\=\qquad\=\kill
+  \tag{html}\\
+  \>\dots\\
+  \>\tag[border=1]{table}\\
+  \>\>\tag[width=200, span=3, /]{colgroup}\\
+  \>\>\dots\\
+  \>\tag{/table}\\
+  \>\dots\\
+  \tag{/html}\\
+\end{tabbing}
+\end{document}
+%% \section{Installation}
+\endinput
+%%
+%% End of file `kvsetkeys-example.tex'.


Property changes on: trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys-example.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys.pdf	2019-12-17 23:21:23 UTC (rev 53165)
+++ trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys.pdf	2019-12-17 23:22:24 UTC (rev 53166)

Property changes on: trunk/Master/texmf-dist/doc/latex/kvsetkeys/kvsetkeys.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/kvsetkeys/kvsetkeys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/kvsetkeys/kvsetkeys.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/kvsetkeys/kvsetkeys.dtx	2019-12-17 23:22:24 UTC (rev 53166)
@@ -0,0 +1,1676 @@
+% \iffalse meta-comment
+%
+% File: kvsetkeys.dtx
+% Version: 2019/12/15 v1.18
+% Info: Key value parser
+%
+% Copyright (C)
+%    2006, 2007, 2009-2012 Heiko Oberdiek
+%    2016-2019 Oberdiek Package Support Group
+%    https://github.com/ho-tex/kvsetkeys/issues
+%
+% This work 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. This version of this license is in
+%    https://www.latex-project.org/lppl/lppl-1-3c.txt
+% and the latest version of this license is in
+%    https://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of
+% LaTeX version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status "maintained".
+%
+% The Current Maintainers of this work are
+% Heiko Oberdiek and the Oberdiek Package Support Group
+% https://github.com/ho-tex/kvsetkeys/issues
+%
+% The Base Interpreter refers to any `TeX-Format',
+% because some files are installed in TDS:tex/generic//.
+%
+% This work consists of the main source file kvsetkeys.dtx
+% and the derived files
+%    kvsetkeys.sty, kvsetkeys.pdf, kvsetkeys.ins, kvsetkeys.drv,
+%    kvsetkeys-example.tex, kvsetkeys-test1.tex,
+%    kvsetkeys-test2.tex, kvsetkeys-test3.tex,
+%    kvsetkeys-test4.tex.
+%
+% Distribution:
+%    CTAN:macros/latex/contrib/kvsetkeys/kvsetkeys.dtx
+%    CTAN:macros/latex/contrib/kvsetkeys/kvsetkeys.pdf
+%
+% Unpacking:
+%    (a) If kvsetkeys.ins is present:
+%           tex kvsetkeys.ins
+%    (b) Without kvsetkeys.ins:
+%           tex kvsetkeys.dtx
+%    (c) If you insist on using LaTeX
+%           latex \let\install=y\input{kvsetkeys.dtx}
+%        (quote the arguments according to the demands of your shell)
+%
+% Documentation:
+%    (a) If kvsetkeys.drv is present:
+%           latex kvsetkeys.drv
+%    (b) Without kvsetkeys.drv:
+%           latex kvsetkeys.dtx; ...
+%    The class ltxdoc loads the configuration file ltxdoc.cfg
+%    if available. Here you can specify further options, e.g.
+%    use A4 as paper format:
+%       \PassOptionsToClass{a4paper}{article}
+%
+%    Programm calls to get the documentation (example):
+%       pdflatex kvsetkeys.dtx
+%       makeindex -s gind.ist kvsetkeys.idx
+%       pdflatex kvsetkeys.dtx
+%       makeindex -s gind.ist kvsetkeys.idx
+%       pdflatex kvsetkeys.dtx
+%
+% Installation:
+%    TDS:tex/generic/kvsetkeys/kvsetkeys.sty
+%    TDS:doc/latex/kvsetkeys/kvsetkeys.pdf
+%    TDS:doc/latex/kvsetkeys/kvsetkeys-example.tex
+%    TDS:source/latex/kvsetkeys/kvsetkeys.dtx
+%
+%<*ignore>
+\begingroup
+  \catcode123=1 %
+  \catcode125=2 %
+  \def\x{LaTeX2e}%
+\expandafter\endgroup
+\ifcase 0\ifx\install y1\fi\expandafter
+         \ifx\csname processbatchFile\endcsname\relax\else1\fi
+         \ifx\fmtname\x\else 1\fi\relax
+\else\csname fi\endcsname
+%</ignore>
+%<*install>
+\input docstrip.tex
+\Msg{************************************************************************}
+\Msg{* Installation}
+\Msg{* Package: kvsetkeys 2019/12/15 v1.18 Key value parser (HO)}
+\Msg{************************************************************************}
+
+\keepsilent
+\askforoverwritefalse
+
+\let\MetaPrefix\relax
+\preamble
+
+This is a generated file.
+
+Project: kvsetkeys
+Version: 2019/12/15 v1.18
+
+Copyright (C)
+   2006, 2007, 2009-2012 Heiko Oberdiek
+   2016-2019 Oberdiek Package Support Group
+
+This work 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. This version of this license is in
+   https://www.latex-project.org/lppl/lppl-1-3c.txt
+and the latest version of this license is in
+   https://www.latex-project.org/lppl.txt
+and version 1.3 or later is part of all distributions of
+LaTeX version 2005/12/01 or later.
+
+This work has the LPPL maintenance status "maintained".
+
+The Current Maintainers of this work are
+Heiko Oberdiek and the Oberdiek Package Support Group
+https://github.com/ho-tex/kvsetkeys/issues
+
+
+The Base Interpreter refers to any `TeX-Format',
+because some files are installed in TDS:tex/generic//.
+
+This work consists of the main source file kvsetkeys.dtx
+and the derived files
+   kvsetkeys.sty, kvsetkeys.pdf, kvsetkeys.ins, kvsetkeys.drv,
+   kvsetkeys-example.tex, kvsetkeys-test1.tex,
+   kvsetkeys-test2.tex, kvsetkeys-test3.tex,
+   kvsetkeys-test4.tex.
+
+\endpreamble
+\let\MetaPrefix\DoubleperCent
+
+\generate{%
+  \file{kvsetkeys.ins}{\from{kvsetkeys.dtx}{install}}%
+  \file{kvsetkeys.drv}{\from{kvsetkeys.dtx}{driver}}%
+  \usedir{tex/generic/kvsetkeys}%
+  \file{kvsetkeys.sty}{\from{kvsetkeys.dtx}{package}}%
+  \usedir{doc/latex/kvsetkeys}%
+  \file{kvsetkeys-example.tex}{\from{kvsetkeys.dtx}{example}}%
+}
+
+\catcode32=13\relax% active space
+\let =\space%
+\Msg{************************************************************************}
+\Msg{*}
+\Msg{* To finish the installation you have to move the following}
+\Msg{* file into a directory searched by TeX:}
+\Msg{*}
+\Msg{*     kvsetkeys.sty}
+\Msg{*}
+\Msg{* To produce the documentation run the file `kvsetkeys.drv'}
+\Msg{* through LaTeX.}
+\Msg{*}
+\Msg{* Happy TeXing!}
+\Msg{*}
+\Msg{************************************************************************}
+
+\endbatchfile
+%</install>
+%<*ignore>
+\fi
+%</ignore>
+%<*driver>
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesFile{kvsetkeys.drv}%
+  [2019/12/15 v1.18 Key value parser (HO)]%
+\documentclass{ltxdoc}
+\usepackage{holtxdoc}[2011/11/22]
+\begin{document}
+  \DocInput{kvsetkeys.dtx}%
+\end{document}
+%</driver>
+% \fi
+%
+%
+%
+% \GetFileInfo{kvsetkeys.drv}
+%
+% \title{The \xpackage{kvsetkeys} package}
+% \date{2019/12/15 v1.18}
+% \author{Heiko Oberdiek\thanks
+% {Please report any issues at \url{https://github.com/ho-tex/kvsetkeys/issues}}}
+%
+% \maketitle
+%
+% \begin{abstract}
+% Package \xpackage{kvsetkeys} provides \cs{kvsetkeys}, a variant
+% of package \xpackage{keyval}'s \cs{setkeys}. It allows to specify
+% a handler that deals with unknown options. Active commas and equal
+% signs may be used (e.g. see \xpackage{babel}'s shorthands) and
+% only one level of curly braces is removed from the values.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \def\M#1{\texttt{\{}\meta{#1}\texttt{\}}}
+%
+% \section{Documentation}
+%
+% First I want to recommend the very good review article
+% ``A guide to key-value methods'' by Joseph Wright \cite{tb94wright}.
+% It introduces the different key-value packages and compares them.
+%
+% \subsection{Motivation}
+%
+% \cs{kvsetkeys} serves as replacement for \xpackage{keyval}'s
+% \cs{setkeys}. It basically uses the same syntax. But the
+% implementation is more robust and predictable:
+% \begin{description}
+% \item[Active syntax characters:]
+%   Comma `|,|' and the equals sign `|=|' are used inside
+%   key value lists as syntax characters. Package \xpackage{keyval}
+%   uses the catcode of the characters that is active during
+%   package loading, usually this is catcode 12 (other).
+%   But it can happen that the catcode setting of the syntax characters
+%   changes. Especially active characters are of interest, because
+%   some language adaptations uses them. For example, option \xoption{turkish}
+%   of package \xpackage{babel} uses the equals sign as active shorthand
+%   character. Therefore package \xpackage{kvsetkeys} deals with
+%   both catcode settings 12 (other) and 13 (active).
+% \item[Brace removal:]
+%   Package \xpackage{keyval}'s \cs{setkeys} removes up to two
+%   levels of curly braces around the value in some unpredictable way:
+%\begin{quote}
+%|\setkeys{fam}{key={{value}}} || || | $\rightarrow$ |value|\\
+%|\setkeys{fam}{key={{{value}}}} | $\rightarrow$ |{value}|\\
+%|\setkeys{fam}{key= {{{value}}}}| $\rightarrow$ |{{value}}|
+%\end{quote}
+%   This package \xpackage{kvsetkeys} follows a much stronger rule:
+%   Exactly one level of braces are removed from an item, if the
+%   item is surrounded by curly braces. An item can be a
+%   the key value pair, the key or the value.
+%\begin{quote}
+%|\kvsetkeys{fam}{key={value}} || | $\rightarrow$ |value|\\
+%|\kvsetkeys{fam}{key={{value}} | $\rightarrow$ |{value}|\\
+%|\kvsetkeys{fam}{key= {{value}}| $\rightarrow$ |{value}|
+%\end{quote}
+% \item[Arbitrary values:] Unmatched conditionals are supported.
+% \end{description}
+%
+% Before I describe
+% \cs{kvsetkeys} in more detail, first I want to explain, how
+% this package deals with key value lists. For the package also
+% provides low level interfaces that can be used by package authors.
+%
+% \subsection{Normalizing key value lists}
+%
+% \begin{declcs}{kv at normalize}\,\M{key value list}
+% \end{declcs}
+% If the user specifies key value lists, he usually prefers
+% nice formatted source code, e.g.:
+% \begin{quote}
+%\begin{verbatim}
+%\hypersetup{
+%  pdftitle    = {...},
+%  pdfsubject  = {...},
+%  pdfauthor   = {...},
+%  pdfkeywords = {...},
+%  ...
+%}
+%\end{verbatim}
+% \end{quote}
+% Thus there can be spaces around keys, around |=| or around the value.
+% Also empty entries are possible by too many commas. Therefore these
+% spaces and empty entries are silently removed by package \xpackage{keyval}
+% and this package. Whereas the contents of the value can be protected
+% by curly braces, especially if spaces or commas are used inside,
+% a key name must not use spaces or other syntax characters.
+%
+% \cs{kv at normalize} takes a key value list and performs the cleanup:
+% \begin{itemize}
+% \item Spaces are removed.
+% \item Syntax characters (comma and equal sign) that are active
+%   are replaced by the same characters with standard catcode.
+%   (Example: \xpackage{babel}'s language option \xoption{turkish}
+%   uses the equal sign as active shorthand character.)
+% \end{itemize}
+% The result is stored in \cs{kv at list}, e.g.:
+% \begin{quote}
+% |\kv at list| $\rightarrow$ |,pdftitle={...},pdfsubject={...},...,|
+% \end{quote}
+% Curly braces around values (or keys) remain untouched.
+% \begin{description}
+% \item[v1.3+:]
+% One comma is added in front of the list and each pair ends with
+% a comma. Thus an empty list consists of one comma, otherwise
+% two commas encloses the list. Empty entries other than the first
+% are removed.
+% \item[v1.0 -- v1.2:]
+% Empty entries are removed later. In fact it adds a comma at the begin
+% and end to protect the last value and an easier implementation.
+% \end{description}
+%
+% \subsection{Parsing key value lists}
+%
+% \begin{declcs}{kv at parse}\,\M{key value list}\,\M{processor}
+% \end{declcs}
+% It is easier to parse a normalized list, thus \cs{kv at parse}
+% normalizes the list and calls \cs{kv at parse@normalized}.
+%
+% \begin{declcs}{kv at parse@normalized}\,\M{key value list}%
+%   \,\M{processor}
+% \end{declcs}
+% Now the key value list is split into single key value pairs.
+% For further processing the key and value are given as arguments
+% for the \meta{processor}:
+% \begin{quote}
+%   \meta{processor}\,\M{key}\,\M{value}
+% \end{quote}
+% Also key and value are stored in macro names:
+% \begin{itemize}
+% \item \cs{kv at key} stores the key.
+% \item \cs{kv at value} stores the value or if the value was not
+%   specified it has the meaning \cs{relax}.
+% \end{itemize}
+% The behaviour in pseudo code:
+% \begin{quote}
+%   foreach (\meta{key}, \meta{value}) in (\meta{key value list})\\
+%   \hspace*{1.5em}\cs{kv at key} := \meta{key}\\
+%   \hspace*{1.5em}\cs{kv at value} := \meta{value}\\
+%   \hspace*{1.5em}\meta{processor}\,\M{key}\,\M{value}
+% \end{quote}
+%
+% \begin{declcs}{kv at break}
+% \end{declcs}
+% Since version 2011/03/03 v1.11 \cs{kv at break} can be
+% called inside the \meta{processor}
+% of \cs{kv at parse} or \cs{kv at parse@normalized}, then
+% the processing is stopped and the following entries discarded.
+%
+% \subsection{Processing key value pairs}
+%
+% Key value pairs can be processed in many different ways.
+% For example, the processor for \cs{kvsetkeys} works similar
+% to \cs{setkeys} of package \xpackage{keyval}. There unknown
+% keys raise an error.
+%
+% Package \xpackage{xkeyval} also knows a star form of \cs{setkeys}
+% that stores unknown keys in an internal macro for further processing
+% with \cs{setrmkeys} and similar macros. This feature is covered
+% by processor \cs{kv at processor@known}.
+%
+% \subsubsection{Processing similar to \xpackage{keyval}}
+%
+% \begin{declcs}{kv at processor@default}\,\M{family}\,\M{key}\,\M{value}
+% \end{declcs}
+% There are many possiblities to process key value pairs.
+% \cs{kv at processor@default} is the processor used in \cs{kvsetkeys}.
+% It reimplements and extends the behaviour of
+% \xpackage{keyval}'s \cs{setkeys}.
+% In case of unknown keys \cs{setkeys} raise an error.
+% This processer, however, calls a handler instead, if it
+% is provided by the family. Both \meta{family} and \meta{key}
+% may contain package \xpackage{babel}'s shorthands
+% (since 2011/04/07 v1.13).
+%
+% Since 2011/10/18 v1.15 the family handler can reject the
+% successful handling of a key by calling \cs{kv at handled@false}.
+%
+% Since 2019/12/15 v1.18 \cs{kv at processor@default} also defines
+% macro \cs{kv at fam} with meaning \meta{family} for convenience.
+%
+% \subsubsection{Processing similar to \cs{setkeys*} of package \xpackage{xkeyval}}
+%
+% \begin{declcs}{kv at processor@known}\,\M{family}\,^^A
+%   \M{cmd}\,\M{key}\,\M{value}
+% \end{declcs}
+% The key value processor \cs{kv at processor@known} behaves similar
+% to \cs{kv at processor@default}. If the \meta{key} exists in the
+% \meta{family} its code is called, otherwise the family handler
+% is tried. If the family handler is not set or cannot handle the
+% key, the unknown key value pair is added to the macro \meta{cmd}.
+% Since 2011/10/18 v1.15.
+%
+% The behaviour in pseudo code:
+% \begin{quote}
+%   if \meta{key} exists\\
+%   \hspace*{1.5em}call the keyval code of \meta{key}\\
+%   else\\
+%   \hspace*{1.5em}if \meta{handler} for \meta{family} exists\\
+%   \hspace*{3em}handled = true\\
+%   \hspace*{3em}\meta{handler}\,\M{key}\,\M{value}\\
+%   \hspace*{3em}if handled\\
+%   \hspace*{3em}else\\
+%   \hspace*{4.5em}add \texttt{"}\M{key}\texttt{=}\M{value}\texttt{"}
+%     to \M{cmd}\\
+%   \hspace*{3em}fi\\
+%   \hspace*{1.5em}else\\
+%   \hspace*{3em}add \texttt{"}\M{key}\texttt{=}\M{value}\texttt{"}
+%     to \M{cmd}\\
+%   \hspace*{3em}raise unknown key error\\
+%   \hspace*{1.5em}fi\\
+%   fi
+% \end{quote}
+%
+% Since 2019/12/15 v1.18 \cs{kv at processor@known} also defines
+% macro \cs{kv at fam} with meaning \meta{family} for convenience.
+%
+% \subsection{Default family handler}
+%
+% \cs{kv at processor@default} calls \meta{handler}, the default
+% handler for the family, if the key does not exist in the family.
+% The handler is called with two arguments, the key and the value.
+% It can be defined with \cs{kv at set@family at hander}:
+%
+% \begin{declcs}{kv at set@family at handler}\,\M{family}\,\M{handler definition}
+% \end{declcs}
+% This sets the default family handler for the keyval family
+% \meta{family}. Inside \meta{handler definition} |#1| stands for
+% the key and |#2| is the value. Also \cs{kv at key} and \cs{kv at value}
+% can be used for the key and the value. If the value is not given,
+% \cs{kv at value} has the meaning \cs{relax}.
+%
+% \begin{declcs}{kv at unset@family at handler}\,\M{family}
+% \end{declcs}
+% It removes the family handler for \meta{family}.
+% Since 2011/10/18 v1.15.
+%
+% \subsection{Put it all together}
+%
+% \begin{declcs}{kvsetkeys}\,\M{family}\,\M{key value list}
+% \end{declcs}
+% Macro \cs{kvsetkeys} processes the \meta{key value list} with
+% the standard processor \cs{kv at processor@default}:
+% \begin{quote}
+%   \cs{kv at parse}\,\M{key value list}^^A
+%   \texttt{\{}\cs{kv at processor@default}\,\M{family}\texttt{\}}
+% \end{quote}
+%
+% \begin{declcs}{kvsetknownkeys}\,\M{family}\,\M{cmd}\,\M{key value list}
+% \end{declcs}
+% Macro \cs{kvsetknownkeys} processes the \meta{key value list}
+% with processor \cs{kv at processor@known}. All key value pairs
+% with keys that are not known in \meta{family} are stored
+% in macro \meta{cmd}. A previous contents of macro \meta{cmd}
+% will be overwritten. If all keys can be handled, \meta{cmd}
+% will be empty, otherwise it contains a key value list of
+% unhandled key value pairs.
+% Since 2011/10/18 v1.15.
+%
+% Pseudo code:
+% \begin{quote}
+%   create macro \meta{cmdaux} with unique name (inside the current group)\\
+%   \cs{def}\meta{cmdaux}\{\}\\
+%   \cs{kv at parse}\,\M{key value list}^^A
+%   \texttt{\{}\cs{kv at processor@known}\,\M{family}\,\M{cmdaux}\texttt{\}}\\
+%   \cs{let}\meta{cmd}=\meta{cmdaux}
+% \end{quote}
+%
+% \begin{declcs}{kvsetkeys at expandafter}\,\M{family}\,\M{list cmd}\\
+%   \cs{kvsetknownkeys at expandafter}\,\M{family}\,%
+%   \M{cmd}\,\M{list cmd}
+% \end{declcs}
+% Both macros behave like the counterparts without suffix
+% |@expandafter|. The difference is that the key value list is
+% given as macro that is expanded once.
+% Since 2011/10/18 v1.15.
+%
+% Thus you can replace \cs{setkeys} of package \xpackage{keyval}
+% by the key value parser of this package:
+% \begin{quote}
+%   |\renewcommand*{\setkeys}{\kvsetkeys}|\\
+%   or\\
+%   |\let\setkeys\kvsetkeys|
+% \end{quote}
+%
+% \subsection{Comma separated lists}
+%
+% Since version 2007/09/29 v1.3 this package also supports the normalizing
+% and parsing of general comma separated lists.
+%
+% \begin{declcs}{comma at normalize}\,\M{comma list}
+% \end{declcs}
+% Macro \cs{comma at normalize} normalizes the comma separated list,
+% removes spaces around commas. The result is put in macro \cs{comma at list}.
+%
+% \begin{declcs}{comma at parse}\,\M{comma list}\,\M{processor}
+% \end{declcs}
+% Macro \cs{comma at parse} first normalizes the comma separated list
+% and then parses the list by calling \cs{comma at parse@normalized}.
+%
+% \begin{declcs}{comma at parse@normalized}\,\M{normalized comma list}^^A
+%   \,\M{processor}
+% \end{declcs}
+% The list is parsed. Empty entries are ignored. \meta{processor}
+% is called for each non-empty entry with the entry as argument:
+% \begin{quote}
+%   \meta{processor}|{|\meta{entry}|}|
+% \end{quote}
+% Also the entry is stored in the macro \cs{comma at entry}.
+%
+% \begin{declcs}{comma at break}
+% \end{declcs}
+% Since version 2011/03/03 v1.11 \cs{comma at break} can be
+% called inside the \meta{processor}
+% of \cs{comma at parse} or \cs{comma at parse@normalized}, then
+% the processing is stopped and the following entries discarded.
+%
+% \section{Example}
+%
+% The following example prints a short piece of HTML code using
+% the tabbing environment for indenting purpose and a key value
+% syntax for specifying the attributes of an HTML tag.
+% The example illustrates the use of a default family handler.
+%    \begin{macrocode}
+%<*example>
+\documentclass{article}
+\usepackage[T1]{fontenc}
+\usepackage{kvsetkeys}
+\usepackage{keyval}
+
+\makeatletter
+\newcommand*{\tag}[2][]{%
+  % #1: attributes
+  % #2: tag name
+  \begingroup
+    \toks@={}%
+    \let\@endslash\@empty
+    \kvsetkeys{tag}{#1}%
+    \texttt{%
+      \textless #2\the\toks@\@endslash\textgreater
+    }%
+  \endgroup
+}
+\kv at set@family at handler{tag}{%
+  % #1: key
+  % #2: value
+  \toks@\expandafter{%
+    \the\toks@
+    \space
+    #1=\string"#2\string"%
+  }%
+}
+\define at key{tag}{/}[]{%
+  \def\@endslash{/}%
+}
+\makeatother
+
+\begin{document}
+\begin{tabbing}
+  \mbox{}\qquad\=\qquad\=\kill
+  \tag{html}\\
+  \>\dots\\
+  \>\tag[border=1]{table}\\
+  \>\>\tag[width=200, span=3, /]{colgroup}\\
+  \>\>\dots\\
+  \>\tag{/table}\\
+  \>\dots\\
+  \tag{/html}\\
+\end{tabbing}
+\end{document}
+%</example>
+%    \end{macrocode}
+%
+% \StopEventually{
+% }
+%
+% \section{Implementation}
+%
+% \subsection{Identification}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%    Reload check, especially if the package is not used with \LaTeX.
+%    \begin{macrocode}
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+  \catcode13=5 % ^^M
+  \endlinechar=13 %
+  \catcode35=6 % #
+  \catcode39=12 % '
+  \catcode44=12 % ,
+  \catcode45=12 % -
+  \catcode46=12 % .
+  \catcode58=12 % :
+  \catcode64=11 % @
+  \catcode123=1 % {
+  \catcode125=2 % }
+  \expandafter\let\expandafter\x\csname ver at kvsetkeys.sty\endcsname
+  \ifx\x\relax % plain-TeX, first loading
+  \else
+    \def\empty{}%
+    \ifx\x\empty % LaTeX, first loading,
+      % variable is initialized, but \ProvidesPackage not yet seen
+    \else
+      \expandafter\ifx\csname PackageInfo\endcsname\relax
+        \def\x#1#2{%
+          \immediate\write-1{Package #1 Info: #2.}%
+        }%
+      \else
+        \def\x#1#2{\PackageInfo{#1}{#2, stopped}}%
+      \fi
+      \x{kvsetkeys}{The package is already loaded}%
+      \aftergroup\endinput
+    \fi
+  \fi
+\endgroup%
+%    \end{macrocode}
+%    Package identification:
+%    \begin{macrocode}
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+  \catcode13=5 % ^^M
+  \endlinechar=13 %
+  \catcode35=6 % #
+  \catcode39=12 % '
+  \catcode40=12 % (
+  \catcode41=12 % )
+  \catcode44=12 % ,
+  \catcode45=12 % -
+  \catcode46=12 % .
+  \catcode47=12 % /
+  \catcode58=12 % :
+  \catcode64=11 % @
+  \catcode91=12 % [
+  \catcode93=12 % ]
+  \catcode123=1 % {
+  \catcode125=2 % }
+  \expandafter\ifx\csname ProvidesPackage\endcsname\relax
+    \def\x#1#2#3[#4]{\endgroup
+      \immediate\write-1{Package: #3 #4}%
+      \xdef#1{#4}%
+    }%
+  \else
+    \def\x#1#2[#3]{\endgroup
+      #2[{#3}]%
+      \ifx#1\@undefined
+        \xdef#1{#3}%
+      \fi
+      \ifx#1\relax
+        \xdef#1{#3}%
+      \fi
+    }%
+  \fi
+\expandafter\x\csname ver at kvsetkeys.sty\endcsname
+\ProvidesPackage{kvsetkeys}%
+  [2019/12/15 v1.18 Key value parser (HO)]%
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+  \catcode13=5 % ^^M
+  \endlinechar=13 %
+  \catcode123=1 % {
+  \catcode125=2 % }
+  \catcode64=11 % @
+  \def\x{\endgroup
+    \expandafter\edef\csname KVS at AtEnd\endcsname{%
+      \endlinechar=\the\endlinechar\relax
+      \catcode13=\the\catcode13\relax
+      \catcode32=\the\catcode32\relax
+      \catcode35=\the\catcode35\relax
+      \catcode61=\the\catcode61\relax
+      \catcode64=\the\catcode64\relax
+      \catcode123=\the\catcode123\relax
+      \catcode125=\the\catcode125\relax
+    }%
+  }%
+\x\catcode61\catcode48\catcode32=10\relax%
+\catcode13=5 % ^^M
+\endlinechar=13 %
+\catcode35=6 % #
+\catcode64=11 % @
+\catcode123=1 % {
+\catcode125=2 % }
+\def\TMP at EnsureCode#1#2{%
+  \edef\KVS at AtEnd{%
+    \KVS at AtEnd
+    \catcode#1=\the\catcode#1\relax
+  }%
+  \catcode#1=#2\relax
+}
+\TMP at EnsureCode{36}{3}% $
+\TMP at EnsureCode{38}{4}% &
+\TMP at EnsureCode{39}{12}% '
+\TMP at EnsureCode{43}{12}% +
+\TMP at EnsureCode{44}{12}% ,
+\TMP at EnsureCode{45}{12}% -
+\TMP at EnsureCode{46}{12}% .
+\TMP at EnsureCode{47}{12}% /
+\TMP at EnsureCode{91}{12}% [
+\TMP at EnsureCode{93}{12}% ]
+\TMP at EnsureCode{94}{7}% ^ (superscript)
+\TMP at EnsureCode{96}{12}% `
+\TMP at EnsureCode{126}{13}% ~ (active)
+\edef\KVS at AtEnd{\KVS at AtEnd\noexpand\endinput}
+%    \end{macrocode}
+%
+% \subsection{Package loading}
+%
+%    \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname RequirePackage\endcsname\relax
+  \def\TMP at RequirePackage#1[#2]{%
+    \begingroup\expandafter\expandafter\expandafter\endgroup
+    \expandafter\ifx\csname ver@#1.sty\endcsname\relax
+      \input #1.sty\relax
+    \fi
+  }%
+  \TMP at RequirePackage{infwarerr}[2007/09/09]%
+  \let\PackageError\@PackageError
+\else
+\fi
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\expandafter\ifx\csname toks@\endcsname\relax
+  \toksdef\toks@=0 %
+\fi
+%    \end{macrocode}
+%
+% \subsection{Check for \eTeX}
+%
+%    \cs{unexpanded}, \cs{ifcsname}, and \cs{unless} are used if found.
+%    \begin{macrocode}
+\ifx\numexpr\@undefined
+  \catcode`\$=9 % ignore
+  \catcode`\&=14 % comment
+\else % e-TeX
+  \catcode`\$=14 % comment
+  \catcode`\&=9  % ignore
+\fi
+%    \end{macrocode}
+%
+% \subsection{Generic help macros}
+%
+%    \begin{macro}{\KVS at Empty}
+%    \begin{macrocode}
+\def\KVS at Empty{}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at FirstOfTwo}
+%    \begin{macrocode}
+\long\def\KVS at FirstOfTwo#1#2{#1}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at SecondOfTwo}
+%    \begin{macrocode}
+\long\def\KVS at SecondOfTwo#1#2{#2}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\KVS at IfEmpty}
+%    \begin{macrocode}
+\long\def\KVS at IfEmpty#1{%
+& \edef\KVS at Temp{\unexpanded{#1}}%
+$ \begingroup
+$   \toks@{#1}%
+$   \edef\KVS at Temp{\the\toks@}%
+$ \expandafter\endgroup
+  \ifx\KVS at Temp\KVS at Empty
+    \expandafter\KVS at FirstOfTwo
+  \else
+    \expandafter\KVS at SecondOfTwo
+  \fi
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+% \subsection{Normalizing}
+%
+%    \begin{macro}{\kv at normalize}
+%    \begin{macrocode}
+\long\def\kv at normalize#1{%
+  \begingroup
+    \toks@{,#1,}%
+    \KVS at Comma
+    \KVS at SpaceComma
+    \KVS at CommaSpace
+    \KVS at CommaComma
+    \KVS at Equals
+    \KVS at SpaceEquals
+    \KVS at EqualsSpace
+    \xdef\KVS at Global{\the\toks@}%
+  \endgroup
+  \let\kv at list\KVS at Global
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\comma at normalize}
+%    \begin{macrocode}
+\def\comma at normalize#1{%
+  \begingroup
+    \toks@{,#1,}%
+    \KVS at Comma
+    \KVS at SpaceComma
+    \KVS at CommaSpace
+    \KVS at CommaComma
+    \xdef\KVS at Global{\the\toks@}%
+  \endgroup
+  \let\comma at list\KVS at Global
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at Comma}
+%    Converts active commas into comma with catcode other.
+%    Also adds a comma at the end to protect the last value
+%    for next cleanup steps.
+%    \begin{macrocode}
+\begingroup
+  \lccode`\,=`\,%
+  \lccode`\~=`\,%
+\lowercase{\endgroup
+  \def\KVS at Comma{%
+    \toks@\expandafter{\expandafter}\expandafter
+    \KVS@@Comma\the\toks@~\KVS at Nil
+  }%
+  \long\def\KVS@@Comma#1~#2\KVS at Nil{%
+    \toks@\expandafter{\the\toks@#1}%
+    \KVS at IfEmpty{#2}{%
+    }{%
+      \KVS@@Comma,#2\KVS at Nil
+    }%
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at SpaceComma}
+%    Removes spaces before the comma, may add commas at the end.
+%    \begin{macrocode}
+\def\KVS at SpaceComma#1{%
+  \def\KVS at SpaceComma{%
+    \expandafter\KVS@@SpaceComma\the\toks@#1,\KVS at Nil
+  }%
+}
+\KVS at SpaceComma{ }
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS@@SpaceComma}
+%    \begin{macrocode}
+\long\def\KVS@@SpaceComma#1 ,#2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@SpaceComma#1,#2\KVS at Nil
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at CommaSpace}
+%    Removes spaces after the comma, may add commas at the end.
+%    \begin{macrocode}
+\def\KVS at CommaSpace{%
+  \expandafter\KVS@@CommaSpace\the\toks@, \KVS at Nil
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS@@CommaSpace}
+%    \begin{macrocode}
+\long\def\KVS@@CommaSpace#1, #2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@CommaSpace#1,#2\KVS at Nil
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at CommaComma}
+%    Replaces multiple commas by one comma.
+%    \begin{macrocode}
+\def\KVS at CommaComma{%
+  \expandafter\KVS@@CommaComma\the\toks@,\KVS at Nil
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS@@CommaComma}
+%    \begin{macrocode}
+\long\def\KVS@@CommaComma#1,,#2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1,}% (!)
+  }{%
+    \KVS@@CommaComma#1,#2\KVS at Nil
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\KVS at Equals}
+%    Converts active equals signs into catcode other characters.
+%    \begin{macrocode}
+\begingroup
+  \lccode`\==`\=%
+  \lccode`\~=`\=%
+\lowercase{\endgroup
+  \def\KVS at Equals{%
+    \toks@\expandafter{\expandafter}\expandafter
+    \KVS@@Equals\the\toks@~\KVS at Nil
+  }%
+  \long\def\KVS@@Equals#1~#2\KVS at Nil{%
+    \edef\KVS at Temp{\the\toks@}%
+    \ifx\KVS at Temp\KVS at Empty
+      \expandafter\KVS at FirstOfTwo
+    \else
+      \expandafter\KVS at SecondOfTwo
+    \fi
+    {%
+      \toks@{#1}%
+    }{%
+      \toks@\expandafter{\the\toks@=#1}%
+    }%
+    \KVS at IfEmpty{#2}{%
+    }{%
+      \KVS@@Equals#2\KVS at Nil
+    }%
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at SpaceEquals}
+%    Removes spaces before the equals sign.
+%    \begin{macrocode}
+\def\KVS at SpaceEquals#1{%
+  \def\KVS at SpaceEquals{%
+    \expandafter\KVS@@SpaceEquals\the\toks@#1=\KVS at Nil
+  }%
+}
+\KVS at SpaceEquals{ }
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS@@SpaceEquals}
+%    \begin{macrocode}
+\long\def\KVS@@SpaceEquals#1 =#2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@SpaceEquals#1=#2\KVS at Nil
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at EqualsSpace}
+%    Removes spaces after the equals sign.
+%    \begin{macrocode}
+\def\KVS at EqualsSpace{%
+  \expandafter\KVS@@EqualsSpace\the\toks@= \KVS at Nil
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS@@EqualsSpace}
+%    \begin{macrocode}
+\long\def\KVS@@EqualsSpace#1= #2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@EqualsSpace#1=#2\KVS at Nil
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+% \subsection{Parsing key value lists}
+%
+%    \begin{macro}{\kv at parse}
+%    Normalizes and parses the key value list. Also sets \cs{kv at list}.
+%    \begin{macrocode}
+\long\def\kv at parse#1{%
+  \kv at normalize{#1}%
+  \expandafter\kv at parse@normalized\expandafter{\kv at list}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\kv at parse@normalized}
+%    |#1|: key value list\\
+%    |#2|: processor
+%    \begin{macrocode}
+\long\def\kv at parse@normalized#1#2{%
+  \KVS at Parse#1,\KVS at Nil{#2}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at Parse}
+%    |#1,#2|: key value list\\
+%    |#3|: processor
+%    \begin{macrocode}
+\long\def\KVS at Parse#1,#2\KVS at Nil#3{%
+  \KVS at IfEmpty{#1}{%
+  }{%
+    \KVS at Process#1=\KVS at Nil{#3}%
+  }%
+  \KVS at MaybeBreak
+  \KVS at IfEmpty{#2}{%
+  }{%
+    \KVS at Parse#2\KVS at Nil{#3}%
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at Process}
+%    |#1|: key\\
+%    |#2|: value, |=|\\
+%    |#3|: processor
+%    \begin{macrocode}
+\long\def\KVS at Process#1=#2\KVS at Nil#3{%
+  \let\KVS at MaybeBreak\relax
+  \def\kv at key{#1}%
+  \KVS at IfEmpty{#2}{%
+    \let\kv at value\relax
+    #3{#1}{}%
+  }{%
+    \KVS@@Process{#1}#2\KVS at Nil{#3}%
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS@@Process}
+%    |#1|: key\\
+%    |#2|: value\\
+%    |#3|: processor
+%    \begin{macrocode}
+\long\def\KVS@@Process#1#2=\KVS at Nil#3{%
+& \edef\kv at value{\unexpanded{#2}}%
+$ \begingroup
+$   \toks@{#2}%
+$   \xdef\KVS at Global{\the\toks@}%
+$ \endgroup
+$ \let\kv at value\KVS at Global
+  #3{#1}{#2}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at MaybeBreak}
+%    \begin{macrocode}
+\let\KVS at MaybeBreak\relax
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at break}
+%    \begin{macrocode}
+\def\KVS at break#1#2#3#4{%
+  \let\KVS at MaybeBreak\relax
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\kv at break}
+%    \begin{macrocode}
+\def\kv at break{%
+  \let\KVS at MaybeBreak\KVS at break
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+% \subsection{Parsing comma lists}
+%
+%    \begin{macro}{\comma at parse}
+%    Normalizes and parses the key value list. Also sets \cs{comma at list}.
+%    \begin{macrocode}
+\def\comma at parse#1{%
+  \comma at normalize{#1}%
+  \expandafter\comma at parse@normalized\expandafter{\comma at list}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\comma at parse@normalized}
+%    |#1|: comma list\\
+%    |#2|: processor
+%    \begin{macrocode}
+\def\comma at parse@normalized#1#2{%
+  \KVS at CommaParse#1,\KVS at Nil{#2}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at CommaParse}
+%    |#1,#2|: comma list\\
+%    |#3|: processor
+%    \begin{macrocode}
+\def\KVS at CommaParse#1,#2\KVS at Nil#3{%
+  \KVS at IfEmpty{#1}{%
+  }{%
+    \def\comma at entry{#1}%
+    #3{#1}%
+  }%
+  \KVS at MaybeBreak
+  \KVS at IfEmpty{#2}{%
+  }{%
+    \KVS at CommaParse#2\KVS at Nil{#3}%
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\comma at break}
+%    \begin{macrocode}
+\def\comma at break{%
+  \let\KVS at MaybeBreak\KVS at break
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+% \subsection{Processing key value pairs}
+%
+%    \begin{macro}{\kv at handled@false}
+%    The handler can call \cs{kv at handled@false} or
+%    \cs{kv at handled@true} so report failure or success.
+%    The default is success (compatibility for versions
+%    before 2011/10/18 v1.15).
+%    \begin{macrocode}
+\def\kv at handled@false{%
+  \let\ifkv at handled@\iffalse
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\kv at handled@true}
+%    \begin{macrocode}
+\def\kv at handled@true{%
+  \let\ifkv at handled@\iftrue
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\ifkv at handled@}
+%    \begin{macrocode}
+\kv at handled@true
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\kv at processor@default}
+%    \begin{macrocode}
+\def\kv at processor@default#1#2{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+    \edef\KVS at temp{\endgroup
+      \noexpand\KVS at ProcessorDefault{#1}{#2}%
+    }%
+  \KVS at temp
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at ProcessorDefault}
+%    \begin{macrocode}
+\long\def\KVS at ProcessorDefault#1#2#3{%
+  \def\kv at fam{#1}%
+& \unless\ifcsname KV@#1@#2\endcsname
+$ \begingroup\expandafter\expandafter\expandafter\endgroup
+$ \expandafter\ifx\csname KV@#1@#2\endcsname\relax
+&   \unless\ifcsname KVS@#1 at handler\endcsname
+$   \begingroup\expandafter\expandafter\expandafter\endgroup
+$   \expandafter\ifx\csname KVS@#1 at handler\endcsname\relax
+      \kv at error@unknownkey{#1}{#2}%
+    \else
+      \kv at handled@true
+      \csname KVS@#1 at handler\endcsname{#2}{#3}%
+      \relax
+      \ifkv at handled@
+      \else
+        \kv at error@unknownkey{#1}{#2}%
+      \fi
+    \fi
+  \else
+    \ifx\kv at value\relax
+&     \unless\ifcsname KV@#1@#2 at default\endcsname
+$     \begingroup\expandafter\expandafter\expandafter\endgroup
+$     \expandafter\ifx\csname KV@#1@#2 at default\endcsname\relax
+        \kv at error@novalue{#1}{#2}%
+      \else
+        \csname KV@#1@#2 at default\endcsname
+        \relax
+      \fi
+    \else
+      \csname KV@#1@#2\endcsname{#3}%
+    \fi
+  \fi
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\kv at processor@known}
+%    \begin{macrocode}
+\def\kv at processor@known#1#2#3{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+    \edef\KVS at temp{\endgroup
+      \noexpand\KVS at ProcessorKnown{#1}\noexpand#2{#3}%
+    }%
+  \KVS at temp
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at ProcessorKnown}
+%    \begin{macrocode}
+\long\def\KVS at ProcessorKnown#1#2#3#4{%
+  \def\kv at fam{#1}%
+& \unless\ifcsname KV@#1@#3\endcsname
+$ \begingroup\expandafter\expandafter\expandafter\endgroup
+$ \expandafter\ifx\csname KV@#1@#3\endcsname\relax
+&   \unless\ifcsname KVS@#1 at handler\endcsname
+$   \begingroup\expandafter\expandafter\expandafter\endgroup
+$   \expandafter\ifx\csname KVS@#1 at handler\endcsname\relax
+      \KVS at AddUnhandled#2{#3}{#4}%
+    \else
+      \kv at handled@true
+      \csname KVS@#1 at handler\endcsname{#3}{#4}%
+      \relax
+      \ifkv at handled@
+      \else
+        \KVS at AddUnhandled#2{#3}{#4}%
+      \fi
+    \fi
+  \else
+    \ifx\kv at value\relax
+&     \unless\ifcsname KV@#1@#2 at default\endcsname
+$     \begingroup\expandafter\expandafter\expandafter\endgroup
+$     \expandafter\ifx\csname KV@#1@#3 at default\endcsname\relax
+        \kv at error@novalue{#1}{#3}%
+      \else
+        \csname KV@#1@#3 at default\endcsname
+        \relax
+      \fi
+    \else
+      \csname KV@#1@#3\endcsname{#4}%
+    \fi
+  \fi
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at AddUnhandled}
+%    \begin{macrocode}
+\long\def\KVS at AddUnhandled#1#2#3{%
+& \edef#1{%
+&   \ifx#1\KVS at empty
+&   \else
+&     \unexpanded{#1},%
+&   \fi
+&   \unexpanded{{#2}={#3}}%
+& }%
+$ \begingroup
+$   \ifx#1\KVS at empty
+$     \toks@{{#2}={#3}}%
+$   \else
+$     \toks@\expandafter{#1,{#2}={#3}}%
+$   \fi
+$   \xdef\KVS at Global{\the\toks@}%
+$ \endgroup
+$ \let#1\KVS at Global
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\kv at set@family at handler}
+%    \begin{macrocode}
+\long\def\kv at set@family at handler#1#2{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+  \expandafter\endgroup
+  \expandafter\def\csname KVS@#1 at handler\endcsname##1##2{#2}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\kv at unset@family at handler}
+%    \begin{macrocode}
+\long\def\kv at unset@family at handler#1#2{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+  \expandafter\endgroup
+  \expandafter\let\csname KVS@#1 at handler\endcsname\@UnDeFiNeD
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+% \subsection{Error handling}
+%
+%    \begin{macro}{\kv at error@novalue}
+%    \begin{macrocode}
+\def\kv at error@novalue{%
+  \kv at error@generic{No value specified for}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\kv at error@unknownkey}
+%    \begin{macrocode}
+\def\kv at error@unknownkey{%
+  \kv at error@generic{Undefined}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\kv at error@generic}
+%    \begin{macrocode}
+\def\kv at error@generic#1#2#3{%
+  \PackageError{kvsetkeys}{%
+    #1 key `#3'%
+  }{%
+    The keyval family of the key `#3' is `#2'.\MessageBreak
+    The setting of the key is ignored because of the error.\MessageBreak
+    \MessageBreak
+    \@ehc
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+% \subsection{Do it all}
+%
+%    \begin{macro}{\kvsetkeys}
+%    \begin{macrocode}
+\long\def\kvsetkeys#1#2{%
+  \kv at parse{#2}{\kv at processor@default{#1}}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\kvsetkeys at expandafter}
+%    \begin{macrocode}
+\def\kvsetkeys at expandafter#1#2{%
+  \expandafter\kv at parse\expandafter{#2}{%
+    \kv at processor@default{#1}%
+  }%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\KVS at cmd}
+%    \begin{macrocode}
+\def\KVS at cmd{0}%
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at cmd@inc}
+%    \begin{macrocode}
+\def\KVS at cmd@inc{%
+& \edef\KVS at cmd{\the\numexpr\KVS at cmd+1}%
+$ \begingroup
+$   \count255=\KVS at cmd\relax
+$   \advance\count255 by 1\relax
+$ \edef\x{\endgroup
+$   \noexpand\def\noexpand\KVS at cmd{\number\count255}%
+$ }%
+$ \x
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at cmd@dec}
+%    \begin{macrocode}
+\def\KVS at cmd@dec{%
+& \edef\KVS at cmd{\the\numexpr\KVS at cmd-1}%
+$ \begingroup
+$   \count255=\KVS at cmd\relax
+$   \advance\count255 by -1\relax
+$ \edef\x{\endgroup
+$   \noexpand\def\noexpand\KVS at cmd{\number\count255}%
+$ }%
+$ \x
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at empty}
+%    \begin{macrocode}
+\def\KVS at empty{}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\kvsetknownkeys}
+%    \begin{macrocode}
+\def\kvsetknownkeys{%
+  \expandafter
+  \KVS at setknownkeys\csname KVS at cmd\KVS at cmd\endcsname{}%
+}
+%    \end{macrocode}
+%    \end{macro}
+%    \begin{macro}{\KVS at setknownkeys}
+%    \begin{macrocode}
+\long\def\KVS at setknownkeys#1#2#3#4#5{%
+  \let#1\KVS at empty
+  \KVS at cmd@inc
+  #2\kv at parse#2{#5}{\kv at processor@known{#3}#1}%
+  \KVS at cmd@dec
+  \let#4=#1%
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\kvsetknownkeys at expandafter}
+%    \begin{macrocode}
+\def\kvsetknownkeys at expandafter{%
+  \expandafter
+  \KVS at setknownkeys
+      \csname KVS at cmd\KVS at cmd\endcsname\expandafter
+}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macrocode}
+\KVS at AtEnd%
+%</package>
+%    \end{macrocode}
+%% \section{Installation}
+%
+% \subsection{Download}
+%
+% \paragraph{Package.} This package is available on
+% CTAN\footnote{\CTANpkg{kvsetkeys}}:
+% \begin{description}
+% \item[\CTAN{macros/latex/contrib/kvsetkeys/kvsetkeys.dtx}] The source file.
+% \item[\CTAN{macros/latex/contrib/kvsetkeys/kvsetkeys.pdf}] Documentation.
+% \end{description}
+%
+%
+% \paragraph{Bundle.} All the packages of the bundle `kvsetkeys'
+% are also available in a TDS compliant ZIP archive. There
+% the packages are already unpacked and the documentation files
+% are generated. The files and directories obey the TDS standard.
+% \begin{description}
+% \item[\CTANinstall{install/macros/latex/contrib/kvsetkeys.tds.zip}]
+% \end{description}
+% \emph{TDS} refers to the standard ``A Directory Structure
+% for \TeX\ Files'' (\CTANpkg{tds}). Directories
+% with \xfile{texmf} in their name are usually organized this way.
+%
+% \subsection{Bundle installation}
+%
+% \paragraph{Unpacking.} Unpack the \xfile{kvsetkeys.tds.zip} in the
+% TDS tree (also known as \xfile{texmf} tree) of your choice.
+% Example (linux):
+% \begin{quote}
+%   |unzip kvsetkeys.tds.zip -d ~/texmf|
+% \end{quote}
+%
+% \subsection{Package installation}
+%
+% \paragraph{Unpacking.} The \xfile{.dtx} file is a self-extracting
+% \docstrip\ archive. The files are extracted by running the
+% \xfile{.dtx} through \plainTeX:
+% \begin{quote}
+%   \verb|tex kvsetkeys.dtx|
+% \end{quote}
+%
+% \paragraph{TDS.} Now the different files must be moved into
+% the different directories in your installation TDS tree
+% (also known as \xfile{texmf} tree):
+% \begin{quote}
+% \def\t{^^A
+% \begin{tabular}{@{}>{\ttfamily}l@{ $\rightarrow$ }>{\ttfamily}l@{}}
+%   kvsetkeys.sty & tex/generic/kvsetkeys/kvsetkeys.sty\\
+%   kvsetkeys.pdf & doc/latex/kvsetkeys/kvsetkeys.pdf\\
+%   kvsetkeys-example.tex & doc/latex/kvsetkeys/kvsetkeys-example.tex\\
+%   kvsetkeys.dtx & source/latex/kvsetkeys/kvsetkeys.dtx\\
+% \end{tabular}^^A
+% }^^A
+% \sbox0{\t}^^A
+% \ifdim\wd0>\linewidth
+%   \begingroup
+%     \advance\linewidth by\leftmargin
+%     \advance\linewidth by\rightmargin
+%   \edef\x{\endgroup
+%     \def\noexpand\lw{\the\linewidth}^^A
+%   }\x
+%   \def\lwbox{^^A
+%     \leavevmode
+%     \hbox to \linewidth{^^A
+%       \kern-\leftmargin\relax
+%       \hss
+%       \usebox0
+%       \hss
+%       \kern-\rightmargin\relax
+%     }^^A
+%   }^^A
+%   \ifdim\wd0>\lw
+%     \sbox0{\small\t}^^A
+%     \ifdim\wd0>\linewidth
+%       \ifdim\wd0>\lw
+%         \sbox0{\footnotesize\t}^^A
+%         \ifdim\wd0>\linewidth
+%           \ifdim\wd0>\lw
+%             \sbox0{\scriptsize\t}^^A
+%             \ifdim\wd0>\linewidth
+%               \ifdim\wd0>\lw
+%                 \sbox0{\tiny\t}^^A
+%                 \ifdim\wd0>\linewidth
+%                   \lwbox
+%                 \else
+%                   \usebox0
+%                 \fi
+%               \else
+%                 \lwbox
+%               \fi
+%             \else
+%               \usebox0
+%             \fi
+%           \else
+%             \lwbox
+%           \fi
+%         \else
+%           \usebox0
+%         \fi
+%       \else
+%         \lwbox
+%       \fi
+%     \else
+%       \usebox0
+%     \fi
+%   \else
+%     \lwbox
+%   \fi
+% \else
+%   \usebox0
+% \fi
+% \end{quote}
+% If you have a \xfile{docstrip.cfg} that configures and enables \docstrip's
+% TDS installing feature, then some files can already be in the right
+% place, see the documentation of \docstrip.
+%
+% \subsection{Refresh file name databases}
+%
+% If your \TeX~distribution
+% (\TeX\,Live, \mikTeX, \dots) relies on file name databases, you must refresh
+% these. For example, \TeX\,Live\ users run \verb|texhash| or
+% \verb|mktexlsr|.
+%
+% \subsection{Some details for the interested}
+%
+% \paragraph{Unpacking with \LaTeX.}
+% The \xfile{.dtx} chooses its action depending on the format:
+% \begin{description}
+% \item[\plainTeX:] Run \docstrip\ and extract the files.
+% \item[\LaTeX:] Generate the documentation.
+% \end{description}
+% If you insist on using \LaTeX\ for \docstrip\ (really,
+% \docstrip\ does not need \LaTeX), then inform the autodetect routine
+% about your intention:
+% \begin{quote}
+%   \verb|latex \let\install=y\input{kvsetkeys.dtx}|
+% \end{quote}
+% Do not forget to quote the argument according to the demands
+% of your shell.
+%
+% \paragraph{Generating the documentation.}
+% You can use both the \xfile{.dtx} or the \xfile{.drv} to generate
+% the documentation. The process can be configured by the
+% configuration file \xfile{ltxdoc.cfg}. For instance, put this
+% line into this file, if you want to have A4 as paper format:
+% \begin{quote}
+%   \verb|\PassOptionsToClass{a4paper}{article}|
+% \end{quote}
+% An example follows how to generate the
+% documentation with pdf\LaTeX:
+% \begin{quote}
+%\begin{verbatim}
+%pdflatex kvsetkeys.dtx
+%makeindex -s gind.ist kvsetkeys.idx
+%pdflatex kvsetkeys.dtx
+%makeindex -s gind.ist kvsetkeys.idx
+%pdflatex kvsetkeys.dtx
+%\end{verbatim}
+% \end{quote}
+%
+% \begin{thebibliography}{9}
+% \bibitem{tb94wright}
+%   A guide to key-value methods, Joseph Wright, second draft for
+%   \href{https://www.tug.org/tugboat}{TUGBoat}, 2009-03-17.
+%   \url{https://www.texdev.net/uploads/2009/03/keyval.pdf}
+%
+% \bibitem{keyval}
+%   David Carlisle:
+%   \textit{The \xpackage{keyval} package};
+%   1999/03/16 v1.13;
+%   \CTANpkg{keyval}.
+%
+% \end{thebibliography}
+%
+% \begin{History}
+%   \begin{Version}{2006/03/06 v1.0}
+%   \item
+%     First version.
+%   \end{Version}
+%   \begin{Version}{2006/10/19 v1.1}
+%   \item
+%     Fix of \cs{kv at set@family at handler}.
+%   \item
+%     Example added.
+%   \end{Version}
+%   \begin{Version}{2007/09/09 v1.2}
+%   \item
+%     Using package \xpackage{infwarerr} for error messages.
+%   \item
+%     Catcode section rewritten.
+%   \end{Version}
+%   \begin{Version}{2007/09/29 v1.3}
+%   \item
+%     Normalizing and parsing of comma separated lists added.
+%   \item
+%     \cs{kv at normalize} rewritten.
+%   \item
+%     Robustness increased for normalizing and parsing,
+%     e.g. for values with unmatched conditionals.
+%   \item
+%     \eTeX\ is used if available.
+%   \item
+%     Tests added for normalizing and parsing.
+%   \end{Version}
+%   \begin{Version}{2009/07/19 v1.4}
+%   \item
+%     Bug fix for \cs{kv at normalize}: unwanted space removed (Florent Chervet).
+%   \end{Version}
+%   \begin{Version}{2009/07/30 v1.5}
+%   \item
+%     Documentation addition: recommendation for Joseph Wright's
+%     review article.
+%   \end{Version}
+%   \begin{Version}{2009/12/12 v1.6}
+%   \item
+%     Short info shortened.
+%   \end{Version}
+%   \begin{Version}{2009/12/22 v1.7}
+%   \item
+%     Internal optimization (\cs{KVS at CommaSpace}, \dots, \cs{KVS at EqualsSpace}).
+%   \end{Version}
+%   \begin{Version}{2010/01/28 v1.8}
+%   \item
+%     Compatibility to ini\TeX\ added.
+%   \end{Version}
+%   \begin{Version}{2010/03/01 v1.9}
+%   \item
+%     Support of \cs{par} inside values.
+%   \end{Version}
+%   \begin{Version}{2011/01/30 v1.10}
+%   \item
+%     Already loaded package files are not input in \hologo{plainTeX}.
+%   \end{Version}
+%   \begin{Version}{2011/03/03 v1.11}
+%   \item
+%     \cs{kv at break} and \cs{comma at break} added.
+%   \end{Version}
+%   \begin{Version}{2011/04/05 v1.12}
+%   \item
+%     Error message with recovery action in help message
+%     (request by GL).
+%   \end{Version}
+%   \begin{Version}{2011/04/07 v1.13}
+%   \item
+%     \cs{kv at processor@default} supports package \xpackage{babel}'s
+%     shorthands.
+%   \item
+%     \cs{kv at set@family at handler} with shorthand support.
+%   \end{Version}
+%   \begin{Version}{2011/06/15 v1.14}
+%   \item
+%     Some optimizations in token register uses (GL, HO).
+%   \end{Version}
+%   \begin{Version}{2011/10/18 v1.15}
+%   \item
+%     \cs{kv at processor@known} and \cs{kvsetknownkeys} added.
+%   \item
+%     \cs{kvsetkeys at expandafter} and \cs{kvsetknownkeys at expandafter} added.
+%   \item
+%     Family handler can report success or failure by \cs{kv at handled@true}
+%     or \cs{kv at handled@false}.
+%   \item
+%     \cs{kv at unset@family at handler} added.
+%   \end{Version}
+%   \begin{Version}{2012/04/25 v1.16}
+%   \item
+%     \cs{kv at processor@default} and \cs{kv at processor@known} define
+%     macro \cs{kv at fam} for convenience.
+%   \item
+%     Catcode section: Catcode setting for \texttt{+} added for \hologo{eTeX}.
+%   \end{Version}
+%   \begin{Version}{2016/05/16 v1.17}
+%   \item
+%     Documentation updates.
+%   \end{Version}
+%   \begin{Version}{2019/12/15 v1.18}
+%   \item
+%     Documentation updates.
+%   \item
+%     Avoid \xpackage{etexcmds} and \xpackage{infwarwerr} in \LaTeX.
+%   \end{Version}
+% \end{History}
+%
+% \PrintIndex
+%
+% \Finale
+\endinput


Property changes on: trunk/Master/texmf-dist/source/latex/kvsetkeys/kvsetkeys.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty
===================================================================
--- trunk/Master/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty	2019-12-17 23:22:24 UTC (rev 53166)
@@ -0,0 +1,573 @@
+%%
+%% This is file `kvsetkeys.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% kvsetkeys.dtx  (with options: `package')
+%% 
+%% This is a generated file.
+%% 
+%% Project: kvsetkeys
+%% Version: 2019/12/15 v1.18
+%% 
+%% Copyright (C)
+%%    2006, 2007, 2009-2012 Heiko Oberdiek
+%%    2016-2019 Oberdiek Package Support Group
+%% 
+%% This work 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. This version of this license is in
+%%    https://www.latex-project.org/lppl/lppl-1-3c.txt
+%% and the latest version of this license is in
+%%    https://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of
+%% LaTeX version 2005/12/01 or later.
+%% 
+%% This work has the LPPL maintenance status "maintained".
+%% 
+%% The Current Maintainers of this work are
+%% Heiko Oberdiek and the Oberdiek Package Support Group
+%% https://github.com/ho-tex/kvsetkeys/issues
+%% 
+%% 
+%% The Base Interpreter refers to any `TeX-Format',
+%% because some files are installed in TDS:tex/generic//.
+%% 
+%% This work consists of the main source file kvsetkeys.dtx
+%% and the derived files
+%%    kvsetkeys.sty, kvsetkeys.pdf, kvsetkeys.ins, kvsetkeys.drv,
+%%    kvsetkeys-example.tex, kvsetkeys-test1.tex,
+%%    kvsetkeys-test2.tex, kvsetkeys-test3.tex,
+%%    kvsetkeys-test4.tex.
+%% 
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+  \catcode13=5 % ^^M
+  \endlinechar=13 %
+  \catcode35=6 % #
+  \catcode39=12 % '
+  \catcode44=12 % ,
+  \catcode45=12 % -
+  \catcode46=12 % .
+  \catcode58=12 % :
+  \catcode64=11 % @
+  \catcode123=1 % {
+  \catcode125=2 % }
+  \expandafter\let\expandafter\x\csname ver at kvsetkeys.sty\endcsname
+  \ifx\x\relax % plain-TeX, first loading
+  \else
+    \def\empty{}%
+    \ifx\x\empty % LaTeX, first loading,
+      % variable is initialized, but \ProvidesPackage not yet seen
+    \else
+      \expandafter\ifx\csname PackageInfo\endcsname\relax
+        \def\x#1#2{%
+          \immediate\write-1{Package #1 Info: #2.}%
+        }%
+      \else
+        \def\x#1#2{\PackageInfo{#1}{#2, stopped}}%
+      \fi
+      \x{kvsetkeys}{The package is already loaded}%
+      \aftergroup\endinput
+    \fi
+  \fi
+\endgroup%
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+  \catcode13=5 % ^^M
+  \endlinechar=13 %
+  \catcode35=6 % #
+  \catcode39=12 % '
+  \catcode40=12 % (
+  \catcode41=12 % )
+  \catcode44=12 % ,
+  \catcode45=12 % -
+  \catcode46=12 % .
+  \catcode47=12 % /
+  \catcode58=12 % :
+  \catcode64=11 % @
+  \catcode91=12 % [
+  \catcode93=12 % ]
+  \catcode123=1 % {
+  \catcode125=2 % }
+  \expandafter\ifx\csname ProvidesPackage\endcsname\relax
+    \def\x#1#2#3[#4]{\endgroup
+      \immediate\write-1{Package: #3 #4}%
+      \xdef#1{#4}%
+    }%
+  \else
+    \def\x#1#2[#3]{\endgroup
+      #2[{#3}]%
+      \ifx#1\@undefined
+        \xdef#1{#3}%
+      \fi
+      \ifx#1\relax
+        \xdef#1{#3}%
+      \fi
+    }%
+  \fi
+\expandafter\x\csname ver at kvsetkeys.sty\endcsname
+\ProvidesPackage{kvsetkeys}%
+  [2019/12/15 v1.18 Key value parser (HO)]%
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+  \catcode13=5 % ^^M
+  \endlinechar=13 %
+  \catcode123=1 % {
+  \catcode125=2 % }
+  \catcode64=11 % @
+  \def\x{\endgroup
+    \expandafter\edef\csname KVS at AtEnd\endcsname{%
+      \endlinechar=\the\endlinechar\relax
+      \catcode13=\the\catcode13\relax
+      \catcode32=\the\catcode32\relax
+      \catcode35=\the\catcode35\relax
+      \catcode61=\the\catcode61\relax
+      \catcode64=\the\catcode64\relax
+      \catcode123=\the\catcode123\relax
+      \catcode125=\the\catcode125\relax
+    }%
+  }%
+\x\catcode61\catcode48\catcode32=10\relax%
+\catcode13=5 % ^^M
+\endlinechar=13 %
+\catcode35=6 % #
+\catcode64=11 % @
+\catcode123=1 % {
+\catcode125=2 % }
+\def\TMP at EnsureCode#1#2{%
+  \edef\KVS at AtEnd{%
+    \KVS at AtEnd
+    \catcode#1=\the\catcode#1\relax
+  }%
+  \catcode#1=#2\relax
+}
+\TMP at EnsureCode{36}{3}% $
+\TMP at EnsureCode{38}{4}% &
+\TMP at EnsureCode{39}{12}% '
+\TMP at EnsureCode{43}{12}% +
+\TMP at EnsureCode{44}{12}% ,
+\TMP at EnsureCode{45}{12}% -
+\TMP at EnsureCode{46}{12}% .
+\TMP at EnsureCode{47}{12}% /
+\TMP at EnsureCode{91}{12}% [
+\TMP at EnsureCode{93}{12}% ]
+\TMP at EnsureCode{94}{7}% ^ (superscript)
+\TMP at EnsureCode{96}{12}% `
+\TMP at EnsureCode{126}{13}% ~ (active)
+\edef\KVS at AtEnd{\KVS at AtEnd\noexpand\endinput}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname RequirePackage\endcsname\relax
+  \def\TMP at RequirePackage#1[#2]{%
+    \begingroup\expandafter\expandafter\expandafter\endgroup
+    \expandafter\ifx\csname ver@#1.sty\endcsname\relax
+      \input #1.sty\relax
+    \fi
+  }%
+  \TMP at RequirePackage{infwarerr}[2007/09/09]%
+  \let\PackageError\@PackageError
+\else
+\fi
+\expandafter\ifx\csname toks@\endcsname\relax
+  \toksdef\toks@=0 %
+\fi
+\ifx\numexpr\@undefined
+  \catcode`\$=9 % ignore
+  \catcode`\&=14 % comment
+\else % e-TeX
+  \catcode`\$=14 % comment
+  \catcode`\&=9  % ignore
+\fi
+\def\KVS at Empty{}
+\long\def\KVS at FirstOfTwo#1#2{#1}
+\long\def\KVS at SecondOfTwo#1#2{#2}
+\long\def\KVS at IfEmpty#1{%
+& \edef\KVS at Temp{\unexpanded{#1}}%
+$ \begingroup
+$   \toks@{#1}%
+$   \edef\KVS at Temp{\the\toks@}%
+$ \expandafter\endgroup
+  \ifx\KVS at Temp\KVS at Empty
+    \expandafter\KVS at FirstOfTwo
+  \else
+    \expandafter\KVS at SecondOfTwo
+  \fi
+}
+\long\def\kv at normalize#1{%
+  \begingroup
+    \toks@{,#1,}%
+    \KVS at Comma
+    \KVS at SpaceComma
+    \KVS at CommaSpace
+    \KVS at CommaComma
+    \KVS at Equals
+    \KVS at SpaceEquals
+    \KVS at EqualsSpace
+    \xdef\KVS at Global{\the\toks@}%
+  \endgroup
+  \let\kv at list\KVS at Global
+}
+\def\comma at normalize#1{%
+  \begingroup
+    \toks@{,#1,}%
+    \KVS at Comma
+    \KVS at SpaceComma
+    \KVS at CommaSpace
+    \KVS at CommaComma
+    \xdef\KVS at Global{\the\toks@}%
+  \endgroup
+  \let\comma at list\KVS at Global
+}
+\begingroup
+  \lccode`\,=`\,%
+  \lccode`\~=`\,%
+\lowercase{\endgroup
+  \def\KVS at Comma{%
+    \toks@\expandafter{\expandafter}\expandafter
+    \KVS@@Comma\the\toks@~\KVS at Nil
+  }%
+  \long\def\KVS@@Comma#1~#2\KVS at Nil{%
+    \toks@\expandafter{\the\toks@#1}%
+    \KVS at IfEmpty{#2}{%
+    }{%
+      \KVS@@Comma,#2\KVS at Nil
+    }%
+  }%
+}
+\def\KVS at SpaceComma#1{%
+  \def\KVS at SpaceComma{%
+    \expandafter\KVS@@SpaceComma\the\toks@#1,\KVS at Nil
+  }%
+}
+\KVS at SpaceComma{ }
+\long\def\KVS@@SpaceComma#1 ,#2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@SpaceComma#1,#2\KVS at Nil
+  }%
+}
+\def\KVS at CommaSpace{%
+  \expandafter\KVS@@CommaSpace\the\toks@, \KVS at Nil
+}
+\long\def\KVS@@CommaSpace#1, #2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@CommaSpace#1,#2\KVS at Nil
+  }%
+}
+\def\KVS at CommaComma{%
+  \expandafter\KVS@@CommaComma\the\toks@,\KVS at Nil
+}
+\long\def\KVS@@CommaComma#1,,#2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1,}% (!)
+  }{%
+    \KVS@@CommaComma#1,#2\KVS at Nil
+  }%
+}
+\begingroup
+  \lccode`\==`\=%
+  \lccode`\~=`\=%
+\lowercase{\endgroup
+  \def\KVS at Equals{%
+    \toks@\expandafter{\expandafter}\expandafter
+    \KVS@@Equals\the\toks@~\KVS at Nil
+  }%
+  \long\def\KVS@@Equals#1~#2\KVS at Nil{%
+    \edef\KVS at Temp{\the\toks@}%
+    \ifx\KVS at Temp\KVS at Empty
+      \expandafter\KVS at FirstOfTwo
+    \else
+      \expandafter\KVS at SecondOfTwo
+    \fi
+    {%
+      \toks@{#1}%
+    }{%
+      \toks@\expandafter{\the\toks@=#1}%
+    }%
+    \KVS at IfEmpty{#2}{%
+    }{%
+      \KVS@@Equals#2\KVS at Nil
+    }%
+  }%
+}
+\def\KVS at SpaceEquals#1{%
+  \def\KVS at SpaceEquals{%
+    \expandafter\KVS@@SpaceEquals\the\toks@#1=\KVS at Nil
+  }%
+}
+\KVS at SpaceEquals{ }
+\long\def\KVS@@SpaceEquals#1 =#2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@SpaceEquals#1=#2\KVS at Nil
+  }%
+}
+\def\KVS at EqualsSpace{%
+  \expandafter\KVS@@EqualsSpace\the\toks@= \KVS at Nil
+}
+\long\def\KVS@@EqualsSpace#1= #2\KVS at Nil{%
+  \KVS at IfEmpty{#2}{%
+    \toks@{#1}%
+  }{%
+    \KVS@@EqualsSpace#1=#2\KVS at Nil
+  }%
+}
+\long\def\kv at parse#1{%
+  \kv at normalize{#1}%
+  \expandafter\kv at parse@normalized\expandafter{\kv at list}%
+}
+\long\def\kv at parse@normalized#1#2{%
+  \KVS at Parse#1,\KVS at Nil{#2}%
+}
+\long\def\KVS at Parse#1,#2\KVS at Nil#3{%
+  \KVS at IfEmpty{#1}{%
+  }{%
+    \KVS at Process#1=\KVS at Nil{#3}%
+  }%
+  \KVS at MaybeBreak
+  \KVS at IfEmpty{#2}{%
+  }{%
+    \KVS at Parse#2\KVS at Nil{#3}%
+  }%
+}
+\long\def\KVS at Process#1=#2\KVS at Nil#3{%
+  \let\KVS at MaybeBreak\relax
+  \def\kv at key{#1}%
+  \KVS at IfEmpty{#2}{%
+    \let\kv at value\relax
+    #3{#1}{}%
+  }{%
+    \KVS@@Process{#1}#2\KVS at Nil{#3}%
+  }%
+}
+\long\def\KVS@@Process#1#2=\KVS at Nil#3{%
+& \edef\kv at value{\unexpanded{#2}}%
+$ \begingroup
+$   \toks@{#2}%
+$   \xdef\KVS at Global{\the\toks@}%
+$ \endgroup
+$ \let\kv at value\KVS at Global
+  #3{#1}{#2}%
+}
+\let\KVS at MaybeBreak\relax
+\def\KVS at break#1#2#3#4{%
+  \let\KVS at MaybeBreak\relax
+}
+\def\kv at break{%
+  \let\KVS at MaybeBreak\KVS at break
+}
+\def\comma at parse#1{%
+  \comma at normalize{#1}%
+  \expandafter\comma at parse@normalized\expandafter{\comma at list}%
+}
+\def\comma at parse@normalized#1#2{%
+  \KVS at CommaParse#1,\KVS at Nil{#2}%
+}
+\def\KVS at CommaParse#1,#2\KVS at Nil#3{%
+  \KVS at IfEmpty{#1}{%
+  }{%
+    \def\comma at entry{#1}%
+    #3{#1}%
+  }%
+  \KVS at MaybeBreak
+  \KVS at IfEmpty{#2}{%
+  }{%
+    \KVS at CommaParse#2\KVS at Nil{#3}%
+  }%
+}
+\def\comma at break{%
+  \let\KVS at MaybeBreak\KVS at break
+}
+\def\kv at handled@false{%
+  \let\ifkv at handled@\iffalse
+}
+\def\kv at handled@true{%
+  \let\ifkv at handled@\iftrue
+}
+\kv at handled@true
+\def\kv at processor@default#1#2{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+    \edef\KVS at temp{\endgroup
+      \noexpand\KVS at ProcessorDefault{#1}{#2}%
+    }%
+  \KVS at temp
+}
+\long\def\KVS at ProcessorDefault#1#2#3{%
+  \def\kv at fam{#1}%
+& \unless\ifcsname KV@#1@#2\endcsname
+$ \begingroup\expandafter\expandafter\expandafter\endgroup
+$ \expandafter\ifx\csname KV@#1@#2\endcsname\relax
+&   \unless\ifcsname KVS@#1 at handler\endcsname
+$   \begingroup\expandafter\expandafter\expandafter\endgroup
+$   \expandafter\ifx\csname KVS@#1 at handler\endcsname\relax
+      \kv at error@unknownkey{#1}{#2}%
+    \else
+      \kv at handled@true
+      \csname KVS@#1 at handler\endcsname{#2}{#3}%
+      \relax
+      \ifkv at handled@
+      \else
+        \kv at error@unknownkey{#1}{#2}%
+      \fi
+    \fi
+  \else
+    \ifx\kv at value\relax
+&     \unless\ifcsname KV@#1@#2 at default\endcsname
+$     \begingroup\expandafter\expandafter\expandafter\endgroup
+$     \expandafter\ifx\csname KV@#1@#2 at default\endcsname\relax
+        \kv at error@novalue{#1}{#2}%
+      \else
+        \csname KV@#1@#2 at default\endcsname
+        \relax
+      \fi
+    \else
+      \csname KV@#1@#2\endcsname{#3}%
+    \fi
+  \fi
+}
+\def\kv at processor@known#1#2#3{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+    \edef\KVS at temp{\endgroup
+      \noexpand\KVS at ProcessorKnown{#1}\noexpand#2{#3}%
+    }%
+  \KVS at temp
+}
+\long\def\KVS at ProcessorKnown#1#2#3#4{%
+  \def\kv at fam{#1}%
+& \unless\ifcsname KV@#1@#3\endcsname
+$ \begingroup\expandafter\expandafter\expandafter\endgroup
+$ \expandafter\ifx\csname KV@#1@#3\endcsname\relax
+&   \unless\ifcsname KVS@#1 at handler\endcsname
+$   \begingroup\expandafter\expandafter\expandafter\endgroup
+$   \expandafter\ifx\csname KVS@#1 at handler\endcsname\relax
+      \KVS at AddUnhandled#2{#3}{#4}%
+    \else
+      \kv at handled@true
+      \csname KVS@#1 at handler\endcsname{#3}{#4}%
+      \relax
+      \ifkv at handled@
+      \else
+        \KVS at AddUnhandled#2{#3}{#4}%
+      \fi
+    \fi
+  \else
+    \ifx\kv at value\relax
+&     \unless\ifcsname KV@#1@#2 at default\endcsname
+$     \begingroup\expandafter\expandafter\expandafter\endgroup
+$     \expandafter\ifx\csname KV@#1@#3 at default\endcsname\relax
+        \kv at error@novalue{#1}{#3}%
+      \else
+        \csname KV@#1@#3 at default\endcsname
+        \relax
+      \fi
+    \else
+      \csname KV@#1@#3\endcsname{#4}%
+    \fi
+  \fi
+}
+\long\def\KVS at AddUnhandled#1#2#3{%
+& \edef#1{%
+&   \ifx#1\KVS at empty
+&   \else
+&     \unexpanded{#1},%
+&   \fi
+&   \unexpanded{{#2}={#3}}%
+& }%
+$ \begingroup
+$   \ifx#1\KVS at empty
+$     \toks@{{#2}={#3}}%
+$   \else
+$     \toks@\expandafter{#1,{#2}={#3}}%
+$   \fi
+$   \xdef\KVS at Global{\the\toks@}%
+$ \endgroup
+$ \let#1\KVS at Global
+}
+\long\def\kv at set@family at handler#1#2{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+  \expandafter\endgroup
+  \expandafter\def\csname KVS@#1 at handler\endcsname##1##2{#2}%
+}
+\long\def\kv at unset@family at handler#1#2{%
+  \begingroup
+    \csname @safe at activestrue\endcsname
+    \let\ifincsname\iftrue
+  \expandafter\endgroup
+  \expandafter\let\csname KVS@#1 at handler\endcsname\@UnDeFiNeD
+}
+\def\kv at error@novalue{%
+  \kv at error@generic{No value specified for}%
+}
+\def\kv at error@unknownkey{%
+  \kv at error@generic{Undefined}%
+}
+\def\kv at error@generic#1#2#3{%
+  \PackageError{kvsetkeys}{%
+    #1 key `#3'%
+  }{%
+    The keyval family of the key `#3' is `#2'.\MessageBreak
+    The setting of the key is ignored because of the error.\MessageBreak
+    \MessageBreak
+    \@ehc
+  }%
+}
+\long\def\kvsetkeys#1#2{%
+  \kv at parse{#2}{\kv at processor@default{#1}}%
+}
+\def\kvsetkeys at expandafter#1#2{%
+  \expandafter\kv at parse\expandafter{#2}{%
+    \kv at processor@default{#1}%
+  }%
+}
+\def\KVS at cmd{0}%
+\def\KVS at cmd@inc{%
+& \edef\KVS at cmd{\the\numexpr\KVS at cmd+1}%
+$ \begingroup
+$   \count255=\KVS at cmd\relax
+$   \advance\count255 by 1\relax
+$ \edef\x{\endgroup
+$   \noexpand\def\noexpand\KVS at cmd{\number\count255}%
+$ }%
+$ \x
+}
+\def\KVS at cmd@dec{%
+& \edef\KVS at cmd{\the\numexpr\KVS at cmd-1}%
+$ \begingroup
+$   \count255=\KVS at cmd\relax
+$   \advance\count255 by -1\relax
+$ \edef\x{\endgroup
+$   \noexpand\def\noexpand\KVS at cmd{\number\count255}%
+$ }%
+$ \x
+}
+\def\KVS at empty{}
+\def\kvsetknownkeys{%
+  \expandafter
+  \KVS at setknownkeys\csname KVS at cmd\KVS at cmd\endcsname{}%
+}
+\long\def\KVS at setknownkeys#1#2#3#4#5{%
+  \let#1\KVS at empty
+  \KVS at cmd@inc
+  #2\kv at parse#2{#5}{\kv at processor@known{#3}#1}%
+  \KVS at cmd@dec
+  \let#4=#1%
+}
+\def\kvsetknownkeys at expandafter{%
+  \expandafter
+  \KVS at setknownkeys
+      \csname KVS at cmd\KVS at cmd\endcsname\expandafter
+}
+\KVS at AtEnd%
+%% \section{Installation}
+\endinput
+%%
+%% End of file `kvsetkeys.sty'.


Property changes on: trunk/Master/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2019-12-17 23:21:23 UTC (rev 53165)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2019-12-17 23:22:24 UTC (rev 53166)
@@ -386,7 +386,7 @@
     koma-moderncvclassic koma-script koma-script-examples koma-script-sfs
     komacv komacv-rg kotex-oblivoir kotex-plain kotex-utf kotex-utils
     kpfonts ksfh_nat ksp-thesis
-    ktv-texdata ku-template kurdishlipsum kurier kvmap kvoptions
+    ktv-texdata ku-template kurdishlipsum kurier kvmap kvoptions kvsetkeys
   l2picfaq l2tabu l2tabu-english l2tabu-french l2tabu-italian l2tabu-spanish
     l3backend l3build l3kernel l3packages l3experimental
     labbook labels labels4easylist labelschanged

Modified: trunk/Master/tlpkg/tlpsrc/collection-latex.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-latex.tlpsrc	2019-12-17 23:21:23 UTC (rev 53165)
+++ trunk/Master/tlpkg/tlpsrc/collection-latex.tlpsrc	2019-12-17 23:22:24 UTC (rev 53166)
@@ -25,6 +25,7 @@
 depend grfext
 depend hyperref
 depend kvoptions
+depend kvsetkeys
 depend latex
 depend latex-bin
 depend latex-fonts

Added: trunk/Master/tlpkg/tlpsrc/kvsetkeys.tlpsrc
===================================================================


More information about the tex-live-commits mailing list