texlive[65623] Master: expkv-bundle (24jan23)

commits+karl at tug.org commits+karl at tug.org
Tue Jan 24 21:57:30 CET 2023


Revision: 65623
          http://tug.org/svn/texlive?view=revision&revision=65623
Author:   karl
Date:     2023-01-24 21:57:30 +0100 (Tue, 24 Jan 2023)
Log Message:
-----------
expkv-bundle (24jan23)

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/README.md
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/comparison.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.pdf
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/impatient.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/introduction.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-cs.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-def.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-main.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-opt.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-pop.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-enverb.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-examples.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-l3doctweaks.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-logos.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-lst.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-noidx.tex
    trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-prefixes.tex
    trunk/Master/texmf-dist/source/latex/expkv-bundle/
    trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-bundle.ins
    trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-cs.dtx
    trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-def.dtx
    trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt-2020-10-10.dtx
    trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt.dtx
    trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-pop.dtx
    trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv.dtx
    trunk/Master/texmf-dist/tex/context/third/expkv-bundle/
    trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-cs.tex
    trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-def.tex
    trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-pop.tex
    trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv.tex
    trunk/Master/texmf-dist/tex/generic/expkv-bundle/
    trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-cs.tex
    trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-def.tex
    trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-pop.tex
    trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv.tex
    trunk/Master/texmf-dist/tex/latex/expkv-bundle/
    trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-cs.sty
    trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-def.sty
    trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt-2020-10-10.sty
    trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt.sty
    trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-pop.sty
    trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv.sty
    trunk/Master/tlpkg/tlpsrc/expkv-bundle.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/README.md	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,46 @@
+-------------------------------------------------------------------------------
+# `expkv-bundle` -- an expandable key=value implementation and more
+
+Version 2023-01-23
+
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+
+Hosted on the Island of TeX at https://gitlab.com/islandoftex/texmf/expkv-bundle
+
+-------------------------------------------------------------------------------
+
+Copyright (C) 2020-2023 Jonathan P. Spratte
+
+This work may be distributed and/or modified under the conditions of the LaTeX
+Project Public License (LPPL), either version 1.3c of this license or (at your
+option) any later version. The latest version of this license is in the file:
+
+  http://www.latex-project.org/lppl.txt
+
+This work is "maintained" (as per LPPL maintenance status) by
+  Jonathan P. Spratte
+
+-------------------------------------------------------------------------------
+
+## Summary of Contents
+
+`expkv-bundle` is a collection of different packages that provide key=value
+functionality in plainTeX, LaTeX, and ConTeXt.
+
+At the core the `expkv` package implements two expandable key=value parsers that
+are somewhat fast and robust against common bugs in many key=value
+implementations (no accidental brace stripping, no fragility for active commas
+or equals signs).
+
+`expkv-cs` enables users to define expandable key=value macros in a comfortable
+and straight forward way.
+
+`expkv-def` provides an interface to define common key types for `expkv` similar
+to the key defining interfaces of wide spread key=value implementations.
+
+`expkv-opt` allows to parse package or class options in LaTeX via `expkv`.
+
+`expkv-pop` is a utility package to define prefix oriented parsers that allow a
+somewhat natural formulation (it provides the core functionality for the
+key-defining front ends of both `expkv-cs` and `expkv-def`).


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/comparison.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/comparison.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/comparison.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,246 @@
+\section{Comparisons}\label{sec:cmp}
+
+This section makes some basic comparison between \expkv\ and other \kv\
+packages. The comparisons are really concise, regarding speed, feature range
+(without listing the features of each package, comparisons are done against the
+base \expkv\ not counting other packages in \expkvbundle\ that extend it, so
+\enquote{bigger feature set} might not necessarily be true if everything is
+included), and bugs and misfeatures.
+
+Comparisons of speed are done with a very simple test key and the help of the
+\pkg{l3benchmark} package. The key and its usage should be equivalent to
+\begin{enverb}[no-tcb]
+  \protected\ekvdef{test}{height}{\def\myheight{#1}}
+  \ekvsetdef\expkvtest{test}
+  \expkvtest{ height = 6 }
+\end{enverb}
+and only the usage of the key, not its definition, is benchmarked. For the
+impatient, the essence of these comparisons regarding speed and buggy
+behaviour is contained in \autoref{tab:comp}.
+
+As far as I know \expkv\ is the only fully expandable \kv\ parser. I tried to
+compare \expkv\ to every \kv\ package listed on
+\href{https://ctan.org/topic/keyval}{CTAN}, however, one might notice that
+some of those are missing from this list. That's because I didn't get the
+others to work due to bugs, or because they just provide wrappers around other
+packages in this list.
+
+In this subsection is no benchmark of |\ekvparse| and |\keyval_parse:NNn|
+contained, as most other packages don't provide equivalent features to my
+knowledge. |\ekvparse| is slightly faster than |\ekvset|, but keep in mind
+that it does less. The same is true for |\keyval_parse:NNn| compared to
+|\keys_set:nn| of \pkg{expl3} (where the difference is much bigger). Comparing
+just the two, |\ekvparse| is a tad faster than |\keyval_parse:NNn| because of
+two tests (for empty key names and only a single equal sign) which are
+omitted.
+
+\paragraph{\pkg{keyval}} is the fastest \kv\ package there is and has a minimal
+feature set with a slightly different way how it handles keys without values
+compared to \expkv. That might be considered a drawback, as it limits the
+versatility, but also as an advantage, as it might reduce doubled code. Keep in
+mind that as soon as someone loads \pkg{xkeyval} the performance of \pkg{keyval}
+gets replaced by \pkg{xkeyval}'s.
+
+Also \pkg{keyval} has a \pmso{bug}feature, which unfortunately can't really be
+resolved without breaking backwards compatibility for \emph{many} documents,
+namely it strips braces from the argument before stripping spaces if the
+outer most braces aren't surrounded by spaces, also it might strip more than one
+set of braces. Hence all of the following are equivalent in their outcome,
+though the last two lines should result in something different than the first
+two:
+\begin{enverb}[no-tcb]
+  \setkeys{foo}{bar=baz}
+  \setkeys{foo}{bar= {baz}}
+  \setkeys{foo}{bar={ baz}}  % should be ` baz'
+  \setkeys{foo}{bar={{baz}}} % should be `{baz}'
+\end{enverb}
+
+\pkg{keyval} doesn't work with non-standard category codes of |=| and |,|. Also
+if a \kv\ pair contains multiple equals signs outside of braces everything post
+the first is silently ignored so the following two inputs yield identical
+outputs:
+\begin{enverb}[no-tcb,lst=belowskip=0pt]
+  \setkeys{foo}{bar=baz}
+  \setkeys{foo}{bar=baz=and more}
+\end{enverb}
+
+\paragraph{\pkg{xkeyval}} is pretty slow (yet not the slowest), but it provides
+more functionality, e.g., it has an interface to disable a list of keys, can
+search multiple sets simultaneously, and has an intriguing mechanism it calls
+\enquote{Pointers} to save the value of particular keys for later reuse. It
+contains the same bug as \pkg{keyval} as it has to be compatible with it by
+design (it replaces \pkg{keyval}'s frontend), but also adds even more cases in
+which braces are stripped that shouldn't be stripped, worsening the situation.
+
+\pkg{xkeyval} does work with non-standard category codes of |=| and |,|, but the
+used mechanism fails if the input contains a mix of different category codes for
+the same character. Just like with \pkg{keyval} equals signs after the first and
+everything after those is ignored.
+
+\paragraph{\pkg{ltxkeys}} is no longer compatible with the \LaTeX\ kernel
+starting with the release 2020-10-01. It is by far the slowest \kv\ package I've
+tested -- which is funny, because it aims to be ``[\ldots] faster [\ldots] than
+these earlier packages [referring to \pkg{keyval} and \pkg{xkeyval}].'' It needs
+more time to parse zero~keys than five of the packages in this comparison need
+to parse 100~keys.  Since it aims to have a bigger feature set than
+\pkg{xkeyval}, it most definitely also has a bigger feature set than \expkv.
+Also, it can't parse |\long| input, so as soon as your values contain a |\par|,
+it'll throw errors.  Furthermore, \pkg{ltxkeys} doesn't strip outer braces at
+all by design, which, imho, is a weird design choice. Some of the more
+intriguing features (e.g., the |\argpattern| mechanism) didn't work for me. In
+addition \pkg{ltxkeys} loads \pkg{catoptions} which is known to introduce bugs
+(e.g., see \url{https://tex.stackexchange.com/questions/461783}). Because it is
+no longer compatible with the kernel, I stop benchmarking it (so the numbers
+listed here and in \autoref{tab:comp} regarding \pkg{ltxkeys} were last updated
+on 2020-10-05).
+
+\pkg{ltxkeys} works with non-standard category codes, it also silently ignores
+any additional equals signs and the following tokens.
+
+\paragraph{\pkg{l3keys}} is at the slower end of the midfield yet not unusably
+slow, but has an, imho, great interface to define keys. It strips \emph{all}
+outer spaces, even if somehow multiple spaces ended up on either end. It offers
+more features, but has pretty much been bound to \pkg{expl3} code before.
+Nowadays the \LaTeX\ kernel has an interface with the macros |\DeclareKeys|,
+|\SetKeys|, and |\ProcessKeyOptions| that provides access to \pkg{l3keys} from
+the \LaTeXe\ layer as well as parsing package options with it. Because of the
+|\ProcessKeyOptions| macro and its features the only two viable options to
+provide \kv\ options for new projects in my opinion are the kernel's methods and
+\expkvo\ as those are the only two until now up to my knowledge that support
+parsing the raw options, and future options.
+
+\pkg{l3keys} handles active commas and equals signs fine. Multiple equals signs
+lead to an error if additional equals signs aren't nested inside of braces, so
+perfectly predictable behaviour here.
+
+\paragraph{\pkg{pgfkeys}} is among the top~4 of speed if one uses |\pgfqkeys|
+over |\pgfkeys|, else the initialisation parsing the family path takes roughly
+\SI{43}{\ops} and moves it two spots down the list (so in \autoref{tab:comp}
+both $p_0$ and $T_0$ would be about \SI{43}{\ops} bigger if
+|\pgfkeys{|\meta{path}|/.cd,|\meta{keys}|}| was used instead). It has an
+\emph{enormous} feature set. It stores keys in a way that reminds one of folders
+in a Unix system which allows interesting features and has other syntactic
+sugars. It is another package that implements something like the \expnotation\
+with less different options though. To get the best performance |\pgfqkeys| was
+used in the benchmark. It has the same or a very similar bug \pkg{keyval} has.
+The brace bug (and also the category fragility) can be fixed by \pkg{pgfkeyx},
+but this package was last updated in 2012 and it slows down |\pgfkeys| by
+factor~\num{8}. Also \pkg{pgfkeyx} is no longer compatible with versions of
+\pkg{pgfkeys} newer than 2020-05-25.
+
+\pkg{pgfkeys} silently drops anything after the second unbraced equals sign in a
+\kv\ pair.
+
+\paragraph{\pkg{kvsetkeys} with \pkg{kvdefinekeys}} is in the slower midfield,
+but it works even if commas and equals have category codes different from 12
+(just as some other packages in this list). It has quadratic run-time unlike
+most other \kv\ implementations which behave linear. The features of the
+keys are equal to those of \pkg{keyval}, the parser adds handling of unknown
+keys.
+
+\pkg{kvsetkeys} does include any additional equals sign in the value. But any
+active equals sign is turned into one of category code 12 if it's not nested in
+braces. Also spaces around superfluous equals signs are stripped. So the
+following all result in the same:
+\begin{enverb}[no-tcb,lst=belowskip=0pt]
+  \kvsetkeys{foo}{bar=baz=morebaz}
+  \kvsetkeys{foo}{bar=baz =morebaz}
+  \kvsetkeys{foo}{bar=baz= morebaz}
+  \kvsetkeys{foo}{bar=baz = morebaz}
+\end{enverb}
+
+\paragraph{\pkg{options}} is in the midfield of speed. It is faster per
+individual key than \pkg{pgfkeys} but has no shortcut like |\pgfqkeys|.
+It has a much bigger feature set than \expkv. Similar to \pkg{pgfkeys} it uses a
+folder like structure, makes searching multiple paths easy, incorporates package
+options and more. It also features a form of expansion control, predefined
+expansion kinds are limited though one can define additional ones. Unfortunately
+it also suffers from the premature unbracing bug \pkg{keyval} has.
+
+\pkg{options} can't handle non-standard category codes and will silently ignore
+superfluous equals signs and following tokens.
+
+\paragraph{\pkg{simplekv}} is hard to compare because I don't speak French (so
+I don't understand the documentation). There was an update released on
+2020-04-27 which greatly improved the package's performance and added
+functionality so that it can be used more like most of the other \kv\
+packages. Speed wise it is pretty close to \expkv. Regarding unknown keys it got
+a very interesting behaviour. It doesn't throw an error, but stores the \val\ in
+a new entry accessible with \cs[no-index]{useKV}. Also if you omit \val\ it
+stores |true| for that \key.
+
+\pkg{simplekv} can't correctly handle non-standard category codes. It silently
+ignores any unbraced equals sign beyond the first and any following tokens.
+
+\paragraph{\protect\yax} is the second slowest package I've tested. It has a
+pretty strange syntax for the \TeX-world, imho, and again a direct equivalent is
+hard to define (don't understand me wrong, I don't say I don't like the syntax,
+quite the contrary, it's just atypical). It has the premature unbracing bug,
+too. \yax\ features some prefixes one can use to make an assignment use |\edef|,
+|\gdef| or |\xdef| so has something that comes close to expansion control. Also
+somehow loading \yax\ broke \pkg{options} for me. The tested definition was:
+\begin{enverb}[no-tcb]
+  \usepackage{yax}
+  \defactiveparameter yax {\storevalue\myheight yax:height } % setup
+  \setparameterlist{yax}{ height = 6 }                       % benchmark
+\end{enverb}
+This seems important to state as \yax\ supports two different input syntaxes,
+the tested one was the one closer to traditional \kv\ input.
+
+\yax\ won't handle non-standard category codes correctly. Superfluous equals
+signs end up in the value in an unaltered form (just like with \expkv).
+
+\begin{table}
+  \def\fnsym{\textcolor{red!80!black}{*}}%
+  \sisetup{round-precision=1, round-mode=places}%
+  \begingroup
+  \centering
+  \newcommand*\yes{\textcolor{red!80!black}  {yes}}^^A
+  \newcommand*\no {\textcolor{green!80!black}{no}}^^A
+  \caption[Comparison of \kv\ packages]
+    {^^A
+      Comparison of \kv\ packages. The packages are ordered from
+      fastest to slowest for one \kv\ pair. Benchmarking was done using
+      \pkg{l3benchmark} and the scripts in the \file{Benchmarks} folder
+      of \href{https://github.com/Skillmon/tex_expkv}{the original \expkv's git
+      repository}.
+      The columns $p_i$ are the polynomial coefficients of a linear fit to the
+      run-time, $p_0$ can be interpreted as the overhead for initialisation
+      and $p_1$ the cost per key. The $T_0$ column is the actual mean ops
+      needed for an empty list argument, as the linear fit doesn't match that
+      point well in general. The column ``BB'' lists whether the
+      parsing is affected by some sort of brace bug, ``CF'' stands for
+      category code fragile and lists whether the parsing breaks with active
+      commas or equal signs.^^A
+      \label{tab:comp}^^A
+    }
+  \begin{tabular}
+      {>{\collectcell\pkg}l<{\endcollectcell}*3{S[table-format=4.1]}ccc}
+    \toprule
+    \rmfamily Package & {$p_1$} & {$p_0$} & {$T_0$}& BB & CF & Date \\
+    \midrule
+    keyval    &   13.557 &    2.202 &    7.185 & \yes & \yes & 2022-05-29 \\
+    \expkv    &   16.669 &    3.132 &    5.836 & \no  & \no  & 2023-01-10 \\
+    simplekv  &   19.943 &    2.850 &   15.120 & \no  & \yes & 2022-10-01 \\
+    pgfkeys   &   24.465 &    2.244 &   10.283 & \yes & \yes & 2021-05-15 \\
+    options   &   23.255 &   16.160 &   20.400 & \yes & \yes & 2015-03-01 \\
+    kvsetkeys & {\fnsym} & {\fnsym} &   40.360 & \no  & \no  & 2022-10-05 \\
+    l3keys    &   70.643 &   35.602 &   32.230 & \no  & \no  & 2022-12-17 \\
+    xkeyval   &  255.906 &  221.276 &  173.400 & \yes & \yes & 2022-06-16 \\
+    \yax      &  438.242 &  131.846 &  114.800 & \yes & \yes & 2010-01-22 \\
+    ltxkeys   & 3400.142 & 4737.958 & 5368.000 & \no  & \no  & 2012-11-17 \\
+    \bottomrule
+  \end{tabular}
+  \par
+  \endgroup
+  \medskip
+  \fnsym For \pkg{kvsetkeys} the linear model used for the other
+  packages is a poor fit, \pkg{kvsetkeys} seems to have approximately
+  quadratic run-time, the coefficients of the second degree polynomial fit are
+  $p_2=\num{7.617}$, $p_1=\num{47.727}$, and $p_0=\num{57.988}$. Of course the
+  other packages might not really have linear run-time, but at least from 1~to
+  20~keys the fits don't seem too bad. If one extrapolates the fits for 100
+  \kv\ pairs one finds that most of them match pretty well, the exception
+  being \pkg{ltxkeys}, which behaves quadratic as well with
+  $p_2=\num{23.500}$, $p_1=\num{2906.634}$, and $p_0=\num{6547.489}$.
+\end{table}


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

Index: trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.pdf	2023-01-24 20:56:46 UTC (rev 65622)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.pdf	2023-01-24 20:57:30 UTC (rev 65623)

Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,353 @@
+\PassOptionsToPackage{full}{textcomp}
+\documentclass[exfoo=value, exbar, exfoo=\empty]{l3doc}
+
+% preamble >>=
+\makeatletter
+\let\save at onlypreamble\@onlypreamble
+\let\@onlypreamble\@gobble
+\usepackage[all]{expkv}
+\let\@onlypreamble\save at onlypreamble
+\makeatother
+\usepackage[oldstylenums,nott]{kpfonts}
+\input{glyphtounicode}
+\pdfgentounicode=1
+\usepackage{xfp} % required for an example
+\usepackage{booktabs}
+\usepackage{array}
+\usepackage{collcell}
+\usepackage{siunitx}
+\DeclareSIUnit\ops{ops}
+\usepackage{xcolor}
+\usepackage{caption}
+\usepackage{microtype}
+\usepackage{accsupp}
+\usepackage{enumitem}
+\usepackage{randtext}
+
+\usepackage{tcolorbox}%>>=
+\newtcolorbox{exresult}[2][]
+  {%
+     colback=ekvgrey!10!white%
+    ,colframe=ekvgrey%
+    ,fontupper=\small
+    ,width={\dimexpr#2\relax}%
+    ,#1%
+  }
+\newtcbox\exres[1][]
+  {
+     colback=ekvgrey!10!white
+    ,colframe=ekvgrey
+    ,size=small
+    ,nobeforeafter
+    ,tcbox raise base
+    ,fontupper=\small
+    ,#1
+  }
+%=<<
+
+\usepackage{listings}%>>=
+\input{preamble-lst.tex}
+%=<<
+
+\let\metaORIG\meta
+\protected\def\meta #1{\texttt{\metaORIG{#1}}}
+
+\input{preamble-examples.tex}
+\input{preamble-logos.tex}
+
+\makeatletter
+% shortcuts >>=
+\newcommand\Vkey{\texttt{Val}-\key}
+\newcommand*\Nkey{\texttt{NoVal}-\key}
+\newcommand\kv{\meta{key}=\penalty2000\meta{value}}
+\newcommand\kvarg{\{\kv, \ldots\}}
+\newcommand\key{\meta{key}}
+\newcommand\val{\meta{value}}
+\newcommand\set{\meta{set}}
+\newcommand\prefix{\texorpdfstring{\textit{prefix}}{prefix}}
+\newcommand\prefixes{\textit{prefixes}}
+\newcommand\type{\texorpdfstring{\textit{type}}{type}}
+\newcommand\types{\textit{types}}
+\newcommand\tkn[2]{\texttt{\char`#1}\textsubscript{#2}}
+\newcommand\expansion{\meta{expansion}}
+%\newcommand\expnotation{}
+%\edef\expnotation
+  %{\noexpand\texttt{exp\string|}\penalty\@M-\hskip\z at skip notation}
+\newcommand\singlecs[1]
+  {%
+    The \meta{cs} should be a single control sequence, such as
+    \cs[no-index]{#1}. \ignorespaces
+  }
+\newcommand\ekvdocsection[8]
+  {%
+    \clearpage
+    \chardef\ekvdoc at insection1
+    \section[{#7}]%
+      {%
+        #7%
+        \hfill
+        \begingroup\scriptsize\ttfamily
+          \begin{tabular}{@{}r@{}l@{}}%
+            #1{\string\input\{expkv#8\}}      & \rlap{#2{\ \% plain}}\\
+            #3{\string\usepackage\{expkv#8\}} & \rlap{#4{\ \% LaTeX}}\\
+            #5{\string\usemodule[expkv#8]}    & \rlap{#6{\ \% ConTeXt}}\\
+          \end{tabular}%
+        \endgroup
+        \label{sec:expkv#8}%
+      }%
+    \chardef\ekvdoc at insection0
+  }
+\chardef\ekvdoc at insection0
+\newcommand*\genericekv
+  {\ekvdocsection{}{\textcolor{gray}}{}{\textcolor{gray}}{}{\textcolor{gray}}}
+\newcommand*\latexekv
+  {\ekvdocsection\phantom\phantom{}{\textcolor{gray}}\phantom\phantom}
+%=<<
+
+\hypersetup{linkcolor=red!80!black,urlcolor=purple!80!black}
+
+\input{preamble-prefixes.tex}
+\input{preamble-noidx.tex}
+\input{preamble-enverb.tex}
+
+% vissp >>=
+\ExplSyntaxOn
+\cs_new_protected:Npn \vissp #1
+  {
+    \group_begin:
+      \tl_set:Nn \l_tmpa_tl {#1}
+      \tl_replace_all:Nnn \l_tmpa_tl { ~ } { \asciispace }
+      \l_tmpa_tl
+    \group_end:
+  }
+\ExplSyntaxOff
+% =<<
+
+\ekvcSplit\expkvorules% >>=
+  {
+     cd = \emph{nothing}
+    ,cu = \emph{nothing}
+    ,pd = \emph{nothing}
+    ,pu = \emph{nothing}
+  }
+  {%
+    \begin{description}
+      \item[Class:]
+        \begin{description}
+          \item[defined]   #1
+          \item[undefined] #2
+        \end{description}
+      \item[Package:]
+        \begin{description}
+          \item[defined]   #3
+          \item[undefined] #4
+        \end{description}
+    \end{description}%
+  }
+\ekvcSecondaryKeys\expkvorules
+  {
+     meta d = {cd={#1},pd={#1}}
+    ,meta u = {cu={#1},pu={#1}}
+  }% =<<
+
+\newcommand*\pmso[1] % poor man's strike out%>>=
+  {%
+    \leavevmode
+    \begingroup
+      \sbox0{#1}%
+      \rlap{\vrule height .6ex depth -.5ex width \wd0\relax}%
+      \usebox0\relax
+    \endgroup
+  }%=<<
+
+\@ifdefinable\gobbledocstriptag{\def\gobbledocstriptag#1>{}}
+
+\renewcommand*\partname{Part}
+
+% \addsec and friends >>=
+\newcommand*\addsec@[2]
+  {%
+    \c at secnumdepth=%
+    \expanded
+      {%
+        \m at ne
+        \unexpanded{#1{#2}}%
+        \c at secnumdepth=\the\c at secnumdepth\relax
+      }%
+  }
+\newcommand*\addsec  {\addsec@\section}
+\newcommand*\addssec {\addsec@\subsection}
+\newcommand*\addsssec{\addsec@\subsubsection}
+% =<<
+
+\newenvironment{syntaxexample}% >>=
+  {%
+    \quote
+    \ttfamily\small\frenchspacing
+    \parskip=\z@
+    \def\indent{\leavevmode\phantom{mm}}%
+  }
+  {\endquote}
+\newenvironment{syntaxexample*}
+  {\syntaxexample\obeylines}
+  {\endsyntaxexample}% =<<
+
+\newcommand\expkvdocPrintErrors[1][]
+  {%
+    \protected\long\def\expkvdoc at errfont##1%
+      {\texttt{\frenchspacing\textcolor{red!80!black}{##1}}}%
+    \protected\long\def\ekv at err@collect##1\par##2%
+      {\expkvdoc at errfont{! \detokenize{##2} Error: ##1}#1}%
+    \protected\long\def\expkvdoc at errm##1##2%
+      {\expkvdoc at errfont{! expkv##1 Error: ##2}#1}%
+    \def\ekv at errm{\expkvdoc at errm{}}%
+    \def\ekvc at errm{\expkvdoc at errm{-cs}}%
+    \def\ekvd at errm{\expkvdoc at errm{-def}}%
+    \def\ekvp at errm{\expkvdoc at errm{-pop}}%
+  }
+\makeatother
+
+\ExplSyntaxOn
+\str_new:N \g__expkvdoc_module_str
+\cs_new_protected:Npn \expkvdocfile #1% >>=
+  {
+    \expkvdoc_for_module:nn {#1}
+      {
+        \str_if_eq:nnTF {#1} {main}
+          { \lstset{style=expkv} }
+          { \lstset{style=expkv-#1} }
+        \addtocontents{exs}
+          {
+            \medskip
+            \noindent
+            \use:c { expkv \str_if_eq:nnF {#1} {main} { \str_head:n {#1} } }
+            \smallskip
+          }
+        \input{pkg-#1.tex}
+      }
+  }% =<<
+\cs_new_protected:Npn \expkvdocdtx #1% >>=
+  {
+    \expkvdoc_for_module:nn {#1}
+      {
+        \str_if_eq:nnTF {#1} {main}
+          { \DocInput{expkv.dtx} }
+          { \DocInput{expkv-#1.dtx} }
+      }
+  }% =<<
+\cs_new_protected:Npn \expkvdoc_for_module:nn #1#2% >>=
+  {
+    \use:e
+      {
+        \exp_not:n
+          {
+            \str_gset:Nn \g__expkvdoc_module_str {#1}
+            #2
+            \str_gset:Nn \g__expkvdoc_module_str
+          }
+            { \g__expkvdoc_module_str }
+      }
+  }% =<<
+\ExplSyntaxOff
+
+\input{preamble-l3doctweaks.tex}
+
+%=<<
+
+% for thanking Niranjan
+% code from https://tex.stackexchange.com/a/635125/117050
+\def\DevnagVersion{2.17}
+\usepackage{devanagari}
+
+\newif\ifexpkvDocImplementation%\expkvDocImplementationtrue
+
+\begin{document}
+\title{\expkvbundle}
+%\title% >>=
+  %{%
+    %\texorpdfstring
+      %{%
+        %\huge\expkvbundle
+        %\\[\medskipamount]
+        %\Large an {\expFormat}andable
+        %\meta{{\kvstyle k}\kern-.05em ey}=%
+        %\meta{{\kvstyle v}\kern-.05em alue}
+        %implementation and more%
+      %}
+      %{expkv-bundle - an expandable <key>=<value> implementation and more}%
+  %}% =<<
+\author
+  {%
+    Jonathan P. Spratte%
+    \thanks
+      {%
+        \protect\randomize{jspratte at yahoo.de};
+        Special thanks to {\protect\dn Enr\2jn} (Niranjan) for valuable
+        suggestions and additions to this documentation.%
+      }%
+  }
+\date{2023-01-23}
+\begingroup
+\renewcommand*\thefootnote{\fnsymbol{footnote}}
+\maketitle
+\endgroup
+
+\begin{abstract}%>>=
+  \noindent\parfillskip=0pt
+  The \expkvbundle\ provides at its core a \emph{fully expandable} \kv\ parser,
+  that is \emph{safe} for active commas and equals signs, \emph{reliable} to
+  only strip one set of braces after spaces are stripped, and blazingly
+  \emph{fast}, as of writing this only \pkg{keyval} is faster.
+  \par
+  \bigskip
+  This parser gets augmented by a family of packages. \expkvc\ allows to easily
+  define expandable macros using a \kv\ interface, making the expandable parser
+  available to the masses. \expkvd\ provides a \kv\ interface to
+  define common \key-types. With \expkvo\ you can parse package
+  and class options. \expkvp\ enables you to design your own prefix
+  oriented parsers for interface definitions.
+\end{abstract}%=<<
+
+\tableofcontents
+
+\clearpage
+
+\begin{documentation}% >>=
+\ifexpkvDocImplementation\part{Documentation}\fi
+
+\input{introduction.tex}
+\clearpage
+\input{impatient.tex}
+
+\expkvdocfile{main}
+\expkvdocfile{cs}
+\expkvdocfile{def}
+\expkvdocfile{opt}
+\expkvdocfile{pop}
+\clearpage
+\lstset{style=expkv-all}
+\input{comparison.tex}
+\end{documentation}% =<<
+
+\clearpage
+\listofexamples
+
+\ifexpkvDocImplementation
+  \clearpage
+  \begin{implementation}% >>=
+    \part{Implementation}
+    \expkvdocdtx{main}
+    \clearpage
+    \expkvdocdtx{cs}
+    \clearpage
+    \expkvdocdtx{def}
+    \clearpage
+    \expkvdocdtx{opt}
+    \clearpage
+    \expkvdocdtx{pop}
+  \end{implementation}% =<<
+\fi
+
+\clearpage
+\PrintIndex
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/expkv-bundle.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/impatient.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/impatient.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/impatient.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,56 @@
+\addsec{\expkvbundle\ for the Impatient}
+
+This section gives a very brief and non-exhaustive overview over the contents of
+the \expkvbundle. For more information (and more functionality) you'll have to
+read the sections of the packages you're interested in.
+
+\expkvbundle\ supports expansion control in \kv\ lists. The corresponding
+syntax and features are documented in \autoref{sec:expkv:expansion}.
+
+The following user interface macros (and more) are available in the different
+packages of the bundle:
+\paragraph{Defining keys}
+\begin{itemize}
+  \item \cs[no-index]{ekvdefinekeys}\marg{set}\texttt{\kvarg}
+    defines the keys in the \kv\ list, many common key types are available
+    (\autoref{sec:d:macros} and for the types \autoref{sec:d:types}).
+  \item \cs[no-index]{ekvdef}\marg{set}\marg{key}\marg{code}
+    defines the behaviour of a \Vkey\ (\autoref{sec:expkv:setup}).
+  \item \cs[no-index]{ekvdefNoVal}\marg{set}\marg{key}\marg{code}
+    defines the behaviour of a \Nkey\ (\autoref{sec:expkv:setup}).
+\end{itemize}
+\paragraph{Parsing \kv\ lists}
+\begin{itemize}
+  \item \cs[no-index]{ekvset}\marg{set}\texttt{\kvarg}
+    sets defined keys (\autoref{sec:expkv:set}).
+  \item \cs[no-index]{ekvparse}\marg{k-code}\marg{kv-code}\texttt{\kvarg}
+    parses the \kv\ list and runs \meta{k-code} or \meta{kv-code} on the
+    elements (\autoref{sec:expkv:parse}).
+\end{itemize}
+\paragraph{Defining expandable \kv\ macros}
+\begin{itemize}
+  \item \cs[no-index]{ekvcSplit}\meta{cs}\texttt{\kvarg}\marg{code}
+    defines a fully expandable macro with the keys in the \kv\ list,
+    values are accessed by |#1| to |#9| (\autoref{sec:c:split}).
+  \item \cs[no-index]{ekvcHash}\meta{cs}\texttt{\kvarg}\marg{code}
+    defines a fully expandable macro with the keys in the \kv\ list,
+    values are accessed using \cs[no-index]{ekvcValue}\hskip0pt\marg{key}|{#1}|
+    (\autoref{sec:c:hash}).
+  \item \cs[no-index]{ekvcSecondaryKeys}\meta{cs}\texttt{\kvarg}
+    defines additional keys of predefined types for a \meta{cs} defined with
+    \cs[no-index]{ekvcSplit} or \cs[no-index]{ekvcHash}
+    (\autoref{sec:c:secondary} and for the types
+    \autoref{sec:c:secondarytypes}).
+\end{itemize}
+\paragraph{Parsing options} (\autoref{sec:o:macros})
+\begin{itemize}
+  \item \cs[no-index]{ekvoProcessOptions}\marg{set}
+    processes the global options, and the options given to the current and
+    all future calls of the package.
+  \item \cs[no-index]{ekvoProcessGlobalOptions}\marg{set}
+    processes the global options.
+  \item \cs[no-index]{ekvoProcessLocalOptions}\marg{set}
+    processes the local options of a package or class.
+  \item \cs[no-index]{ekvoProcessFutureOptions}\marg{set}
+    processes the options of future calls of the package.
+\end{itemize}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/impatient.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/introduction.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/introduction.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/introduction.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,115 @@
+\addsec{Introduction}
+%The name \expkv\ stands for \emph{exp}andable \emph{k}ey-\emph{v}alue and shall
+%be pronounced \enquote{axe(b) kay vee}.
+
+This bundle consists of different packages the base being \expkv. Most of these
+packages are available for \hologo{plainTeX}, \LaTeXe, and \hologo{ConTeXt}. For
+stylistic reasons the package names are printed as
+\expkvLogoFormat{\textit{$\langle$pkg$\rangle$}}, but the files are named
+\texttt{expkv-\meta{pkg}} (CTAN-rules don't allow \string| in names), so in
+order to load \expkvc\ in \LaTeXe\ you should use
+\begin{enverb}[no-tcb]
+  \usepackage{expkv-cs}
+\end{enverb}
+Each section describing a package of this bundle has next to its heading the
+formats in which they work printed flush right. If more than a single format is
+supported by a package the functionality is defined by the \hologo{plainTeX}
+variant and the other variants only load the generic code in a way suitable for
+the format.
+
+\addssec{Terminology}
+This documentation uses a few terms which always mean specific things:
+\begin{description}
+  \item[\kv\ pair]
+    is one element in a comma separated list which contains at least one equals
+    sign \emph{not} contained in any braces, and the first such equals sign is
+    the separator between the \key\ (with an optional \expansion\ prefix) and
+    the \val.
+  \item[\key]
+    means the entire left-hand side of a \kv\ pair with an optional \expansion\
+    prefix stripped, or if =\val\ is omitted the complete list element, again
+    with an \expansion\ prefix stripped.
+  \item[\key-name]
+    synonymous to \key.
+  \item[\Vkey]
+    describes a \key\ in a \kv\ pair.
+  \item[\Nkey]
+    describes a \key\ for which =\val\ was or should be omitted.
+  \item[\val]
+    is the right-hand side of a \kv\ pair.
+  \item[\kv\ list]
+    is a comma separated list containing \kv\ pairs and \Nkey{}s (each possibly
+    with an \expansion\ prefix).
+  \item[\kvarg]
+    an argument that should get a \kv\ list.
+  \item[\expansion\ prefix]
+    an optional prefix in front of \key\ to specify \expansion-rules (see
+    \autoref{sec:expkv:expansion}), that prefix consists of the \expansion-rules
+    followed by a colon immediately followed by a space.
+  \item[\expansion]
+    a list of tokens specifying expansion steps for \key\ and \val.
+  \item[\expansion-rule]
+    a single expansion step in the \expansion-rules.
+  \item[\expansion-rules]
+    synonymous to \expansion.
+  \item[\expnotation]
+    the notation of \expansion-rules in form of the \expansion\ prefix.
+  \item[key-code]
+    the code that is executed for a given \key.
+  \item[key-macro]
+    the internal macro that stores the key-code.
+\end{description}
+
+Though not really terminology but more typographic representation I want to
+highlight a distinction between two different types of code listings in this
+documentation. I use the following looks to show a code example and its results:
+\begin{enverb}[same-line=0.6]
+  \newcommand*\foo{This is an example.}
+  \foo
+\end{enverb}
+And this is how a syntax summary or a syntax example looks like (this is more
+abstract than an example and contains short meta-descriptions of inputs):
+\begin{syntaxexample}
+  \cs[no-index]{function}\marg{syntax}
+\end{syntaxexample}
+Inside such syntax summaries the following rules usually apply (and \meta{arg}
+would be the meta description here):
+\begin{description}[font=\small\ttfamily]
+  \item[\marg{arg}]
+    a mandatory argument is shown in braces
+  \item[\meta{arg}]
+    a mandatory argument that should be a single token is shown without
+    additional parentheses/braces/brackets
+  \item[\oarg{arg}]
+    an optional argument is shown in brackets (and should be input with
+    brackets)
+  \item[\meta{*}]
+    an optional star is shown like this
+\end{description}
+If other types of arguments are displayed the documentation will explain what
+they mean in this particular place.
+
+\addssec{Category Codes}
+Supporting different category codes of a single character code makes the
+programmer's life harder in \TeX, but there are valid reasons to make some
+active, or letter. Because of this the packages in this bundle support different
+category codes for specific syntax relevant characters (unless otherwise
+documented). This doesn't mean that \expkv\ changes any category codes, only
+that parsing is correct \emph{if} they are changed later (the codes listed
+assume standard category codes of \hologo{plainTeX} and \LaTeXe\ apply while
+\expkv\ is loaded). The supported tokens are:
+\begin{description}
+  \item[=] \tkn{=}{12} and \tkn{=}{13}
+  \item[,] \tkn{,}{12} and \tkn{,}{13}
+  \item[:] (for the \expnotation) \tkn{:}{11}, \tkn{:}{12}, and \tkn{:}{13}
+  \item[*] (for starred macros) \tkn{*}{3}, \tkn{*}{4}, \tkn{*}{6}, \tkn{*}{7},
+    \tkn{*}{8}, \tkn{*}{11}, \tkn{*}{12}, and \tkn{*}{13}
+  \item[{[}] (for |\ekvoptarg|) only \tkn{[}{12}
+  \item[{]}] (for |\ekvoptarg|) only \tkn{]}{12}
+\end{description}
+
+\addssec{Bugs}
+Just like \pkg{keyval}, \expkv\ is bug free. But if you find \pmso{bugs}hidden
+features\footnote{Thanks, David!} you can tell me about them either via mail
+(see the first page) or directly on GitLab if you have an account there:
+\url{https://gitlab.com/islandoftex/texmf/expkv-bundle}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/introduction.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-cs.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-cs.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-cs.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,937 @@
+\genericekv\expkvc{-cs}
+
+\expkvc\ aids in creating fully expandable macros that take a \kv\ argument. It
+implements somewhat efficient solutions to expandable \kv\ parsing without the
+user having to worry too much about the details.
+
+The package supports two main approaches for this. The first is splitting the
+keys up into individual arguments, the second preparses the \kv\ list into a
+single argument in which accessing the value of individual keys is fast. The
+behaviour of the second type is similar to a hash table, so we call that variant
+|Hash|, the first type is called |Split|. Both these variants support a number
+of so called \emph{primary keys} (a primary key matches an argument, roughly
+speaking).
+
+In addition to these methods there is a structured way to define additional keys
+which might build upon the primary keys but not directly relate to an argument.
+These keys are called \emph{secondary keys}. Primary and secondary keys belong
+to a specific macro (the macro name serves as the \emph{set}).
+
+A word of advice you should consider: Macros defined with \expkvc\ are simple to
+create, and there might be good use cases for them (for instance since they
+don't work by assignments but only by argument forwarding logic they have no
+issues with implicit or explicit groups whatsoever). But they don't scale as
+well as established \kv\ interfaces (think of the idiomatic key definitions with
+\pkg{keyval}, or \pkg{l3keys}, or \expkv\ with or without \expkvd), and they are
+slower than idiomatic key definitions in packages with fast \kv\ parsing.
+
+
+\subsection{Defining Macros and Primary Keys}
+
+All macros defined with \expkvc\ have to be previously undefined (or have the
+|\meaning| of |\relax|). There is no way to automatically undefine keys once
+they are set up -- so to make sure there are no conflicts only new definitions
+are allowed. The \emph{set} name (as used by \cs[no-index]{ekvset}) will be
+\cs[no-index]{string}\cs[no-index]{\meta{macro}}.
+
+
+\subsubsection{Primary Keys\label{sec:c:primary}}
+
+The notion of primary keys needs a bit of explanation, or better, the input
+syntax for the argument \meta{primary keys} in the following explanations. The
+\meta{primary keys} argument should be a \kv\ list in which each \key\ will be
+one primary key and \val\ the initial value of said \key\ (and that value is
+mandatory, even if you leave it blank that's fine, but you have to explicitly
+state it). By default all keys are defined short, but you can define |\long|
+keys by prefixing \key\ with |long| (\emph{e.g.},
+|long name=Jonathan P. Spratte| to define a |\long| key called |name|). Due to
+some internal implementations it's worth noting that |\long| keys are a
+microscopic grain faster. The \meta{cs} will only be defined |\long| if at least
+one of the keys was |\long|. For obvious reasons there is no interface in place
+to define something as |\protected|.
+
+To allow keys to start with the word |long| even if you don't want them to be
+|\long| you can also prefix them with |short|. The first found prefix of the two
+will stop the parsing for prefixes and what remains becomes the \key.
+
+These rules culminate in the following:
+
+\begin{enverb}[no-tcb]
+  \ekvcSplit\foo
+    {
+       long short = abc\par
+      ,short long = def
+    }
+    {#1#2}
+\end{enverb}
+will define a macro |\foo| that knows two primary keys, |short| which is defined
+|\long| (so will accept explicit |\par| tokens inside its value at use time),
+and |long| which doesn't accept explicit |\par| tokens (leading to a low level
+\TeX\ error). The description of |\ekvcSplit| follows shortly.
+
+There is one exception to the rule that each \key\ in \meta{primary keys} needs
+to get a value: If you include a key named |...| without a value this will be a
+primary key in which every unknown key will be collected -- and \meta{cs} will
+be defined |\long|. The unknown keys will be stored in a way that \emph{most}
+\kv\ parsers will parse them correctly (but this is no general guarantee, for
+instance \pkg{pgfkeys} can accidentally strip multiple sets of braces at the
+wrong moment). See some examples in \autoref{sec:c:unknown}.
+
+At the moment \expkvc\ doesn't require any internal keys, but I can't foresee
+whether this will be the case in the future as well, as it might turn out that
+some features I deem useful can't be implemented without such internal keys.
+Because of this, please don't use key names starting with "EKVC|" as that
+should be the private name space.
+
+
+\subsubsection{Split\label{sec:c:split}}
+
+The split variants will provide the key values as separate arguments. This
+limits the number of keys for which this is truly useful.
+
+\begin{function}{\ekvcSplit}
+  \begin{syntax}
+    \cs{ekvcSplit}\meta{cs}\marg{primary keys}\marg{definition}
+  \end{syntax}
+  This defines \meta{cs} to be a macro taking one mandatory argument which
+  should contain a \kv\ list. The \meta{primary keys} will be defined for this
+  macro (see \autoref{sec:c:primary}). The \meta{definition} is the code that
+  will be executed. You can access the \val\ of a \key\ by using a macro
+  parameter from |#1| to |#9|. The order of the macro parameters will be the
+  order provided in the \meta{primary keys} list (so |#1| is the \val\ of the
+  \key\ defined first). With \cs{ekvcSplit} you can define macros using at most
+  nine primary keys.
+\end{function}
+\begin{example}{Simple macro with \cs[no-index]{ekvcSplit}}
+  The following defines a macro |\foo| that takes the keys |a| and |b|
+  and outputs their values in a textual form:
+  \begin{enverb}
+    \ekvcSplit\foo{a=a,b=b}{a is #1.\par b is #2.\par}
+    \foo{}
+    \foo{b=e}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvcSplitAndForward}
+  \begin{syntax}
+    \cs{ekvcSplitAndForward}\meta{cs}\marg{after}\marg{primary keys}
+  \end{syntax}
+  This defines \meta{cs} to be a macro taking one mandatory argument which
+  should contain a \kv\ list. You can use as many primary keys as you want with
+  this. The primary keys will be forwarded to \meta{after} as braced arguments
+  (as many as necessary for your primary keys). The order of the braced
+  arguments will be the order of your primary key definitions. In \meta{after}
+  you can use just a single control sequence, or some arbitrary stuff which will
+  be left in the input stream before your braced values (with one set of braces
+  stripped from \meta{after}), so both of the following would be fine:
+  \begin{enverb}[no-tcb]
+    \ekvcSplitAndForward\foo\foo at aux{keyA = A, keyB = B}
+    \ekvcSplitAndForward\foo{\foo at aux{more args}}{keyA = A, keyB = B}
+  \end{enverb}
+\end{function}
+\noindent
+In the first case |\foo at aux| should take at least two arguments (|keyA| and
+|keyB|), in the second case at least three (|more args|, |keyA|, and |keyB|).
+
+\begin{function}{\ekvcSplitAndUse}
+  \begin{syntax}
+    \cs{ekvcSplitAndUse}\meta{cs}\marg{primary keys}
+  \end{syntax}
+  This will roughly do the same as \cs{ekvcSplitAndForward}, but instead of
+  specifying what will be used after splitting the keys, \meta{cs} will use what
+  follows the \kv\ list. So its syntax will be
+\end{function}
+\begin{quote}
+  \ttfamily
+  \meta{cs}\kvarg\marg{after}
+\end{quote}
+and the code in |after| should expect at least as many arguments as the number
+of keys defined for \meta{cs}.
+
+
+\subsubsection{Hash\label{sec:c:hash}}
+
+The hash variants will provide the key values as a single argument in which you
+can access specific values using a special macro. The implementation might be
+more convenient and scale better, \emph{but} it is slower (for a rudimentary
+macro with a single key benchmarking was almost 1.7~times slower, the root of
+which being the key access with \cs{ekvcValue}, not the parsing, and for a key
+access using \cs{ekvcValueFast} it was still about 1.2~times slower). Still to
+be future proof, considering the hash variants is a good idea, and to get best
+performance but less maintainable code you can resort to the split approach.
+
+\begin{function}{\ekvcHash}
+  \begin{syntax}
+    \cs{ekvcHash}\meta{cs}\marg{primary keys}\marg{definition}
+  \end{syntax}
+  This defines \meta{cs} to be a macro taking one mandatory argument which
+  should contain a \kv\ list. You can use as many primary keys as you want. The
+  primary keys will be forwarded as a single argument containing every key to
+  the underlying macro. The underlying macro is defined as \meta{definition}, in
+  which you can access the \val\ of a \key\ by using
+  \cs{ekvcValue}\marg{key}|{#1}| (or similar).
+\end{function}
+\begin{example}{Simple macro with \cs[no-index]{ekvcHash}}
+  This defines an equivalent macro to the |\foo| defined with \cs{ekvcSplit}
+  earlier:
+  \begin{enverb}
+    \ekvcHash\foo{a=a,b=b}{a is \ekvcValue{a}{#1}.\par
+                           b is \ekvcValue{b}{#1}.\par}
+    \foo{}
+    \foo{b=e}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvcHashAndForward}
+  \begin{syntax}
+    \cs{ekvcHashAndForward}\meta{cs}\marg{after}\marg{primary keys}
+  \end{syntax}
+  This defines \meta{cs} to be a macro taking one mandatory argument which
+  should contain a \kv\ list. You can use as many primary keys as you want. The
+  primary keys will be forwarded as a single argument containing every key to
+  \meta{after}. You can use a single macro for \meta{after} or use some
+  arbitrary stuff, which will be left in the input stream before the hashed \kv\
+  list with one set of braces stripped. In the macro called in \meta{after} you
+  can access the \val\ of a \key\ by using \cs{ekvcValue}\marg{key}|{#1}| (or
+  whichever argument the hashed \kv\ list will be in).
+\end{function}
+\begin{example}{Using \cs[no-index]{ekvcHashAndForward}}
+  This defines a macro |\foo| processing two keys, and passing the result to
+  |\foobar|:
+  \begin{enverb}
+    \ekvcHashAndForward\foo\foobar{a=a,b=b}
+    \newcommand*\foobar[1]{a is \ekvcValue{a}{#1}.\par
+                           b is \ekvcValue{b}{#1}.\par}
+    \foo{}
+    \foo{b=e}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvcHashAndUse}
+  \begin{syntax}
+    \cs{ekvcHashAndUse}\meta{cs}\marg{primary keys}
+  \end{syntax}
+  This will roughly do the same as \cs{ekvcHashAndForward}, but instead of
+  specifying what will be used after hashing the keys during the definition,
+  \meta{cs} will use what follows the \kv\ list. So its syntax will be
+  \begin{quote}
+    \ttfamily
+    \meta{cs}\kvarg\marg{after}
+  \end{quote}
+\end{function}
+
+\begin{function}{\ekvcValue}
+  \begin{syntax}
+    \cs{ekvcValue}\marg{key}\marg{key list}
+  \end{syntax}
+  This is a safe way to access your keys in a hash variant. \key\ is the key
+  which's \val\ you want to use out of the \meta{key list}. \meta{key list}
+  should be the key list argument forwarded to your underlying macro by
+  \cs{ekvcHash}, \cs{ekvcHashAndForward}, or \cs{ekvcHashAndUse}. It will be
+  tested whether the hash function to access that \key\ exists, the \key\
+  argument is not empty, and that the \meta{key list} really contains a \val\ of
+  that \key. This macro needs exactly two steps of expansion and if used inside
+  of an |\edef| or |\expanded| context will protect the \val\ from further
+  expanding.
+\end{function}
+
+\begin{function}{\ekvcValueFast}
+  \begin{syntax}
+    \cs{ekvcValueFast}\marg{key}\marg{key list}
+  \end{syntax}
+  This behaves similar to \cs{ekvcValue}, but \emph{without any} safefy tests.
+  As a result this is about 1.4~times faster \emph{but} will throw low level
+  \TeX\ errors eventually if the hash function isn't defined or the \key\ isn't
+  part of the \meta{key list} (\emph{e.g.}, because it was defined as a key for
+  another macro -- all macros share the same hash function per \meta{key} name).
+  Note that this will not only throw low level errors but result in undefined
+  behaviour as well! This macro needs exactly three steps of expansion in the
+  no-error case.
+\end{function}
+
+\begin{function}{\ekvcValueSplit}
+  \begin{syntax}
+    \cs{ekvcValueSplit}\marg{key}\marg{key list}\marg{next}
+  \end{syntax}
+  If you need a specific \key\ from a \meta{key list} more than once, it'll be a
+  good idea to only extract it once and from then on keep it as a separate
+  argument (or if you want to forward this value to another macro). Hence the
+  macro \cs{ekvcValueSplit} will extract one specific \key's \val\ from the list
+  and forward it as an argument to \meta{next}, so the result of this will be
+  \meta{next}\marg{value}. This is roughly as fast as \cs{ekvcValue} and runs
+  the same tests.
+\end{function}
+\begin{example}
+    {Splitting of a key from a hash list using \cs[no-index]{ekvcValueSplit}}
+  The following defines a macro |\foo| which will take three keys. Since the
+  next parsing step will need the value of one of the keys multiple times we
+  split that key off the list (in this example the next step doesn't use the key
+  multiple times for simplicity though), and the entire list is forwarded as the
+  second argument:
+  \begin{enverb}
+    \ekvcHash\foo{a=a,b=b,c=c}
+      {\ekvcValueSplit{a}{#1}\foobar{#1}}
+    \newcommand*\foobar[2]{a is #1.\par
+                           b is \ekvcValue{b}{#2}.\par
+                           c is \ekvcValue{c}{#2}.\par}
+    \foo{}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvcValueSplitFast}
+  \begin{syntax}
+    \cs{ekvcValueSplitFast}\marg{key}\marg{key list}\marg{next}
+  \end{syntax}
+  This behaves just like \cs{ekvcValueSplit}, but it won't run the safety tests,
+  hence it is faster but more error prone, just like the relation between
+  \cs{ekvcValue} and \cs{ekvcValueFast}.
+\end{function}
+
+
+\subsection{Secondary Keys\label{sec:c:secondary}}
+
+To lift some limitations of each primary key matching one argument or hash
+entry, you can define secondary keys. Those have to be defined for each macro
+individually but it doesn't matter whether that macro was set up as a split or
+hash variant.
+
+Secondary keys can have a \prefix\ (|long|), and must have a \type\
+(like |meta|). Some \types\ might require some \prefix\ while other
+\types\ might forbid the usage of a specific \prefix.
+
+Please keep in mind that key names shouldn't start with "EKVC|".
+
+\begin{function}{\ekvcSecondaryKeys}
+  \begin{syntax}
+    \cs{ekvcSecondaryKeys}\meta{cs}\kvarg
+  \end{syntax}
+  This is the front facing macro to define secondary keys. For the macro
+  \meta{cs} define \key\ to have definition \val. The general syntax for \key\
+  should be
+  \begin{quote}\ttfamily
+    \meta{prefix} \meta{name}
+  \end{quote}
+  Where \meta{prefix} is a space separated list of optional \prefixes\
+  followed by one \type. The syntax of \meta{value} is dependent on the
+  used \type.
+\end{function}
+
+
+\subsubsection{\textit{Prefixes}}
+
+Currently there is only one \prefix\ available, which is
+\begin{function}[module=expkv-cs prefix]{long}
+  The following key will be defined |\long|.
+\end{function}
+
+
+\subsubsection{\textit{Types}\label{sec:c:secondarytypes}}
+
+Compared to \expkvd\ you might notice that the \types\ here are much fewer.
+Unfortunately the expansion only concept doesn't allow for great variety in the
+common key \types.
+
+The syntax examples of the \types\ will show which \prefix\ will be
+automatically used by printing those black (\texttt{\enfprefix{long}}), which
+will be available in grey (\texttt{\allprefix{long}}), and which will be
+disallowed in red (\texttt{\notprefix{long}}). This will be put flush right next
+to the syntax line.
+
+If a secondary key references another key it doesn't matter whether that other
+key is a primary or secondary key (unless explicitly stated otherwise).
+
+\begin{function}[module=expkv-cs type]{meta}
+  \begin{syntax}
+    meta \key\ = \kvarg \prefixes2
+  \end{syntax}
+  With a |meta| key you can set other keys. Whenever \meta{key} is used the keys
+  in the \kv\ list will be set to the values given there. You can use the \val\
+  given to \key\ by using |#1| in the \kv\ list.
+\end{function}
+
+\begin{function}[module=expkv-cs type]{nmeta}
+  \begin{syntax}
+    nmeta \key\ = \kvarg \prefixes3
+  \end{syntax}
+  An |nmeta| key is like a |meta| key, but it doesn't take a value at use time,
+  so the \kv\ list is static.
+\end{function}
+
+\begin{function}[module=expkv-cs type]{alias}
+  \begin{syntax}
+    alias \meta{key} = \marg{key_2} \prefixes3
+  \end{syntax}
+  This assigns the definition of \meta{key_2} to \key. As a result \key\ is an
+  alias for \meta{key_2} behaving just the same. Both the \Vkey\ and the \Nkey\
+  will be copied if they are defined when |alias| is used. Of course,
+  \meta{key_2} has to be defined as at least one of \Nkey\ or \Vkey.
+\end{function}
+
+\begin{function}[module=expkv-cs type]{default}
+  \begin{syntax}
+    default \key\ = \marg{default} \prefixes3
+  \end{syntax}
+  If \key\ is defined as a \Vkey\ you can define a \Nkey\ version with this. The
+  \Nkey\ will behave as if \key\ was given \meta{default} as its \val. Note that
+  this doesn't change the initial values of primary keys set at definition time
+  (see \cs{ekvcChange} in \autoref{sec:c:change} for this). If \key\ isn't yet
+  defined this results in an error.
+\end{function}
+
+\begin{function}[module=expkv-cs type]{enum}
+  \begin{syntax}
+    enum \key\ = \marg{key_2}\kvarg \prefixes2
+  \end{syntax}
+  This defines \key\ to only accept the values given in the list of the second
+  argument of its definition. It forwards the position of \val\ in that list to
+  \meta{key_2} (zero-based). The \meta{key_2} has to already be defined by the
+  time an |enum| key is set up. Each \val\ in the list (and at use time) is
+  |\detokenize|d, so no expansion takes place here.
+
+  If you use |enum| twice on the same \key\ the new values will again start at
+  zero (so it is possible to define multiple values with the same outcome),
+  however since you can't skip values you'll have to use the same as in the
+  first call for values with just a single variant. There is no interface to
+  delete existing values.
+\end{function}
+\begin{example}{Enumerating choices with the \texttt{enum} \type}
+  First a small example that might give you an idea of what the description
+  above could mean:
+  \begin{enverb}
+    \ekvcSplit\foo{k-internal=-1}{#1}
+    \ekvcSecondaryKeys\foo
+      {enum k = {k-internal}{a,b,c}}
+    \foo{}\foo{k=a}\foo{k=b}\foo{k=c}
+  \end{enverb}
+\end{example}
+\begin{example}{A slightly more complicated usage of the \texttt{enum} \type}
+  We can define a choice setup that might do different things based on the
+  choice encountered, and the numeric value is easy to parse using
+  \cs[no-index]{ifcase}:
+  \begin{enverb}
+    \ekvcSplit\foo{k-internal=-1}
+      {%
+        \ifcase#1
+          is\or
+          This\or
+          easy%
+        \else
+          .%
+        \fi
+      }
+    \ekvcSecondaryKeys\foo
+      {enum k = {k-internal}{a,b,c}}
+    \foo{k=b} \foo{k=a} \foo{k=c}\foo{}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-cs type]{choice}
+  \begin{syntax}
+    choice \key\ = \marg{key_2}\kvarg \prefixes2
+  \end{syntax}
+  This is pretty similar to an |enum|, but unlike with |enum| the forwarded
+  \val\ will not be numeric, instead the \val\ as given during the definition
+  time will be forwarded. This means that while the user input has to match in a
+  |\detokenize|d form, the \val\ might still expand further during your macro's
+  expansion (if what you provided as a choice is expandable).
+\end{function}
+\begin{example}{Filtering possible values with the \texttt{choice} \type}
+  We could use this to filter out the possible vertical placements of a \LaTeXe\
+  |tabular|:
+  \begin{enverb}
+    \ekvcSplit\foo{v-internal=c,a=t,b=c,c=b}
+      {%
+        \begin{tabular}[#1]{@{} c @{:} c @{}}
+          a & #2\\
+          b & #3\\
+          c & #4\\
+        \end{tabular}%
+      }
+    \ekvcSecondaryKeys\foo
+      {choice v = {v-internal}{t,c,b}}
+    \foo{} \foo{v=t} \foo{v=c} \foo{v=b}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-cs type]{aggregate,e-aggregate}
+  \begin{syntax}
+    aggregate \key\ = \marg{primary}\marg{definition} \prefixes3
+  \end{syntax}
+  While other key \types\ replace the current value of the associated
+  primary key, with |aggregate| you can create keys that append or prepend (or
+  whatever you like) the new value to the current one. Your definition of an
+  |aggregate| key must be exactly two \TeX\ arguments, where \meta{primary}
+  should be the name of a primary key, and \meta{definition} the way you want to
+  store the current and the new value. Inside \meta{definition} you can use |#1|
+  for the current, and |#2| for the new value. The \meta{definition} will not
+  expand any further during the entire parsing for |aggregate|, whereas in
+  |e-aggregate| everything that ends up in \meta{definition} (so whatever you
+  provide including the values in |#1| and |#2|) will be fully expanded (using
+  the |\expanded| primitive), so use |\noexpand| and |\unexpanded| to protect
+  what shouldn't be expanded.
+  The resulting \meta{key} will inherit being either |short| or |long| from the
+  \meta{primary} key.
+\end{function}
+\begin{example}{Building a list with the \texttt{aggregate} \type}
+  The following defines an internal key (|k-internal|), which is used to build a
+  comma separated list from each call of the user facing key (|k|):
+  \begin{enverb}
+    \ekvcSplit\foo
+      {k-internal=0,color=red}
+      {\textcolor{#2}{#1}}
+    \ekvcSecondaryKeys\foo
+      {aggregate k = {k-internal}{#1,#2}}
+    \foo{}\par
+    \foo{k=1,k=2,k=3,k=4}
+  \end{enverb}
+\end{example}
+\begin{example}{Building a convoluted list with the \texttt{aggregate} \type}
+  But also more strange stuff could end there, like macros or using the same
+  value multiple times:
+  \begin{enverb}[no-tcb]
+    \ekvcSecondaryKeys\foo
+      {aggregate k = {k-internal}{\old{#1}\new{#2\old{#1}}}}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-cs type]{flag-bool}
+  \begin{syntax}
+    flag-bool \key\ = \meta{cs} \prefixes3
+  \end{syntax}
+  This is a secondary \type\ that doesn't involve any of the primary or other
+  secondary keys. This defines \key\ to take a value, which should be either
+  |true| or |false|, and set the flag called \meta{cs} accordingly as a boolean.
+  If \meta{cs} isn't defined yet it will be initialised as a flag. Note that the
+  flag will not be set to a specific state automatically so a flag set in one
+  macro might affect every other macro in the current scope. Please also read
+  \autoref{sec:c:flags}.
+\end{function}
+\begin{example}{Using a Boolean flag with the \texttt{flag-bool} \type}
+  Provide a key |bold| to turn the output of our macro bold if the associated
+  flag is |true|.
+  \begin{enverb}
+    \ekvcSplit\foo{a=a,b=b}
+      {%
+        \ekvcFlagIf\fooFlag
+          {\textbf{a is #1 and b is #2}\par}
+          {a is #1 and b is #2\par}%
+      }
+    \ekvcSecondaryKeys\foo{flag-bool bold = \fooFlag}
+    \foo{}\foo{bold=true}\foo{}\foo{bold=false}\foo{}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-cs type]{flag-true,flag-false}
+  \begin{syntax}
+    flag-true \key\ = \meta{cs} \prefixes3
+  \end{syntax}
+  This is similar to |flag-bool|, but the \meta{key} will be a \Nkey\ and if
+  used will set the flag to either |true| or |false|. If \meta{cs} isn't defined
+  yet it will be initialised as a flag. Note that the flag will not be set to a
+  specific state automatically. Please also read \autoref{sec:c:flags}.
+\end{function}
+
+\begin{function}[module=expkv-cs type]{flag-raise}
+  \begin{syntax}
+    flag-raise \key\ = \meta{cs} \prefixes3
+  \end{syntax}
+  This defines \key\ to be a \Nkey\ that will raise the flag called \meta{cs} on
+  usage. If \meta{cs} isn't defined yet it will be initialised as a flag. Note
+  that the flag will not be set to a specific state automatically. Please also
+  read \autoref{sec:c:flags}.
+\end{function}
+
+
+\subsection{Changing the Initial Values\label{sec:c:change}}
+
+\begin{function}{\ekvcChange}
+  \begin{syntax}
+    \cs{ekvcChange}\meta{cs}\kvarg
+  \end{syntax}
+  This processes the \kv\ list for the macro \meta{cs} to set new defaults for
+  it (meaning the initial values used if you don't provide anything at use time,
+  not those specified with the |default| \type). \meta{cs} should be defined
+  with \expkvc\ (but it doesn't matter if it's a split or hash variant). Inside
+  the \kv\ list both primary and secondary keys can be used. If \meta{cs} was
+  defined |\long| earlier it will still be |\long|, every other \TeX\ prefix
+  will be stripped (but \expkvc\ doesn't support them anywhere else so that
+  should be fine). The resulting new defaults will be stored inside the
+  \meta{cs} locally (just as the original initial values were). If there was an
+  unknown key forwarding added to \meta{cs} (see \autoref{sec:c:unknown}) any
+  unknown key will be stored inside the list of unknown keys as well.
+  \cs{ekvcChange} is not expandable!
+\end{function}
+\begin{example}
+    {Changing the values for future calls using \cs[no-index]{ekvcChange}}
+  With \cs{ekvcChange} we can now do the following:
+  \begin{enverb}
+    \ekvcSplit\foo{a=a,b=b}{a is #1.\par b is #2.\par}
+    \begingroup
+      \ekvcChange\foo{b=B}
+      \foo{}
+      \ekvcSecondaryKeys\foo{meta c={a={#1},b={#1}}}
+      \ekvcChange\foo{c=c}
+      \foo{}
+    \endgroup
+    \foo{}
+  \end{enverb}
+\end{example}
+\begin{example}{A typical setup macro for \expkvc\ macros}
+  As a result with this the typical setup macro could be implemented:
+  \begin{enverb}[no-tcb]
+    \ekvcHashAndUse\fooKV{keyA=a,keyB=b}
+    \def\fooA#1{\fooKV{#1}\fooAinternal}
+    \def\fooB#1{\fooKV{#1}\fooBinternal}
+    \protected\def\foosetup{\ekvcChange\fooKV}
+  \end{enverb}
+  Of course the usage is limited to a single macro |\fooKV|, hence this might
+  not be as powerful as similar macros used with other \kv\ interfaces. But at
+  least a few similar macros could be grouped using the same key parsing macro
+  internally like |\fooA| and |\fooB| do in this example.
+\end{example}
+
+
+\subsection{Handling Unknown Keys\label{sec:c:unknown}}
+
+If your macro should handle unknown keys without directly throwing an error you
+can use the special |...| marker in the \meta{primary keys} list. Since those
+keys will be processed once by \expkv\ they will be forwarded normalised: The
+\key\ and the \val\ will be forwarded with one set of surrounding spaces and
+braces, so a \kv\ pair will result in \texttt{\vissp{ \marg{key} = \marg{val} }}
+and a \Nkey\ is forwarded as \texttt{\vissp{ \marg{key} }} (this way most other
+\kv\ implementations should parse the correct input).
+
+The exact behaviour differs slightly between the two variants (as all primary
+keys do). The behaviour inside the split variants will be similar to normal
+primary keys, the $n$-th argument (corresponding to the position of |...| inside
+the primary keys list) will contain any unknown key encountered while parsing
+the argument. And inside the split variant you can use a primary key named |...|
+at the same time (since only the position in the list determines the argument,
+not the name).
+\begin{example}{Using unknown key handlers to wrap another \kv\ enabled macro}
+  The following will forward any unknown key to |\includegraphics| to control
+  the appearance while processing its own keys:
+  \begin{enverb}[same-line=0.6]
+    \newcommand*\foo{\ekvoptarg\fooKV{}}
+    \ekvcSplitAndForward\fooKV\fooOUT
+      {
+         a=a
+        ,...
+        ,b=b
+        ,...={}
+      }
+    \newcommand\fooOUT[5]
+      {%
+        a is #1 and b is #3.\par
+        \includegraphics[{#2}]{#5}\par
+        \texttt{...} is #4.\par
+      }
+    \foo[width=.5\linewidth, b=c,
+         ...={a stupid key name, but works}]
+        {example-image-duck}
+  \end{enverb}
+\end{example}
+
+Inside the hash variants the unknown keys list will be put inside the hash named
+|...| (we have to use some name, and this one seems reasonable). As a
+consequence a primary key named |...| would clash with the unknown key handler.
+If you still used such a key it would remove any unknown key stored there until
+that point and replace the list with its value.
+\begin{example}{Wrapping an existing macro, but with a hash variant}
+  The following is more or less equivalent to the above example, but with the
+  hash variant, and it will not contain the primary |...| key. We have to make
+  sure that |\includegraphics| sees the \kv\ list, so need to expand
+  |\ekvcValue{...}{#1}| before |\includegraphics| parses it.
+  \begin{enverb}[same-line=0.76]
+    \newcommand*\foo{\ekvoptarg\fooKV{}}
+    \ekvcHashAndForward\fooKV\fooOUT
+      {a=a, b=b, ...}
+    \newcommand\fooOUT[2]
+      {%
+        a is \ekvcValue{a}{#1} and
+        b is \ekvcValue{b}{#1}.\par
+        \ekvcValueSplit{...}{#1}{\includegraphics[}]%
+          {#2}\par
+      }
+    \foo[width=\linewidth, b=c]
+        {example-image-duck-portrait}
+  \end{enverb}
+\end{example}
+
+
+\subsection{Flags\label{sec:c:flags}}
+
+The idea of flags is taken from \pkg{expl3}. They provide a way to store
+numerical information expandably, however only incrementing and accessing works
+expandably, decrementing is unexpandable. A flag has a height, which is a
+numerical value, and which can be raised by 1. Flags come at a high
+computational cost (accessing them is slow and they require more memory than
+normal \TeX\ data types like registers, both issues getting linearly worse with
+the height), so don't use them if not necessary.
+
+The state of flags is always changed locally to the current group, but not to
+the current macro, so if you're using one of the \types\ involving flags
+bear in mind that they can affect other macros using the same flags at the
+current scope!
+
+\expkvc\ provides some macros to access, alter, and use flags. Flags of \expkvc\
+don't share a name space with the flags of \pkg{expl3}.
+
+\begin{function}{\ekvcFlagNew}
+  \begin{syntax}
+    \cs{ekvcFlagNew}\meta{flag}
+  \end{syntax}
+  This initialises the macro \meta{flag} as a new flag. It isn't checked whether
+  the macro \meta{flag} is currently undefined. A \meta{flag} will expand to the
+  flag's current height with a trailing space (so you can use it directly with
+  \cs[no-index]{ifnum} for example and it will terminate the number scanning on
+  its own).
+
+  All other macros dealing with flags take as a parameter a macro defined as a
+  \meta{flag} with \cs{ekvcFlagNew}.
+\end{function}
+
+\begin{function}{\ekvcFlagHeight}
+  \begin{syntax}
+    \cs{ekvcFlagHeight}\meta{flag}
+  \end{syntax}
+  This expands to the current height of \meta{flag} in a single step of
+  expansion (without a trailing space).
+\end{function}
+
+\begin{function}{\ekvcFlagRaise}
+  \begin{syntax}
+    \cs{ekvcFlagRaise}\meta{flag}
+  \end{syntax}
+  This expandably raises the height of \meta{flag} by 1.
+\end{function}
+
+\begin{function}{\ekvcFlagSetTrue,\ekvcFlagSetFalse}
+  \begin{syntax}
+    \cs{ekvcFlagSetTrue}\meta{flag}
+  \end{syntax}
+  By interpreting an even value as false and an odd value as true we can use a
+  flag as a boolean. This expandably sets \meta{flag} to true or false,
+  respectively, by raising it if necessary.
+\end{function}
+
+\begin{function}{\ekvcFlagIf}
+  \begin{syntax}
+    \cs{ekvcFlagIf}\meta{flag}\marg{true}\marg{false}
+  \end{syntax}
+  This interprets a \meta{flag} as a boolean and expands to either \meta{true}
+  or \meta{false}.
+\end{function}
+
+\begin{function}{\ekvcFlagIfRaised}
+  \begin{syntax}
+    \cs{ekvcFlagIfRaised}\meta{flag}\marg{true}\marg{false}
+  \end{syntax}
+  This tests whether the \meta{flag} is raised, meaning it has a height greater
+  than zero, and if so expands to \meta{true} else to \meta{false}.
+\end{function}
+
+\begin{function}{\ekvcFlagReset,\ekvcFlagResetGlobal}
+  \begin{syntax}
+    \cs{ekvcFlagReset}\meta{flag}
+  \end{syntax}
+  This resets a flag (so restores its height to 0). This operation is \emph{not}
+  expandable and done locally for \cs{ekvcFlagReset} and globally for
+  \cs{ekvcFlagResetGlobal}. If you really intend to use flags you can reset them
+  every now and then to keep the performance hit low.
+\end{function}
+
+\begin{function}{\ekvcFlagGetHeight}
+  \begin{syntax}
+    \cs{ekvcFlagGetHeight}\meta{flag}\marg{next}
+  \end{syntax}
+  This retrieves the current height of the \meta{flag} and provides it as a
+  braced argument to \meta{next}, leaving \meta{next}\marg{height} in the input
+  stream.
+\end{function}
+
+\begin{function}{\ekvcFlagGetHeights}
+  \begin{syntax}
+    \cs{ekvcFlagGetHeights}\marg{flag-list}\marg{next}
+  \end{syntax}
+  This retrieves the current height of each \meta{flag} in the \meta{flag-list}
+  and provides them as a single argument to \meta{next}. Inside that argument
+  each height is enclosed in a set of braces individually. The \meta{flag-list}
+  is just a single argument containing the \meta{flag}s. So a usage like
+  |\ekvcFlagGetHeights{\myflagA\myflagB}{\stuff}| will expand to
+  |\stuff{|\marg{height-A}\marg{height-B}|}|.
+\end{function}
+
+
+\subsection{Further Examples}
+
+\begin{example}{Defining an expandable \kv\ macro with an optional argument}
+  Using \cs[no-index]{NewExpandableDocumentCommand} or \expkv's \cs{ekvoptarg}
+  or \cs{ekvoptargTF} and forwarding arguments one can easily define \kv\ macros
+  with actual optional and mandatory arguments as well. A small nonsense
+  example:
+  \begin{enverb}[below,inter=resulting in]
+    \makeatletter
+    \newcommand*\nonsense{\ekvoptarg\nonsense at a{}}
+    \ekvcHashAndForward\nonsense at a\nonsense at b
+      {
+        keyA = A,
+        keyB = B,
+        keyC = c,
+        keyD = d,
+      }
+    \newcommand*\nonsense at b[2]
+      {%
+        \begin{tabular}{lll|}
+          key & A & \ekvcValue{keyA}{#1} \\
+              & B & \ekvcValue{keyB}{#1} \\
+              & C & \ekvcValue{keyC}{#1} \\
+              & D & \ekvcValue{keyD}{#1} \\
+          \multicolumn{2}{l}{mandatory} & #2 \\
+        \end{tabular}%
+      }
+    \makeatother
+    \nonsense{} % do nonsense
+    \nonsense[keyA=hihi]{haha}
+    \nonsense[keyA=hihi, keyB=A]{hehe}
+    \nonsense[keyC=huhu, keyA=hihi, keyB=A]{haha}
+  \end{enverb}
+\end{example}
+
+\begin{example}{The \cs[no-index]{sine} example revisited}
+  In \autoref{sec:expkv:sneak} I presented an expandable macro to calculate the
+  sine of some user input with a few keys, and there I hinted to \expkvc, so
+  here's the same function implemented with |\ekvcSplitAndForward|. There is a
+  small difference here, we need to use an internal key to store whether degrees
+  or radians will be used, but we don't need to use an internal key to collect
+  the values of our individual keys in the correct order.
+  \begin{enverb}
+    \makeatletter
+    \newcommand\sine{\ekvoptarg\sine at kv{}}
+    \ekvcSplitAndForward\sine at kv\sine at do
+      {
+         f        = sin
+        ,internal = d
+        ,round    = 3
+      }
+    \ekvcSecondaryKeys\sine at kv
+      {
+         nmeta degree = internal=d
+        ,nmeta radian = internal={}
+      }
+    \newcommand*\sine at do[4]{\fpeval{round(#1#2(#4),#3)}}
+    \makeatother
+    \sine{60}\par
+    \sine[round=10]{60}\par
+    \sine[f=cos,radian]{pi}\par
+    \edef\myval{\sine[f=tan]{1}}\texttt{\meaning\myval}
+  \end{enverb}
+\end{example}
+
+
+\subsection{Freedom for Keys!}
+
+If this had been the \TeX{}book this subsection would have had a double bend
+sign. Not because it is overly complicated, but because it shows things which
+could break \expkvc's expandability and its alignment safety. This is for
+experienced users wanting to get the most flexibility and knowing what they are
+doing.
+
+In case you're wondering, it is possible to define other keys than the primaries
+and the secondary key \types\ listed in \autoref{sec:c:secondary} for a
+macro defined with \expkvc\ by using the low-level interface of \expkv\ or even
+the interface provided by \expkvd. The set name used for \expkvc's keys is the
+macro name, including the leading backslash, or more precisely the result of
+|\string|\meta{cs} is used. This can be exploited to define additional keys with
+arbitrary code. Consider the following \emph{bad} example:
+\begin{enverb}[no-tcb]
+  \ekvcSplit\foo{a=A,b=B}{a is #1.\par b is #2.\par}
+  \protected\ekvdef{\string\foo}{c}{\def\fooC{#1}}
+\end{enverb}
+This would define a key named |c| that will store its \val\ inside a macro. The
+issue with this is that this can't be done expandably. As a result, the macro
+|\foo| isn't always expandable any more (not that bad if this was never
+required; killjoy if it was) and as soon as the key |c| is used it is also no
+longer alignment safe\footnote{This means that the \kv\ list can't contain
+  alignment markers that are not inside an additional set of braces if used
+  inside a \TeX\ alignment}
+(might be bad depending on the usage).
+
+So why do I show you this? Because we could as well do something useful like
+creating a key that pre-parses the input and after that passes the parsed value
+on. This parsing would have to be completely expandable though (and we could
+perhaps also implement this using the |e-aggregate| \type). For the
+pass-on part we can use the following function:
+
+\begin{function}{\ekvcPass}
+  \begin{syntax}
+    \cs{ekvcPass}\meta{cs}\marg{key}\marg{value}
+  \end{syntax}
+  This passes \val\ on to \key\ for the \expkvc-macro \meta{cs}. It should be
+  used inside the key parsing of a macro defined with \expkvc, else this most
+  likely results in a low level \TeX\ error. You can't forward anything to the
+  special unknown key handler |...| as that is no defined key.
+\end{function}
+\begin{example}
+    {Forwarding pre-parsed keys to an \expkvc\ key with \cs[no-index]{ekvcPass}}
+  With this we could for example split the value of a key at a hyphen and pass
+  the parts to different keys:
+  \begin{enverb}
+    \ekvcSplit\foo{a=A,b=B}{a is #1.\par b is #2.\par}
+    \ekvdef{\string\foo}{c}{\fooSplit#1\par}
+    \def\fooSplit#1-#2\par
+      {\ekvcPass\foo{a}{#1}\ekvcPass\foo{b}{#2}}
+    \foo{}
+    \foo{c=1-2}
+  \end{enverb}
+\end{example}
+
+Additionally, there is a more general version of the |aggregate| secondary key
+type, namely the |process| key type:
+
+\begin{function}[module=expkv-cs type]{process}
+  \begin{syntax}
+    process \key\ = \marg{primary}\marg{definition} \prefixes2
+  \end{syntax}
+  This will grab the current value of a \meta{primary} key as |#1| (without
+  changing the current value) and the new value as |#2| and leave all the
+  processing to \meta{definition}. You should use \cs{ekvcPass} to forward the
+  values afterwards. Unlike |aggregate| you can specify whether the \meta{key}
+  should be long or not, this isn't inherited from the \meta{primary} key. Keep
+  in mind that you could easily break things here if your code does not work by
+  expansion.
+\end{function}
+\begin{example}{Filtering out values with the \texttt{process} \type} 
+  We could define a key that only accepts values greater than the current value
+  with this:
+  \begin{enverb}
+    \ekvcSplit\foo{internal=5}{a is #1.\par}
+    \ekvcSecondaryKeys\foo
+      {
+        process a={internal}
+          {\ifnum#1<#2 \ekvcPass\foo{internal}{#2}\fi}
+      }
+    \foo{a=1}
+    \foo{a=5}
+    \foo{a=9}
+  \end{enverb}
+\end{example}
+\begin{example}{Filtering out values with the \texttt{e-aggregate} \type}
+  The same is possible with an |e-aggregate| key as well though:
+  \begin{enverb}[no-tcb]
+    \ekvcSplit\foo{internal=5}{a is #1.\par}
+    \ekvcSecondaryKeys\foo
+      {
+        e-aggregate a={internal}
+          {\ifnum#1<#2 \unexpanded{#2}\else\unexpanded{#1}\fi}
+      }
+  \end{enverb}
+\end{example}
+
+\subsection{Useless Macros}
+
+These macros are most likely of little to no interest to users.
+
+\begin{function}{\ekvcDate,\ekvcVersion}
+  These two macros store the version and date of the package/generic code.
+\end{function}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-cs.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-def.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-def.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-def.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,727 @@
+\genericekv\expkvd{-def}
+
+Since the trend for the last couple of years goes to defining keys for a \kv\
+interface using a \kv\ interface, I thought that maybe providing such an
+interface for \expkv\ will make it more attractive for actual use. But at the
+same time I didn't want to broaden \expkv's initial scope. So here is \expkvd,
+go define \kv\ interfaces with \kv\ interfaces.
+
+Unlike many of the other established \kv\ interfaces to define keys, \expkvd\
+works using prefixes instead of suffixes (\emph{e.g.}, |.tl_set:N| of
+\pkg{l3keys}) or directory like handlers (\emph{e.g.}, |/.store in| of
+\pkg{pgfkeys}). This was decided as a personal preference, more over in \TeX\
+parsing for the first spaces is way easier than parsing for the last one, so
+this should also turn out to be faster. \expkvd's prefixes are sorted into two
+categories: \prefixes, which are equivalent to \TeX's prefixes like |\long| and
+of which a \key\ can have multiple, and \types\ defining the basic behaviour of
+the \key\ and of which a \key\ must have one. For a description of the available
+\prefixes\ take a look at \autoref{sec:d:prefixes}, the \types\ are described in
+\autoref{sec:d:types}.
+
+
+\subsection{Macros\label{sec:d:macros}}
+
+The number of user-facing macros is quite manageable:
+
+\begin{function}{\ekvdefinekeys}
+  \begin{syntax}
+    \cs{ekvdefinekeys}\marg{set}\kvarg
+  \end{syntax}
+  In \meta{set}, define \key\ to have definition \val. The general syntax for
+  \key\ should be
+  \begin{quote}
+    \ttfamily
+    \meta{prefix} \meta{name}
+  \end{quote}
+  where \meta{prefix} is a space separated list of optional \prefixes\ followed
+  by one \type. The syntax of \val\ is dependent on the used \type.
+\end{function}
+
+\begin{function}{\ekvdDate,\ekvdVersion}
+  These two macros store the version and date of the package.
+\end{function}
+
+
+\subsection{Prefixes}
+
+As already said, prefixes are separated into two groups, \prefixes\ and \types.
+Not every \prefix\ is allowed for all \types.
+
+
+\subsubsection{\textit{Prefixes}\label{sec:d:prefixes}}
+
+\begin{function}[module=expkv-def prefix]{new}
+  The following \key\ must be new (so previously undefined). An error is thrown
+  if it is already defined and the new definition is ignored. |new| only asserts
+  that there are no conflicts between \Nkey{}s and other \Nkey{}s or \Vkey{}s
+  and other \Vkey{}s.
+\end{function}
+\begin{example}{The effects of the \texttt{new} \prefix}
+  You can test the following (lines throwing an error are marked by a comment,
+  error messages are printed in red for this example):
+  \expkvdocPrintErrors[\par]%
+  \begin{enverb}[below]
+    \ekvdefinekeys{new-example}
+      {
+         new code  key = \domystuffwitharg{#1}
+        ,new noval KEY = \domystuffwithoutarg
+        ,new bool  key = \mybool % Error!
+        ,new bool  KEY = \mybool % Error!
+        ,new meta  key = {KEY}   % Error!
+        ,new nmeta KEY = {key}   % Error!
+      }
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def prefix]{also}
+  The following key \type\ will be \emph{added} to an existing \key's
+  definition. You can't add a \type\ taking an argument at use time to an
+  existing \key\ which doesn't take an argument and vice versa. Also you'll get
+  an error if you try to add an action which isn't allowed to be either |\long|
+  or |\protected| to a \key\ which already is |\long| or |\protected| (the
+  opposite order would be suboptimal as well, but can't be really captured with
+  the current code).
+
+  A \key\ already defined as |\long| or |\protected| will stay that way, but you
+  can add |\long| or |\protected| to a \key\ which isn't by using |also|.
+\end{function}
+\begin{example}
+    {Overload a key \type\ with another with the \texttt{also} \prefix}
+  Suppose you want to create a boolean \key, but additionally to setting a
+  boolean value you want to execute some more code as well. For this you can use
+  the following:
+  \begin{enverb}[no-tcb]
+    \ekvdefinekeys{also-example}
+      {
+         bool key      = \ifmybool
+        ,also code key = \domystuff{#1}
+      }
+  \end{enverb}
+\end{example}
+
+If you use |also| on a |choice|, |bool|, |invbool|, or |boolpair| \key\ it is
+tried to determine if the key already is of one of those types. If this test is
+true the declared choices will be added to the possible choices but the key's
+definition will not be changed other than that. If that wouldn't have been done,
+the callbacks of the different choices could get called multiple times.
+
+\begin{function}[module=expkv-def prefix]{protected,protect}
+  The following \key\ will be defined |\protected|. Note that \types\ which
+  can't be defined expandable will always use |\protected|. This only affects
+  the key at use time not the \key\ definition.
+\end{function}
+
+\begin{function}[module=expkv-def prefix]{long}
+  The following \key\ will be defined |\long| (so can take an explicit |\par|
+  token in its \val). Please note that this only changes the \key\ at use time.
+  |long| being present or not doesn't limit you to use |\par| inside of the
+  \key's definition (if the \type\ allows this).
+\end{function}
+
+
+\subsubsection{\textit{Types}\label{sec:d:types}}
+
+Since the \prefixes\ apply to some of the \types\ automatically but sometimes
+one might be disallowed we need some way to highlight this behaviour. In the
+following an enforced \prefix\ will be printed black
+(\texttt{\enfprefix{protected}}), allowed \prefixes\ will be grey
+(\texttt{\allprefix{protected}}), and disallowed \prefixes\ will be red
+(\texttt{\notprefix{protected}}). This will be put flush-right in the syntax
+showing line.
+
+\begin{function}[module=expkv-def type]{code,ecode}
+  \begin{syntax}
+    code \key\ = \marg{definition} \prefixes2222
+  \end{syntax}
+  Define \key\ to be a \Vkey\ expanding to \meta{definition}. You can use |#1|
+  inside \meta{definition} to access the \key's \val. The |ecode| variant will
+  fully expand \meta{definition} inside an |\edef|.
+\end{function}
+\ekvset{enverb}{no-tcb,store}% affect all the next examples.
+\begin{example}
+    {Defining a \Vkey\ with arbitrary effect with the \texttt{code} \type}
+  The following defines the key |foo|, that'll count the number of tokens passed
+  to it (we'll borrow a function from \pkg{expl3} for this). It'll accept
+  explicit |\par| tokens. Also it'll flip the \TeX-if \cs[no-index]{iffoo} to
+  true. The result of the counting will be stored in a count register. (Don't
+  get confused, all the next examples are part of this |\ekvdefinekeys| call, so
+  there is no closing brace here.)
+  \begin{enverb}
+    \ExplSyntaxOn
+      \cs_new_eq:NN \exampleCount \tl_count_tokens:n
+    \ExplSyntaxOff
+    \newcount\examplefoocount
+    \newif\iffoo
+    \ekvdefinekeys{example}
+      {
+         protected long code foo =
+          \footrue
+          \examplefoocount=\exampleCount{#1}\relax
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{noval,enoval}
+  \begin{syntax}
+    noval \key\ = \marg{definition} \prefixes2223
+  \end{syntax}
+  The |noval| \type\ defines \key\ as a \Nkey\ expanding to \meta{definition}.
+  |enoval| fully expands \meta{definition} inside an |\edef|.
+\end{function}
+\begin{example}{An arbitrary \Nkey\ action with the \texttt{noval} \type}
+  The following defines the \Nkey\ |foo| to toggle the \TeX-if
+  \cs[no-index]{iffoo} to false and set |\examplecount| to |0|. It'll be
+  |\protected| and mustn't override any existing key.
+  \begin{enverb}
+        ,new protected noval foo = \foofalse\examplefoocount=0\relax
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{default,odefault,fdefault,edefault}
+  \begin{syntax}
+    default \key\ = \marg{definition} \prefixes2223
+  \end{syntax}
+  This serves to place a default \val\ for a \Vkey. Afterwards if you use \key\
+  as a \Nkey\ it will be the same as if \key\ got passed \meta{definition} as
+  its \val. The |odefault| variant will expand the key-macro once, so will be
+  slightly quicker, but not change if you redefine the \Vkey\ afterwards. The
+  |fdefault| version will expand the key-code until a non-expandable token or a
+  space is found, a space would be gobbled.\footnotemark{}
+  The |edefault| on the other hand fully expands the key-code with
+  \meta{definition} as its argument in |\expanded|. The \prefix\ |new|
+  means that there should be no \Nkey\ of that name yet.
+\end{function}%
+\footnotetext{For those familiar with \TeX-coding: This uses a
+\cs[no-index]{romannumeral}-expansion}
+\begin{example}
+    {Setting a default value for a \Vkey\ with the \texttt{default} \type}
+  We later decide that the above behaviour isn't what we need any more and
+  instead redefine the \Nkey\ |foo| to pass some default value to the \Vkey\
+  |foo|.
+  \begin{enverb}
+        ,default foo = {Some creative default text}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{initial,oinitial,finitial,einitial}
+  \begin{syntax}
+    initial \key\ = \marg{value} \prefixes3333
+    initial \key
+  \end{syntax}
+  With |initial| you can set an initial \val\ for an already defined \key. It'll
+  just call the \key\ and pass it \val. The |einitial| variant will expand \val\
+  using |\expanded| prior to passing it to the \key\ and the |oinitial|
+  variant will expand the first token in \val\ once. |finitial| will expand
+  \val\ until a non-expandable token or a space is found, a space would be
+  gobbled.\footnotemark
+
+  If you don't provide a \val\ (and no equals sign) the \Nkey\ of the same name
+  is called once (or, if you specified a |default| for a \Vkey\ that would be
+  used).
+\end{function}%
+\footnotetext{Again using \cs[no-index]{romannumeral}}
+\begin{example}{Specifying initial values with the \texttt{initial} \type}
+  We want to get a defined initial behaviour for our |foo|. So we count
+  0~tokens.
+  \begin{enverb}
+        ,initial foo = {}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{bool,gbool,boolTF,gboolTF}
+  \begin{syntax}
+    bool \key\ = \meta{cs} \prefixes2223
+  \end{syntax}
+  \singlecs{iffoo}
+  This will define \key\ to be a boolean key, which only takes the values |true|
+  or |false| and will throw an error for other values. If the \key\ is used as
+  a \Nkey\ it'll have the same effect as if you use |true|. |bool| and |gbool|
+  will behave like \TeX-ifs, so either be \cs[no-index]{iftrue} or
+  \cs[no-index]{iffalse}. The \meta{cs} in the |boolTF| and |gboolTF| variants
+  will take two arguments and if true the first will be used else the second, so
+  they are always either |\@firstoftwo| or |\@secondoftwo|. The variants with a
+  leading |g| will set the \meta{cs} globally, the other locally. If \meta{cs}
+  is not yet defined it'll be initialised as the |false| version. Note that the
+  initialisation is \emph{not} done with |\newif|, so you will not be able to do
+  |\footrue| outside of the \kv\ interface, but you could use |\newif| yourself.
+  Even if the \key\ will not be |\protected| the commands which execute the
+  |true| or |false| choice will be, so the usage should be safe in an expansion
+  context (\emph{e.g.}, you can use \texttt{edefault \key\ = false} without an
+  issue to change the default behaviour to execute the |false| choice).
+  Internally a |bool| is the same as a |choice| \type\ which is set up to handle
+  |true| and |false| as choices. |new| will assert that neither the \Vkey\ nor
+  the \Nkey\ are already defined.
+\end{function}
+\begin{example}{Defining Boolean keys with the \texttt{bool} \type}
+  Also we want to have a direct way to set our \cs[no-index]{iffoo}, now that
+  the \Nkey\ doesn't toggle it any longer.
+  \begin{enverb}
+        ,bool dofoo = \iffoo
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{invbool,ginvbool,invboolTF,ginvboolTF}
+  \begin{syntax}
+    invbool \key\ = \meta{cs} \prefixes2223
+  \end{syntax}
+  These are inverse boolean keys, they behave like |bool| and friends but set
+  the opposite meaning to the macro \meta{cs} in each case. So if |key=true| is
+  used |invbool| will set \meta{cs} to \cs[no-index]{iffalse} and vice versa.
+\end{function}
+\begin{example}
+    {Inversing the logic of a Boolean with the \texttt{invbool} \type}
+  And since traditional interfaces lacked \kv\ support for packages, often a
+  negated boolean key was used as well.
+  \begin{enverb}
+        ,invbool nofoo = \iffoo
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{boolpair,gboolpair,boolpairTF,gboolpairTF}
+  \begin{syntax}
+    boolpair \key\ = \meta{cs_1}\meta{cs_2} \prefixes2223
+  \end{syntax}
+  The |boolpair| \type\ behaves like both |bool| and |invbool|, the \meta{cs_1}
+  will be set to the meaning according to the rules of |bool|, and \meta{cs_2}
+  will be set to the opposite.
+\end{function}
+
+\begin{function}[module=expkv-def type]{store,estore,gstore,xstore}
+  \begin{syntax}
+    store \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  \singlecs{foo}
+  This will define a \Vkey\ to store \val\ inside of the control sequence. If
+  \meta{cs} isn't yet defined it will be initialised as empty. The variants
+  behave similarly to their |\def|, |\edef|, |\gdef|, and |\xdef| counterparts,
+  but will allow you to store macro parameters inside them without needing to
+  double them. So |estore foo = \foo, initial foo = #1| will not result in a low
+  level \TeX\ error.
+\end{function}
+\begin{example}
+    {Also store the \val\ of an existing \key\ in a macro using the
+    \texttt{also} \prefix\ and the \texttt{store} \type}
+  Not only do we want to count the tokens handed to |foo|, but we want to also
+  store them inside of a macro (and we don't need to specify |long| here, since
+  |foo| is already |\long| from our |code| definition above).
+  \begin{enverb}
+        ,also store foo = \examplefoostore
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{data,edata,gdata,xdata}
+  \begin{syntax}
+    data \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  \singlecs{foo}
+  This will define a \Vkey\ to store \val\ inside of the control sequence. But
+  unlike the |store| \type\ the macro \meta{cs} will be a switch at the same
+  time, it'll take two arguments and if \meta{key} was used expands to the first
+  argument followed by \val\ in braces, if \key\ was not used \meta{cs} will
+  expand to the second argument (so behave like |\@secondoftwo|). The idea is
+  that with this type you can define a key which should be typeset formatted.
+  The |edata| and |xdata| variants will fully expand \val, the |gdata| and
+  |xdata| variants will store \val\ inside \meta{cs} globally. Juts like with
+  |store| you can use macro parameters without having to double them. The
+  \prefixes\ only affect the key-macro, \meta{cs} will always be expandable and
+  |\long|.
+\end{function}
+\begin{example}{Define a key using the \texttt{data} \type}
+  Next we start to define other keys, now that our |foo| is pretty much
+  exhausted. The following defines a key |bar| to be a |data| key.
+  \begin{enverb}
+        ,data bar = \examplebar
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{dataT,edataT,gdataT,xdataT}
+  \begin{syntax}
+    dataT \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  Just like |data|, but instead of \meta{cs} grabbing two arguments it'll only
+  grab one, so by default it'll behave like |\@gobble|, and if \val\ was given
+  to \key\ the \meta{cs} will behave like |\@firstofone| appended by
+  \marg{value}.
+\end{function}
+\begin{example}{Define a key using the \texttt{dataT} \type}
+  Another key we want to use is |baz|.
+  \begin{enverb}
+        ,dataT baz = \examplebaz
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{int,eint,gint,xint}
+  \begin{syntax}
+    int \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  \singlecs{foo}
+  An |int| key will be a \Vkey\ setting a \TeX\ count register. If \meta{cs}
+  isn't defined yet, |\newcount| will be used to initialise it. The |eint| and
+  |xint| variants will use |\numexpr| to allow basic computations in their \val.
+  The |gint| and |xint| variants set the register globally.
+\end{function}
+
+\begin{function}[module=expkv-def type]{dimen,edimen,gdimen,xdimen}
+  \begin{syntax}
+    dimen \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  \singlecs{foo}
+  This is just like |int| but uses a dimen register, |\newdimen|, and |\dimexpr|
+  instead.
+\end{function}
+
+\begin{function}[module=expkv-def type]{skip,eskip,gskip,xskip}
+  \begin{syntax}
+    skip \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  \singlecs{foo}
+  This is just like |int| but uses a skip register, |\newskip|, and |\glueexpr|
+  instead.
+\end{function}
+\begin{example}
+    {Define keys that use \TeX\ registers, here a skip with the \texttt{eskip}
+    \type}
+  Exemplary for the different register keys, the following defines |distance| so
+  that we can store some distance.
+  \begin{enverb}
+        ,eskip distance = \exampledistance
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{toks,gtoks,apptoks,gapptoks,pretoks,gpretoks}
+  \begin{syntax}
+    toks \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  \singlecs{foo}
+  Store \val\ inside of a toks-register. The |g| variants use |\global|, the
+  |app| variants append \val\ to the contents of that register, the |pre|
+  variants will prepend \val. If \meta{cs} is not yet defined it will be
+  initialised with |\newtoks|.
+\end{function}
+
+\begin{function}[module=expkv-def type]{box,gbox}
+  \begin{syntax}
+    box \key\ = \meta{cs} \prefixes2212
+  \end{syntax}
+  \singlecs{foo}
+  Typesets \val\ into a |\hbox| and stores the result in a box register. The
+  boxes are colour safe. \expkvd\ currently doesn't provide a |vbox| type.
+\end{function}
+
+\begin{function}[module=expkv-def type]{meta}
+  \begin{syntax}
+    meta \key\ = \kvarg \prefixes2222
+  \end{syntax}
+  This key \type\ can set other keys, you can access the \val\ given to the
+  created \Vkey\ inside the \kv\ list using |#1|. This works by injecting the
+  \kv\ list into the currently parsed list, so behaves just as if the \kv\ list
+  was directly used instead of \key.
+\end{function}
+\begin{example}
+    {Define a \Vkey\ as a shortcut to set multiple other keys with the
+    \texttt{meta} \type}
+  And we want to set a full set of keys with just this single one called |all|.
+  \begin{enverb}
+        ,meta all =
+          {distance=5pt,baz=cheese cake,bar=cocktail bar,foo={#1}}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{nmeta}
+  \begin{syntax}
+    nmeta \key\ = \kvarg \prefixes2223
+  \end{syntax}
+  This \type\ sets other keys, but unlike |meta| this defines a \Nkey, so the
+  \kv\ list is static.
+\end{function}
+\begin{example}
+    {Set multiple other keys from a \Nkey\ with the \texttt{nmeta} \type}
+  and if |all| is set without a value we want to do something about it as well.
+  \begin{enverb}
+        ,nmeta all =
+          {distance=10pt,baz=nothing,bar=Waikiki bar,foo}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{smeta}
+  \begin{syntax}
+    smeta \key\ = \marg{set}\kvarg \prefixes2222
+  \end{syntax}
+  Yet another |meta| variant. |smeta| will define a \Vkey, you can access the
+  given \val\ in the provided \kv\ list using |#1|. Unlike |meta| this will
+  process that \kv\ list inside of \meta{set} using a nested |\ekvset| call, so
+  this is equal to \texttt{\cs[no-index]{ekvset}\marg{set}\kvarg}. As a
+  result you can't use |\ekvsneak| using keys or similar macros in the way you
+  normally could.
+\end{function}
+
+\begin{function}[module=expkv-def type]{snmeta}
+  \begin{syntax}
+    snmeta \key\ = \marg{set}\kvarg \prefixes2223
+  \end{syntax}
+  And the last |meta| variant. |snmeta| combines |smeta| and |nmeta|, so parses
+  the \kv\ list inside of \meta{set} and defines a \Nkey\ with a static list.
+\end{function}
+
+\begin{function}[module=expkv-def type]{set}
+  \begin{syntax}
+    set \key\ = \marg{set} \prefixes2233
+    set \key
+  \end{syntax}
+  This will define a \Nkey\ that will change the current set to \meta{set}. If
+  you give no value to this definition (omit |= |\marg{set}) the set name will
+  be the same as \key\ so
+  |set |\key\
+  is equivalent to
+  |set |\key| = |\marg{key}.
+  Note that just like in \expkv\ it'll not be checked whether \meta{set} is
+  defined and you'll get a low-level \TeX\ error if you use an undefined
+  \meta{set}.
+\end{function}
+
+\begin{function}[module=expkv-def type]{choice}
+  \begin{syntax}
+    choice \key\ = \{\val=\meta{definition}, \ldots\} \prefixes2223
+  \end{syntax}
+  |choice| defines a \Vkey\ that will only accept a limited set of values. You
+  should define each possible \meta{value} inside of the \val=\meta{definition}
+  list. If a defined \meta{value} is passed to \meta{key} the \meta{definition}
+  will be left in the input stream. You can make individual values |protected|
+  inside the \val=\meta{definition} list by using that \prefix. To also allow
+  choices that shouldn't be |\protected| but which start with the word
+  |protected| you can also use |unprotected| as a special \prefix. By default a
+  |choice| key and all its choices are expandable, an undefined \meta{value}
+  will throw an error in an expandable way. You can add additional choices after
+  the \meta{key} was created by using |choice| again for the same \key,
+  redefining choices is possible the same way, but there is no interface to
+  remove certain choices. To change the behaviour of unknown choices see also
+  the |unknown-choice| \type.
+\end{function}
+\begin{example}
+    {Define a choice with arbitrary code using the \texttt{choice} \type}
+  We give the users a few choices.
+  \begin{enverb}
+        ,choice choose =
+          {
+             protected lemonade = \def\exampledrink{something sour}
+            ,protected water = \def\exampledrink{something boring}
+          }
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{choice-store}
+  \begin{syntax}
+    choice-store \key\ = \meta{cs}\{\val=\meta{definition}, \ldots\} \prefixes2223
+  \end{syntax}
+  \singlecs{foo}
+  This is a special \type\ of the |choice| \type\ that'll store the given choice
+  inside the macro \meta{cs}. Since storing inside a macro can't be done
+  expandably every choice-code is |\protected|, and you might define the
+  |choice-store| key itself as |\protected| as well if you want. Inside the
+  \val|=|\meta{definition} list the |=|\meta{definition} part is optional, if
+  you omit it the \val\ will be stored as given during define-time inside of
+  \meta{cs} (during use-time the \val\ needs to be matched |\detokenize|d), and
+  if you specify |=|\meta{definition} that \meta{definition} will be stored
+  inside of \meta{cs} instead. If \meta{cs} doesn't yet exist it's initialised
+  as empty.
+\end{function}
+\begin{example}
+    {Show the equivalent setup for a \texttt{choice} \type\ to mimic a
+    \texttt{choice-store} \type}
+  The following keys |key1| and |key2| are equivalent at use time (this doesn't
+  continue the |\ekvdefinekeys|-call for the set |example| above):
+  \begin{enverb}[no-store,no-tcb]
+    \newcommand*\mya{}% initialise \mya
+    \ekvdefinekeys{choice-store-example}
+      {
+         choice key1 =
+          {
+             protected a = \def\mya{a}
+            ,protected b = \def\mya{b}
+            ,protected c = \def\mya{c}
+            ,protected d = \def\mya{FOO}
+          }
+        ,choice-store key2 = \myb{a,b,c,d=FOO}
+      }
+  \end{enverb}
+\end{example}
+\begin{example}
+    {Store the user's choices in a macro with the \texttt{choice-store} \type}
+  (this continues the |\ekvdefinekeys|-call for the set |example| from above)
+  After the above drinks we define a few more choices which are directly stored.
+  \begin{enverb}
+        ,choice-store choose = \exampledrink{beer,wine}
+  \end{enverb}
+  One might notice that the entire setup of the |choose| key could've been done
+  using only |choice-store|.
+\end{example}
+
+\begin{function}[module=expkv-def type]{choice-enum}
+  \begin{syntax}
+    choice-enum \key\ = \meta{cs}\{\val, \ldots\} \prefixes2223
+  \end{syntax}
+  \singlecs{foo}
+  This is similar to |choice-store|, the differences are: \meta{cs} should be a
+  count register or is initialised as such using |\newcount|; instead of the
+  \val\ itself being stored its position in the list of choices is stored
+  (zero-based). It is not possible to specify a \meta{definition} to store
+  something else than the numerical position inside the list.
+\end{function}
+\begin{example}
+    {Show the equivalent setup for a \texttt{choice} \type\ to mimic a
+    \texttt{choice-enum} \type}
+  The following keys |key1| and |key2| are equivalent at use time (another
+  example not using the |example| set of above's |\ekvdefinekeys|):
+  \begin{enverb}[no-store,no-tcb]
+    \newcount\myc
+    \ekvdefinekeys{choice-enum-example}
+      {
+         choice key1 =
+          {
+             protected a={\myc=0 }
+            ,protected b={\myc=1 }
+            ,protected c={\myc=2 }
+          }
+        ,choice-enum key2 = \myd{a,b,c}
+      }
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{unknown-choice}
+  \begin{syntax}
+    unknown-choice \key\ = \marg{definition} \prefixes2323
+  \end{syntax}
+  By default an unknown \val\ passed to a |choice| or |bool| \type\ (and all
+  their variants) will throw an error. However, with this prefix you can define
+  an alternative action which should be executed if \key\ received an unknown
+  choice. In \meta{definition} you can refer to the given invalid choice with
+  |#1|.
+\end{function}
+\begin{example}
+    {Handle unknown choices without throwing an error with the
+    \texttt{unknown-choice} \type}
+  If a drink was chosen with |choose| that's not defined we don't want to throw
+  an error, but store something else instead.
+  \begin{enverb}
+        ,protected unknown-choice choose =
+          \def\exampledrink{something unavailable}
+      }% closing brace for \ekvdefinekeys
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=expkv-def type]{unknown code}
+  \begin{syntax}
+    unknown code = \marg{definition} \prefixes2322
+  \end{syntax}
+  By default \expkv\ throws errors when it encounters unknown keys in a set.
+  With the |unknown| \type\ you can define handlers that deal with undefined
+  keys, instead of a \key\ name you have to specify a subtype for this, here the
+  subtype is |code|.
+
+  With |unknown code| the \meta{definition} is used for unknown keys which were
+  provided a value (so corresponds to |\ekvdefunknown|), you can access the
+  unknown \key\ name with |#1| (|\detokenize|d), the given \val\ with |#2|, and
+  the unprocessed \key\ name with |#3| (in case you want to further expand
+  it).\footnotemark
+\end{function}%
+\footnotetext{There is some trickery involved to get this more intuitive
+argument order without any performance hit if you compare this to
+\cs[no-index]{ekvdefunknown} directly}
+
+\begin{function}[module=expkv-def type]{unknown noval}
+  \begin{syntax}
+    unknown noval = \marg{definition} \prefixes2323
+  \end{syntax}
+  This is like |unknown code| but uses \meta{definition} for unknown keys to
+  which no value was passed (so corresponds to |\ekvdefunknownNoVal|). You can
+  access the |\detokenize|d \key\ name with |#1| and the unprocessed one with
+  |#2|.
+\end{function}
+
+\begin{function}[module=expkv-def type]{unknown redirect-code}
+  \begin{syntax}
+    unknown redirect-code = \marg{set-list} \prefixes2331
+  \end{syntax}
+  This uses a predefined action for |unknown code|. Instead of throwing an
+  error, it is tried to find the \meta{key} in each \meta{set} in the comma
+  separated \meta{set-list}. The first found match will be used and the
+  remaining options from the list discarded. If the \meta{key} isn't found in
+  any \meta{set} an expandable error will be thrown eventually. Internally
+  \expkv's |\ekvredirectunknown| will be used.
+\end{function}
+
+\begin{function}[module=expkv-def type]{unknown redirect-noval}
+  \begin{syntax}
+    unknown redirect-noval = \marg{set-list} \prefixes2333
+  \end{syntax}
+  This behaves just like |unknown redirect-code| but will set up means to
+  forward keys for |unknown noval|. Internally \expkv's
+  |\ekvredirectunknownNoVal| will be used.
+\end{function}
+
+\begin{function}[module=expkv-def type]{unknown redirect}
+  \begin{syntax}
+    unknown redirect = \marg{set-list} \prefixes2333
+  \end{syntax}
+  This is a short cut to apply both, |unknown redirect-code| and
+  |unknown redirect-noval|, as a result you might get doubled error messages,
+  one from each.
+\end{function}
+
+\bigskip
+Time to use all those keys defined in the different examples!
+% undo the global no-tcb setting
+\ekvset{enverb}{no-store,undo-no-tcb}%
+\begin{enverb}[restore,below,inter=Which results in three paragraphs of text:]
+  \newcommand\defexample[1][]
+    {%
+      \ekvset{example}{#1}%
+      After walking \the\exampledistance\space we finally reached
+      \examplebar{\emph}{no particular place}.
+      There I ordered
+      \iffoo
+        a drink called \examplefoostore\space (that has
+        \the\examplefoocount\space tokens in it)%
+      \else
+        nothing of particular interest%
+      \fi
+      \examplebaz{ and ate \emph}.
+      Then a friend of mine also chose \exampledrink.
+      \par
+    }
+  \defexample[nofoo]
+  \defexample[all,choose=lemonade]
+  \defexample
+    [all=wheat beer,bar=Biergarten,baz=pretzel,choose=champagne]
+\end{enverb}
+
+\subsection{Another Example}
+
+This picks up the standard use case from \autoref{sec:expkv:standard}, but
+defines the keys using |\ekvdefinekeys|.
+
+\begin{enverb}
+  \makeatletter
+  \ekvdefinekeys{myrule}
+    {
+       store   ht    = \myrule at ht
+      ,initial ht    = 1ex
+      ,store   wd    = \myrule at wd
+      ,initial wd    = 0.1em
+      ,store   raise = \myrule at raise
+      ,initial raise = \z@
+      ,meta    lower = {raise={-#1}}
+    }
+  \ekvsetdef\myruleset{myrule}
+  \newcommand*\myrule[1][]
+    {%
+      \begingroup
+        \myruleset{#1}%
+        \rule[\myrule at raise]{\myrule at wd}{\myrule at ht}%
+      \endgroup
+    }
+  \makeatother
+  a\myrule\par
+  a\myrule[ht=2ex,lower=.5ex]\par
+  \myruleset{wd=5pt}
+  a\myrule
+\end{enverb}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-def.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-main.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-main.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-main.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,1097 @@
+\genericekv\expkv{}
+
+This package supports two different front ends to parse a \kv\ list. The first
+(|\ekvset|) is similar to \pkg{keyval}'s |\setkeys|, it parses the list and
+executes defined actions based on the encountered \key{}s. The second
+(|\ekvparse|) is more versatile, it only splits the list into \key{}s and
+\val{}s and then runs user-provided code on the result.
+
+The first is described in subsections~\ref{sec:expkv:setup}
+to~\ref{sec:expkv:set}, the latter is described in \autoref{sec:expkv:parse}.
+
+Unlike the other packages in the bundle, if you load \expkv\ as a \LaTeXe\
+package there is a single option available:
+\begin{function}{all}
+  \begin{syntax}
+    \cs[no-index]{usepackage}[all]\{expkv\}
+  \end{syntax}
+  Loads all the packages of \expkvbundle.
+\end{function}
+
+\subsection{General Parsing Rules}
+
+\expkv\ parses a \kv\ list by first splitting the elements on commas (active or
+other), then looking for an equals sign (active or other). If there is one the
+\kv\ pair will be split at the first. From both \key\ and \val\ (if there was a
+\val) one set of outer spaces is stripped, and afterwards one set of outer
+braces (meaning braces which are around the complete remainder after space
+stripping if there are any).
+
+So the syntax looks something like the following pseudo-input:
+\begin{syntaxexample}
+  \vissp{ \marg{key} = \marg{value} }
+\end{syntaxexample}
+with the displayed spaces and braces being optional and removed if found. Note
+that if you want either \key\ or \val\ to include a comma the braces become
+mandatory, the same is true if \key\ should contain an equals sign.
+
+\subsubsection{Expansion Control\label{sec:expkv:expansion}}
+
+\expkv\ provides a mechanism to specify expansions of a \key\ and/or \val. For
+those familiar with \pkg{pgfkeys} this is similar to its |.expand once| or
+|.expanded| handlers. This concept will be called \expnotation\ or \expansion\
+throughout this documentation.
+
+The syntax for this notation is a leading list of \expansion-rules followed by a
+colon that is immediately followed by a space. Also the \expansion-rules must
+not contain any spaces outside of braces, and the remainder on the right hand
+side of the colon must not be blank, else it is not considered an \expnotation\
+but just a weirdly formed \key-name.
+
+The entire syntax of a \kv\ pair is
+\begin{syntaxexample}
+  \vissp{ \{\expansion: \asciispace\marg{key} \} = \marg{value} }
+\end{syntaxexample}
+Note that the \expansion\ prefix is right delimited by \verb*|: | so the space
+after the colon is only optional in the sense that the entire \expansion\ prefix
+is optional. Else all displayed spaces and braces are optional, the inner set of
+spaces and braces around \key\ only being optional if the optional \expansion\
+prefix (\expansion\verb*|: |) was present. If that part was present the list of
+\expansion-rules will be executed, which might change the contents of both \key\
+and \val. For |\ekvparse| this is always true, however in |\ekvset| it is only
+parsed for the \expnotation\ if there is no \key\ matching the given input (so
+this notation doesn't impose a restriction on key names, though \key-names
+actually containing what would otherwise be an \expansion\ prefix should be
+pretty rare in practice).
+
+All packages in \expkvbundle\ support this notation (most of them internally use
+|\ekvset| or |\ekvparse|). Please note however that while \expkvo\ fully
+supports them, reinsertion via the |\r| \expansion-rule might affect the unused
+global options list if used in the class options.
+
+An \expansion-rule consists of a single token. In a \Vkey\ they work on the
+\val\ (but you can use the |\key| rule to also affect the \key\ there) while in
+a \Nkey\ they work on the \key. The following rules are available (those
+familiar with \pkg{expl3} will notice that the first six are identical to its
+argument types):
+
+\begingroup
+\let\bigskip\medskip
+\begin{function}[module=Expansion]{o}
+  Expands the first token once.
+\end{function}
+
+\begin{function}[module=Expansion]{e}
+  Expands the entire \val\ inside of |\expanded|.
+\end{function}
+
+\begin{function}[module=Expansion]{c}
+  Builds a |\csname| from the contents.
+\end{function}
+
+\begin{function}[module=Expansion]{f}
+  Expands the contents until a space or an unexpandable token is found (the
+  space would be removed).
+\end{function}
+
+\begin{function}[module=Expansion]{V}
+  The \val\ should be a single token, either defined as a parameterless macro or
+  as a register (via |\newcount| etc.). This expands to the value of the
+  register or the macro's replacement text. If the token in \val\ has the
+  |\meaning| of |\relax| an error is thrown and the result is empty.
+\end{function}
+
+\begin{function}[module=Expansion]{v}
+  This is a combination of |c| and |V|, meaning the \val\ is turned into a
+  single control sequence via |\csname|, and then expanded to its value. The
+  control sequence will only be built if it's defined.
+\end{function}
+\begin{example}{The difference between \texttt{co} and \texttt{v} expansion}
+  Say we want to hand the contents of a macro as the value to our key, but the
+  actual macro name depends on user input. For this we have two options which
+  behave slightly different. One is to use |v| the other is to combine the |co|
+  \expansion-rules. The following demonstrates both (I modified the way errors
+  are thrown to instead output them in red for this; you'll learn about
+  |\ekvparse| in a few pages, for now just stick with me):
+  \expkvdocPrintErrors
+  \makeatletter
+  \begin{enverb}[below]
+    \newcommand\mypair[2]{Arg: `\detokenize{#2}'. }%
+    \newcommand\myvalue{Value}%
+    \ekvparse\@firstofone\mypair
+      {
+         co: key = myvalue, v: key = myvalue, \par
+        ,co: key = myValue, v: key = myValue, \par
+      }
+  \end{enverb}
+  The difference is that in |co| the variable is implicitly initialised as
+  |\relax| by |c| if it doesn't exist and then doesn't expand in |o|. On the
+  other hand |v| will check whether the variable would exist and throw an error
+  if it doesn't (and will not set it to |\relax| by blindly using |\csname|).
+\end{example}
+
+\begin{function}[module=Expansion]{s}
+  Strips one set of outer spaces and outer braces.
+\end{function}
+
+\begin{function}[module=Expansion]{b}
+  Adds one set of outer braces.
+\end{function}
+
+\begin{function}[module=Expansion]{p}
+  \begin{syntax}
+    p\marg{contents}
+  \end{syntax}
+  Places \meta{contents} before the \val.
+\end{function}
+
+\begin{function}[module=Expansion]{P}
+  \begin{syntax}
+    P\marg{contents}
+  \end{syntax}
+  Places \meta{contents} after the \val.
+\end{function}
+
+\begin{function}[module=Expansion]{g}
+  Gobbles the first token or balanced group on the left (leads to a low-level
+  \TeX-error if the \val\ is empty).
+\end{function}
+
+\begin{function}[module=Expansion]{\r}
+  In a \Vkey\ reinserts the contents of \val\ after all the \expansion-rules
+  were executed (the \key-name needs to be empty). In a \Nkey\ the contents of
+  \key\ are reinserted after all the \expansion-rules were executed (the \val\
+  needs to be empty, which is an easy to fulfil rule as there was no \val).
+  Normal \kv\ parsing is aborted afterwards for the current \kv\ list element.
+\end{function}
+\begin{example}{Parse the contents of a macro as additional \kv\ input}
+  Say we want to store a list of common settings in a macro, then we want to
+  parse a few keys, insert the contents of the macro, and parse a few more keys.
+  The following does exactly that (|\ekvset| is analogue to |\setkeys| of the
+  \pkg{keyval} package if you're familiar with it, else you'll learn about
+  |\ekvset| a few pages down the road so be patient):
+  \begin{enverb}[no-tcb]
+    \newcommand*\mykeylist{color=red,height=5cm}
+    \ekvset{mypkg}{key=value, o\r: \mykeylist, other key=other value}
+  \end{enverb}
+  You could also use the following with the same outcome, but this looks more
+  complicated so the other form should be preferred:
+  \begin{enverb}[no-tcb]
+    \ekvset{mypkg}{key=value, o\r: {}=\mykeylist, other key=other value}
+  \end{enverb}
+\end{example}
+
+\begin{function}[module=Expansion]{\key}
+  \begin{syntax}
+    \cs[module=Expansion]{key}\marg{expansion}
+  \end{syntax}
+  This is the only supported way to change the contents of \key\ for a \Vkey\ in
+  the \expnotation. All the rules in \expansion\ are applied to \key\ instead of
+  \val.
+\end{function}
+
+\begin{function}[module=Expansion]{R}
+  This is the same as if you used |V\r|. So it expects a single token, retrieves
+  its value, and reinserts this as additional \kv\ input.
+\end{function}
+
+\begin{function}[module=Expansion]{r}
+  This is the same as if you used |v\r|. So it builds a |\csname| if that is
+  defined, retrieves its value, and reinserts this as additional \kv\ input.
+\end{function}
+\begin{example}
+  {Parse the contents of a macro as additional \kv\ input (revisited)}
+  Now that we also know the |R| and |r| rule, the example above can be input
+  even simpler:
+  \begin{enverb}[no-tcb]
+    \ekvset{mypkg}{key=value, R: \mykeylist, other key=other value}
+  \end{enverb}
+  or
+  \begin{enverb}[no-tcb]
+    \ekvset{mypkg}{key=value, r: mykeylist, other key=other value}
+  \end{enverb}
+\end{example}
+\endgroup
+
+\subsection{Setting up Keys\label{sec:expkv:setup}}
+
+\expkv\ provides a rather simple approach to setting up keys, similar to
+\pkg{keyval}. If you're looking for a more sophisticated interface similar to
+those of \pkg{l3keys} or \pkg{pgfkeys} take a look at \expkvd\ described in
+\autoref{sec:expkv-def} or for a simple interface that defines expandable macros
+at \expkvc\ described in \autoref{sec:expkv-cs}.
+
+Keys in \expkv\ (as in many other \kv\ implementations) belong to a \emph{set},
+so that different sets can contain keys of the same name. Unlike many other
+implementations \expkv\ doesn't provide means to set a default value, instead we
+have keys that take a value (we call those \Vkey) and keys that don't (which are
+called \Nkey\ by \expkv), but both can share the same name on the user level,
+the only difference for the user is whether =\val\ was used or not.
+
+The following macros are available to define new keys. Those macros containing
+\enquote{\texttt{def}} in their name can be prefixed by anything allowed to
+prefix |\def| (but \emph{don't} use |\outer|, keys defined with it won't ever be
+usable). And prefixes allowed for |\let| can prefix those macros with
+\enquote{\texttt{let}} in their name, accordingly. Neither \set\ nor \key\ are
+allowed to be empty for new keys. \set\ will be used as is inside of
+|\csname ...\endcsname| and \key\ will get |\detokenize|d. Also \set\ should not
+contain an explicit |\par| token.
+
+\begin{function}{\ekvdef}
+  \begin{syntax}
+    \cs{ekvdef}\marg{set}\marg{key}\marg{code}
+  \end{syntax}
+  Defines a \Vkey\ in a \set\ to expand to \meta{code}. In \meta{code} you can
+  use |#1| to refer to the given \val.
+\end{function}
+\begin{example}{Define a single \Vkey}
+  Define |text| in |foo| to store the \val\ inside |\foo at text|:
+  \begin{enverb}[no-tcb]
+    \protected\long\ekvdef{foo}{text}{\def\foo at text{#1}}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvdefNoVal}
+  \begin{syntax}
+    \cs{ekvdefNoVal}\marg{set}\marg{key}\marg{code}
+  \end{syntax}
+  Defines a \Nkey\ in \set\ to expand to \meta{code}.
+\end{function}
+\begin{example}{Define a single \Nkey}
+  Define |bool| in |foo| to set |\iffoo at bool| to |true|:
+  \begin{enverb}[no-tcb]
+    \protected\ekvdefNoVal{foo}{bool}{\foo at booltrue}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvlet}
+  \begin{syntax}
+    \cs{ekvlet}\marg{set}\marg{key}\meta{cs}
+  \end{syntax}
+  Let the \Vkey\ in \set\ to \meta{cs}. There are no checks on \meta{cs}
+  enforced, but the code should expect the \val\ as a single braced argument
+  directly following it.
+\end{function}
+\begin{example}{Copy a macro to define a \Vkey}
+  Let |cmd| in |foo| do the same as |\foo at cmd|:
+  \begin{enverb}[no-tcb]
+    \ekvlet{foo}{cmd}\foo at cmd
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvletNoVal}
+  \begin{syntax}
+    \cs{ekvletNoVal} \marg{set} \marg{key} \meta{cs}
+  \end{syntax}
+  Let the \Nkey\ in \set\ to \meta{cs}. Again no checks on \meta{cs} are done.
+  It shouldn't expect any provided argument.
+\end{function}
+\begin{example}{Copy a macro to define a \Nkey}
+  See above.
+\end{example}
+
+\begin{function}{\ekvletkv}
+  \begin{syntax}
+    \cs{ekvletkv}\marg{set}\marg{key}\marg{set2}\marg{key2}
+  \end{syntax}
+  Copies the definition such that \Vkey\ in \set\ behaves like \meta{key2} of
+  \meta{set2}. It is not checked whether that second key exists!
+\end{function}
+\begin{example}{Copy an existing \Vkey}
+  Let |B| in |bar| do the same as |A| in |foo|:
+  \begin{enverb}[no-tcb]
+    \ekvletkv{bar}{B}{foo}{A}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvletkvNoVal}
+  \begin{syntax}
+    \cs{ekvletkvNoVal}\marg{set}\marg{key}\marg{set2}\marg{key2}
+  \end{syntax}
+  And this lets the \Nkey\ in \set\ to the definition of the |NoVal|-\meta{key2}
+  in \meta{set2}. Again, it is not checked whether the second key exists.
+\end{function}
+\begin{example}{Copy an existing \Nkey}
+  See above.
+\end{example}
+
+\subsection{Handle Unknown Keys}
+
+By default \expkv\ throws an error message if it encounters an undefined \key.
+You can change this behaviour with the macros listed here. Just like in the
+section above, prefixes for |\def| are allowed if the macro has |def| in its
+name, and |\let| prefixes are allowed if the macro is named something with
+|let|.
+
+\begin{function}{\ekvdefunknown}
+  \begin{syntax}
+    \cs{ekvdefunknown}\marg{set}\marg{code}
+  \end{syntax}
+  Execute \meta{code} if an undefined \Vkey\ is encountered while parsing in
+  \set. You can refer to the given \val\ with |#1|, the unknown \key's name
+  with |#2| (will be |\detokenize|d), and to the \key's name without
+  |\detokenize| applied with |#3| in \meta{code} (this order is chosen for
+  performance reasons).
+
+  \cs{ekvdefunknown} and \cs{ekvredirectunknown} are mutually exclusive, you
+  can't use both.
+\end{function}
+\begin{example}{Search undefined \Vkey{}s in another \set}
+  Also search |bar| for undefined keys of set |foo| (and use the not yet
+  |\detokenize|d \key's name in case the undefined key handler of |bar| needs
+  that):
+  \begin{enverb}[no-tcb]
+    \long\ekvdefunknown{foo}{\ekvset{bar}{{#3}={#1}}}
+  \end{enverb}
+  This example differs from using |\ekvredirectunknown{foo}{bar}| (see below) in
+  that also the unknown-key handler of the |bar| set will be triggered, error
+  messages for undefined keys will look different, and this is slower than using
+  \cs{ekvredirectunknown}.
+\end{example}
+
+\begin{function}{\ekvdefunknownNoVal}
+  \begin{syntax}
+    \cs{ekvdefunknownNoVal}\marg{set}\marg{code}
+  \end{syntax}
+  With this you can let \expkv\ execute \meta{code} if an unknown \Nkey\ was
+  encountered. You can refer to the given \key\ with |#1| (will be
+  |\detokenize|d), and to the not |\detokenize|d \key's name with |#2|.
+
+  \cs{ekvdefunknownNoVal} and \cs{ekvredirectunknownNoVal}
+  are mutually exclusive, you can't use both.
+\end{function}
+\begin{example}{Search undefined \Nkey{}s in another \set}
+  Adding to the above also handling of \Nkey{}s in |foo|:
+  \begin{enverb}[no-tcb]
+    \ekvdefunknownNoVal{foo}{\ekvset{bar}{{#2}}}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvredirectunknown}
+  \begin{syntax}
+    \cs{ekvredirectunknown}\marg{set}\marg{set-list}
+  \end{syntax}
+  This is a short cut to set up a special \cs{ekvdefunknown}-rule for \set\ that
+  will check each set in the comma separated \meta{set-list} for an unknown
+  \Vkey. The resulting unknown-key handler will always be |\long| and \emph{not}
+  |\protected|. The first set in \meta{set-list} has highest priority, once the
+  \Vkey\ is found in one of the sets the remainder of the list is discarded. If
+  \meta{key} isn't found in any of the sets an error will be thrown eventually.
+  Note that the error message looks different than a normal key-not-found error,
+  in particular no unwanted-value message can be thrown (it will not be checked
+  if a \Nkey\ of the same name does exist), and the error message will contain
+  all sets.
+
+  \cs{ekvdefunknown} and \cs{ekvredirectunknown}
+  are mutually exclusive, you can't use both.
+\end{function}
+\begin{example}{Search an undefined \Vkey\ in a list of other \set{}s}
+  For every undefined \Vkey\ in |foo| also search the sets |bar| and |baz|:
+  \begin{enverb}[no-tcb]
+    \ekvredirectunknown{foo}{bar, baz}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvredirectunknownNoVal}
+  \begin{syntax}
+    \cs{ekvredirectunknownNoVal}\marg{set}\marg{set-list}
+  \end{syntax}
+  This behaves just like \cs{ekvredirectunknown}, it does the same but for
+  \Nkey{}s. Again no prefixes are supported (the result will neither be |\long|
+  nor |\protected|). Note that the error messages will not check whether a
+  missing-value error should be thrown.
+
+  \cs{ekvdefunknownNoVal} and \cs{ekvredirectunknownNoVal}
+  are mutually exclusive, you can't use both.
+\end{function}
+\begin{example}{Search an undefined \Nkey\ in a list of other \set{}s}
+  See above.
+\end{example}
+
+\begin{function}{\ekvletunknown}
+  \begin{syntax}
+    \cs{ekvletunknown}\marg{set}\meta{cs}
+  \end{syntax}
+  This lets the handler for unknown \Vkey{}s to \meta{cs}. \meta{cs} should
+  expect three arguments, the first will be the \val\ the second the
+  |\detokenize|d \key-name, the third the unprocessed \key-name. No conditions
+  on \meta{cs} are enforced.
+\end{function}
+\begin{example}
+    {Do the same as an already defined macro if an unknown \Vkey\ is found}
+  Let the set |foo| do the same as the macro |\foo at unknown| whenever an unknown
+  \Vkey\ is encountered:
+  \begin{enverb}[no-tcb]
+    \ekvletunknown{foo}\foo at unknown
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvletunknownNoVal}
+  \begin{syntax}
+    \cs{ekvletunknownNoVal}\marg{set}\meta{cs}
+  \end{syntax}
+  This does the same as \cs{ekvletunknown} but for \Nkey{}s. The \meta{cs}
+  should expect two arguments, namely the |\detokenize|d \key\ and the
+  unprocessed \key.
+\end{function}
+\begin{example}{Silently ignore unknown \Nkey{}s}
+  Let the set |foo| ignore unknown \Nkey{}s by gobbling the \key-name:
+  \begin{enverb}[no-tcb]
+    \ekvletunknownNoVal{foo}\@gobbletwo
+  \end{enverb}
+\end{example}
+
+\subsection{Helpers in Actions}
+
+\begin{function}{\ekvifdefined,\ekvifdefinedNoVal}
+  \begin{syntax}
+    \cs{ekvifdefined}\marg{set}\marg{key}\marg{true}\marg{false}
+    \cs{ekvifdefinedNoVal}\marg{set}\marg{key}\marg{true}\marg{false}
+  \end{syntax}
+  These two macros test whether there is a \key\ in \set. It is false if either
+  a hash table entry doesn't exist for that key or its meaning is |\relax|.
+\end{function}
+\begin{example}{Check if a \Vkey\ is already defined}
+  Check whether the key |special| is already defined in set |foo|, if it isn't
+  input a file that contains more key definitions:
+  \begin{enverb}[no-tcb]
+    \ekvifdefined{foo}{special}{}{\input{foo.morekeys.tex}}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvifdefinedset}
+  \begin{syntax}
+    \cs{ekvifdefinedset}\marg{set}\marg{true}\marg{false}
+  \end{syntax}
+  This macro tests whether \set\ is defined (which it is if at least one key was
+  defined for it). If it is \meta{true} will be run, else \meta{false}.
+\end{function}
+\begin{example}{Check if a \set\ is already defined}
+  Check whether the set |VeRyUnLiKeLy| is already defined, if so throw an error,
+  else do nothing:
+  \begin{enverb}[no-tcb]
+    \ekvifdefinedset{VeRyUnLiKeLy}
+      {\errmessage{VeRyUnLiKeLy already defined}}{}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvsneak,\ekvsneakPre}
+  \begin{syntax}
+    \cs{ekvsneak}\marg{after}
+  \end{syntax}
+  Puts \meta{after} after the effects of \cs{ekvset} (without cancelling the
+  current \cs{ekvset} call). The first variant will put \meta{after} after any
+  other tokens which might have been sneaked before, while \cs{ekvsneakPre} will
+  put \meta{after} before other smuggled stuff. After \cs{ekvset} has parsed the
+  entire \kv\ list everything that has been \cs{ekvsneak}ed will be left in the
+  input stream.
+\end{function}
+\begin{example}{Execute code after \cs[no-index]{ekvset} if a \Nkey\ was used}
+  Define a key |secret| in the set |foo| that will sneak out
+  |\foo at secretly@sneaked|:
+  \begin{enverb}[no-tcb]
+    \ekvdefNoVal{foo}{secret}{\ekvsneak{\foo at secretly@sneaked}}
+  \end{enverb}
+\end{example}
+A more elaborate usage example is shown in \autoref{sec:expkv:sneak}.
+
+\begin{function}{\ekvbreak,\ekvbreakPreSneak,\ekvbreakPostSneak}
+  \begin{syntax}
+    \cs{ekvbreak}\marg{after}
+  \end{syntax}
+  Gobbles the remainder of the current \cs{ekvset} call and its argument list
+  and inserts \meta{after}. So this can be used to break out of \cs{ekvset}. The
+  first variant will also gobble anything that has been sneaked out using
+  \cs{ekvsneak} or \cs{ekvsneakPre}, while \cs{ekvbreakPreSneak} will put
+  \meta{after} before anything that has been smuggled and \cs{ekvbreakPostSneak}
+  will put \meta{after} after the stuff that has been sneaked out.
+\end{function}
+\begin{example}{Stop parsing a \kv\ list if a specific \Nkey\ was used}
+  Define a key |abort| that will stop key parsing inside the set |foo| and
+  execute |\foo at aborted|, or if it got a value |\foo at aborted@with|:
+  \begin{enverb}[no-tcb]
+    \ekvdefNoVal{foo}{abort}{\ekvbreak{\foo at aborted}}
+    \ekvdef{foo}{abort}{\ekvbreak{\foo at aborted@with{#1}}}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvmorekv}
+  \begin{syntax}
+    \cs{ekvmorekv}\kvarg
+  \end{syntax}
+  Adds the contents of the \kv\ list to the list processed by the current call
+  of |\ekvset|.
+\end{function}
+\begin{example}{Use one \key\ to set multiple other keys}
+  Define a \Nkey\ |style| that sets the keys |border|, |width|, and |height| as
+  a shortcut:
+  \begin{enverb}[no-tcb]
+    \ekvdefNoVal{foo}{style}{\ekvmorekv{border, width=2cm, height=1.5ex}}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvchangeset}
+  \begin{syntax}
+    \cs{ekvchangeset}\marg{new-set}
+  \end{syntax}
+  Replaces the current \set\ with \meta{new-set}, so for the rest of the current
+  \cs{ekvset} call that call behaves as if it was called with
+  \cs{ekvset}\marg{new-set}. It is comparable to using \key|/.cd| in
+  \pkg{pgfkeys}.
+\end{function}
+\begin{example}{Change the current \set}
+  Define a key |cd| in set |foo| that will change to another set as specified in
+  the \val. If the set is undefined it'll stop the parsing and throw an error as
+  defined in the macro |\foo at cd@error|:
+  \begin{enverb}[no-tcb]
+    \ekvdef{foo}{cd}
+      {\ekvifdefinedset{#1}{\ekvchangeset{#1}}{\ekvbreak{\foo at cd@error}}}
+  \end{enverb}
+\end{example}
+
+\subsection{Parsing Keys in Sets}\label{sec:expkv:set}
+
+\begin{function}{\ekvset}
+  \begin{syntax}
+    \cs{ekvset}\marg{set}\kvarg
+  \end{syntax}
+  This macro parses the \kv\ list and checks for defined \key{}s that are in
+  \set. Unlike the generic \cs{ekvparse} this macro uses |\detokenize| on the
+  \key\ before checking whether it is a defined key.
+
+  \cs{ekvset} is nestable, and fully expandable. But it is \emph{not} alignment
+  safe. As a result \key\ names and \val{}s that contain an |&| must be wrapped
+  in braces if \cs{ekvset} is used inside an alignment (like \LaTeXe's |tabular|
+  environment) or alternatively you have to create a wrapper that ensurs an
+  alignment safe context.
+\end{function}
+\begin{example}{Set defined keys using \cs[no-index]{ekvset}}
+  Parse |key=arg, key| in set |foo|:
+  \begin{enverb}[no-tcb]
+    \ekvset{foo}{key=arg, key}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvsetSneaked}
+  \begin{syntax}
+    \cs{ekvsetSneaked}\marg{set}\marg{sneak}\kvarg
+  \end{syntax}
+  This behaves like \cs{ekvset} in which \cs{ekvsneak} was immediately called.
+\end{function}
+\begin{example}
+    {Set defined keys and execute code afterwards using
+    \cs[no-index]{ekvsetSneaked}}
+  Parse |key=arg, key| in the set |foo| with |\afterwards| sneaked out:
+  \begin{enverb}[no-tcb]
+    \ekvsetSneaked{foo}{\afterwards}{key=arg, key}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvsetdef}
+  \begin{syntax}
+    \cs{ekvsetdef}\meta{cs}\marg{set}
+  \end{syntax}
+  Defines the macro \meta{cs} to be a shortcut for \cs{ekvset}\marg{set}. You
+  can use any \TeX-prefix allowed to prefix |\def| for \cs{ekvsetdef} (so
+  |\long|, |\protected|, or |\global| -- don't use |\outer|).
+  The resulting macro is faster than but else equivalent to the idiomatic
+  definition:\par
+  |\def|\meta{cs}|#1{|\cs{ekvset}\marg{set}|{#1}}|
+\end{function}
+\begin{example}
+    {Define a setup command for a defined \set\ using \cs[no-index]{ekvsetdef}}
+  Define the macro |\foosetup| to parse keys in the set |foo| and use it to
+  parse |key=arg, key|:
+  \begin{enverb}[no-tcb]
+    \ekvsetdef\foosetup{foo}
+    \foosetup{key=arg, key}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvsetSneakeddef}
+  \begin{syntax}
+    \cs{ekvsetSneakeddef}\meta{cs}\marg{set}
+  \end{syntax}
+  Just like \cs{ekvsetdef} this defines a shorthand macro \meta{cs}, but this
+  will make it a shorthand for \cs{ekvsetSneaked}, meaning \meta{cs} will take
+  two arguments (first the \cs{ekvsneak} argument, then the \kv\ list). Hence
+  the result is a faster version of:\par
+  |\long\def|\meta{cs}|#1#2{|\cs{ekvsetSneaked}\marg{set}|{#1}{#2}}|
+\end{function}
+\begin{example}
+    {Define a setup command that will also require code to execute after all
+    keys were processed using \cs[no-index]{ekvsetSneakeddef}}
+  Define the macro |\foothings| to parse keys in the set |foo| and accept a
+  sneaked argument, then use it to parse |key=arg, key| and sneak |\afterwards|:
+  \begin{enverb}[no-tcb]
+    \ekvsetSneakeddef\foothings{foo}
+    \foothings{\afterwards}{key=arg, key}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvsetdefSneaked}
+  \begin{syntax}
+    \cs{ekvsetdefSneaked}\meta{cs}\marg{set}\marg{sneaked}
+  \end{syntax}
+  This macro behaves like \cs{ekvsetSneakeddef}, but with a fixed \meta{sneaked}
+  argument. So the resulting macro is faster than but else equivalent to\par
+  |\long\def|\meta{cs}|#1{|\cs{ekvsetSneaked}\marg{set}\marg{sneaked}|{#1}}|
+\end{function}
+\begin{example}
+    {Define a setup command that will execute codes after all keys were
+    processed using \cs[no-index]{ekvsetdefSneaked}}
+  Define the macro |\barthing| to parse keys in the set |bar| and always execute
+  |\afterwards| afterwards, then use it to parse |key=arg, key|:
+  \begin{enverb}[no-tcb]
+    \ekvsetdefSneaked\barthing{bar}{\afterwards}
+    \barthing{key=arg, key}
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvcompile}
+  \begin{syntax}
+    \cs{ekvcompile}\meta{*}\meta{cs}\meta{parameters}\marg{set}\kvarg
+  \end{syntax}
+  This macro defines \meta{cs} to be a \emph{fast} way to set the given \kv\
+  list in \meta{set}. The meaning of the keys is frozen if you don't give the
+  optional |*| (if the star is present the stored content will be the key-macros
+  and later redefinitions of keys will affect them, otherwise the key-macros are
+  expanded once, hence the key-code is stored). This does support the unknown
+  key handlers set up with |\ekvdefunknown| and |\ekvdefunknownNoVal| and also
+  the redirection of unknown keys (the latter will not be expanded exhaustively
+  though, so the key-search is done on every later call of \meta{cs}). Any
+  prefix allowed for |\def| might prefix \cs{ekvcompile}. The list is not
+  entirely fixed, as you might use \meta{parameters} in a \val\ (this is not a
+  single token but a parameter text as you'd use it with |\def|). They can not
+  be part of a \key-name (the names are indeed fixed). If you need a |#| in a
+  \val\ you'll need to double it just as you'd do in |\def|. Internally
+  \cs{ekvcompile} uses |\ekvparse| and no |\ekvset| variant, because of this the
+  \expnotation\ is handled slightly differently; in case you're using a
+  \key-name that starts with something that looks like \expnotation\ you'll have
+  to explicitly add an empty \expansion\ prefix.
+\end{function}
+\begin{example}
+    {Compile a \kv\ list into a macro that will quickly set that list}
+  Define the macro |\foo| to set some keys in the set |foo|. Since one key has a
+  strange name we need to add an empty \expansion\ prefix. Also we'd like |\foo|
+  to take one parameter which is part of the \val\ of |bar| (since the list is
+  parsed now and not when |\foo| is used we don't need to put braces around that
+  value, even if at use time |#1| contains commas):
+  \begin{enverb}[no-tcb]
+    \ekvcompile\foo#1{foo}
+      {
+         bar = #1baz
+        ,: part-of-key: name = strange
+        ,NoVal
+      }
+  \end{enverb}
+  After this using |\foo{VAL}| will be the same as but faster than
+  \begin{enverb}[no-tcb]
+    \ekvset{foo}{bar={VALbaz},part-of-key: name=strange,NoVal}
+  \end{enverb}
+\end{example}
+
+\subsection{Generic Key Parsing}\label{sec:expkv:parse}
+
+\begin{function}{\ekvparse}
+  \begin{syntax}
+    \cs{ekvparse}\marg{code1}\marg{code2}\kvarg
+  \end{syntax}
+  This macro parses the \kv\ list and provides \Nkey{}s to \meta{code1} as a
+  single argument and \Vkey{}s with their corresponding \val\ as two arguments
+  to \meta{code2}.
+
+  \cs{ekvparse} is fully expandable and alignment safe, meaning that you don't
+  have to take any extra precautions if it is used inside an alignment context
+  (like \LaTeXe's |tabular| environment) and any \key\ or \val\ can contain an
+  |&|. \cs{ekvparse} expands in exactly two steps, the result is provided inside
+  |\unexpanded| (so doesn't expand further in an |\edef| or |\expanded|
+  context).
+
+  \cs{ekvbreak}, \cs{ekvsneak}, \cs{ekvmorekv}, \emph{etc.}\ don't work
+  in \cs{ekvparse}. \cs{ekvparse} does not throw an error if multiple
+  unprotected equals signs are found (it just splits at the first), and doesn't
+  throw an error if a \key\ is empty. If something looks like \expnotation\ (has
+  a colon followed but not preceded by a space and with non-blank material
+  following it) it'll be parsed as such (which might throw errors due to
+  undefined \expansion-rules if that wasn't the intended input). If you for some
+  reason need to input a \key-name that would match that pattern you'll need to
+  precede it by \verb*|: | (an empty \expansion\ prefix).
+\end{function}
+\begin{example}
+    {Parse a \kv\ list and execute arbitrary code for each element using
+    \cs[no-index]{ekvparse}}
+  \begin{enverb}[no-tcb]
+    \ekvparse{\handlekey{S}}{\handlekeyval{S}}{foo = bar, key, baz={zzz}}
+  \end{enverb}
+  would be equivalent to
+  \begin{enverb}[no-tcb]
+    \handlekeyval{S}{foo}{bar}\handlekey{S}{key}\handlekeyval{S}{baz}{zzz}
+  \end{enverb}
+  and afterwards |\handlekey| and |\handlekeyval| would have to further handle
+  the keys. No such macros are contained in \expkv, but I hope you get the idea.
+  Because it expands in two steps and doesn't expand any further both
+  \begin{enverb}[no-tcb]
+    \expandafter\parse\expanded{\ekvparse\k\kv{foo = bar, key, baz={zzz}}}
+  \end{enverb}
+  and
+  \begin{enverb}[no-tcb]
+    \expandafter\expandafter\expandafter
+    \parse\ekvparse\k\kv{foo={bar}, key, baz = zzz}
+  \end{enverb}
+  expand to
+  \begin{enverb}[no-tcb]
+    \parse\kv{foo}{bar}\k{key}\kv{baz}{zzz}
+  \end{enverb}
+\end{example}
+
+\subsection{Other Useful Macros}
+
+\begin{function}{\ekvoptarg}
+  \begin{syntax}
+    \cs{ekvoptarg}\marg{next}\marg{default}
+  \end{syntax}
+  This macro will expandably check for a following optional argument in brackets
+  (|[]|). After the optional argument there has to be a mandatory one (or else
+  this might have unwanted side effects). The code in \meta{next} should expect
+  two arguments (or more), namely the processed optional argument and the
+  mandatory one that followed it. If there was an optional argument the result
+  will be \meta{next}\marg{optional}\meta{mandatory} (so the optional argument
+  will be wrapped in braces, the mandatory argument will be untouched). If there
+  was no optional argument the result will be
+  \meta{next}\marg{default}\marg{mandatory} (so the default will be used and the
+  mandatory argument will be wrapped in braces after it was read once -- if it
+  was already wrapped it is effectively unchanged).
+
+  \cs{ekvoptarg} expands in exactly two steps, grabs all the arguments only at
+  the second expansion step, and is alignment safe. It has its limitations
+  however. It can't tell the difference between |[| and |{[}|, so it doesn't
+  work if the mandatory argument is a single bracket. Also if the optional
+  argument should contain a nested closing bracket it has to be nested in braces
+  like so: |[{arg[u]ment}]| (or else the result would be |arg[u| with a trailing
+  |ment]|).
+\end{function}
+\begin{example}{Expandably search for an optional argument with a default value}
+  Say we have a macro that should take an optional argument defaulting to |1|,
+  we could program it like this:
+  \makeatletter
+  \begin{enverb}
+    \newcommand\foo{\ekvoptarg\@foo{1}}
+    \newcommand\@foo[2]{Mandatory: #2\par Optional: #1}
+    \foo{5}\par
+    \foo[4]{5}\par
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvoptargTF}
+  \begin{syntax}
+    \cs{ekvoptargTF}\marg{true}\marg{false}
+  \end{syntax}
+  This macro is similar to \cs{ekvoptarg} but will result in
+  \meta{true}\marg{optional}\meta{mandatory} or \meta{false}\marg{mandatory}
+  instead of placing a default value.
+
+  \cs{ekvoptargTF} expands in exactly two steps, grabs all the arguments only at
+  the second expansion step, and is alignment safe. It has the same limitations
+  as \cs{ekvoptarg}.
+\end{function}
+\begin{example}
+    {Expandably search for an optional argument and behave differently if it's
+    found or not}
+  Say we have a macro that should behave differently depending on whether there
+  was an optional argument or not. This could be done with:
+  \makeatletter
+  \begin{enverb}
+    \newcommand\foo{\ekvoptargTF\foo at a\foo at b}
+    \newcommand\foo at a[2]{Mandatory: #2\par Optional: #1}
+    \newcommand\foo at b[1]{Mandatory: #1\par No optional.}
+    \foo{5}\par
+    \foo[4]{5}\par
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekvcsvloop}
+  \begin{syntax}
+    \cs{ekvcsvloop}\marg{code}\marg{csv-list}
+  \end{syntax}
+  This loops over the comma separated items in \meta{csv-list} and, after
+  stripping spaces from either end of \meta{item} and removing at most one set
+  of outer braces, leaves |\unexpanded{|\meta{code}\marg{item}|}| for each list
+  item in the input stream. Blank elements are ignored (if you need a blank
+  element it should be given as \verb*|{ }|). It supports both active commas and
+  commas of category other. \cs{ekvcsvloop} is not alignment safe, but you could
+  make it so by nesting it in |\expanded| (since the braces around the argument
+  of |\expanded| will hide alignment characters from \TeX's parsing).
+\end{function}
+\begin{example}
+    {Loop over a comma separated list and execute arbitrary code for each
+    element}
+  The following splits a comma separated list and prints it in a typewriter font
+  with parentheses around each element:
+  \begin{enverb}
+    \newcommand*\myprocessor[1]{\texttt{(#1)}}
+    \ekvcsvloop\myprocessor{abc,def,ghi}\par
+    \ekvcsvloop\myprocessor{1,,2,,3,,4}\par
+  \end{enverb}
+\end{example}
+
+\begin{function}{\ekverr}
+  \begin{syntax}
+    \cs{ekverr}\marg{package}\marg{message}
+  \end{syntax}
+  This macro will throw an error fully expandably.\footnotemark\ The error
+  length is limited to a total length of 69~characters, and since ten characters
+  will be added for the formatting (\verb*|! | and \verb*| Error: |) that leaves
+  us with a total length of \meta{package} plus \meta{message} of 59~characters.
+  If the message gets longer \TeX\ will only display the first 69~characters and
+  append |\ETC.| to the end.
+
+  Neither \meta{package} nor \meta{message} expand any further. Also
+  \meta{package} must not contain an explicit |\par| token or the token
+  |\thanks at jfbu|. No such restriction applies to \meta{message}.
+
+  If |^^J| is set up as the |\newlinechar| (which is the case in \LaTeXe\ but
+  not in \hologo{plainTeX} by default) you can use that to introduce line breaks
+  in your error message. However that doesn't change the message length limit.
+\end{function}
+\footnotetext{The used mechanism was to the best of my knowledge first
+implemented by Jean-François Burnol.}
+After your own error message some further text will be placed. The formatting
+of that text will look good if |^^J| is the |\newlinechar|, else not so much.
+That text will read:
+\begin{verbatim}
+  ! Paragraph ended before \<an-expandable-macro>
+  completed due to above exception.  If the error
+  summary is  not comprehensible  see the package
+  documentation.
+  I will try to recover now.  If you're in inter-
+  active mode hit <return>  at the ? prompt and I
+  continue hoping recovery was complete.
+\end{verbatim}
+Any clean up has to be done by you, |\ekverr| will expand to nothing after
+throwing the error message.
+
+In \ConTeXt\ this macro works differently. While still being fully expandable,
+it doesn't have the character count limitation and doesn't impose restrictions
+on \meta{package}. It will not display the additional text and adding line
+breaks is not possible.
+\begin{example}{Expandably throw error messages using \cs[no-index]{ekverr}}
+  Say we set up a macro that takes as mandatory argument a simple equation which
+  must not be empty and if it's not empty it displays it and calculates the
+  result:
+  \begin{enverb}[no-tcb]
+    \newcommand*\mycalc[1]
+      {%
+        \the\numexpr
+        \if\relax\detokenize{#1}\relax
+          \ekverr{my}{Empty equation not allowed, leaving -2147483647}%
+          -2147483647%
+        \else
+          #1%
+        \fi
+        \relax
+      }
+    Using \mycalc{} wrong.
+  \end{enverb}
+  If that code gets executed the following will be the terminal output
+  \begin{verbatim}
+    Runaway argument?
+    ! my Error: Empty equation not allowed, leaving -2147483647
+    ! Paragraph ended before \<an-expandable-macro>
+    completed due to above exception.  If the error
+    summary is  not comprehensible  see the package
+    documentation.
+    I will try to recover now.  If you're in inter-
+    active mode hit <return>  at the ? prompt and I
+    continue hoping recovery was complete.
+    <to be read again>
+                       \par
+    l.17 Using \mycalc{}
+                         wrong.
+    ? 
+  \end{verbatim}
+  and the output would contain
+  \exres{Using -2147483647 wrong}
+  if we continued the \TeX\ run at the prompt.
+\end{example}
+
+
+\subsection{Other Macros}
+
+\begin{variable}{\ekvDate,\ekvVersion}
+  These two macros store \expkv's date and version.
+\end{variable}
+
+\begin{function}{\ekv at name,\ekv at name@set,\ekv at name@key}
+  \begin{syntax}
+    \cs{ekv at name}\marg{set}\marg{key}
+    \cs{ekv at name@set}\marg{set}
+    \cs{ekv at name@key}\marg{key}
+  \end{syntax}
+  The names of the macros storing the code of \Vkey{}s are stored in are built
+  with these macros. The name is built from two blocks, one that is formatting
+  the \set\ name, and on for formatting the \key\ name. To get the actual name
+  the argument to \cs{ekv at name@key} must be |\detokenize|d. Both blocks are put
+  together (with the necessary |\detokenize|) by \cs{ekv at name}. For \Nkey{}s an
+  additional |N| gets appended, so their name is
+  \cs{ekv at name}\marg{set}\marg{key}|N|.
+
+  You can use these macros to implement additional functionality or access
+  key-macros outside of \expkv, but \emph{don't} change them! \expkv\ relies on
+  their exact definitions internally.
+\end{function}
+\begin{example}{Directly call key code without parsing a \kv\ list}
+  Execute the key-macro of the \Nkey\ named |bar| in set |foo|:
+  \begin{enverb}[no-tcb]
+    \csname\ekv at name{foo}{bar}N\endcsname
+  \end{enverb}
+\end{example}
+
+
+\subsection{Examples}
+\subsubsection{Standard Use-Case\label{sec:expkv:standard}}
+
+\begin{example}{A \kv\ based replacement for \LaTeXe's \cs[no-index]{rule}}
+  Because I keep forgetting the correct order of \LaTeXe's |\rule| command I
+  want to create a \kv\ interface to it. For this I define the keys |ht| to
+  specify the rule's height, |wd| to specify its width, and to give a
+  displacement I use two keys (because who can remember whether the rule is
+  moved upwards or downwards?).
+
+  First the internals storing the values are initialised
+  \begin{enverb}[no-tcb,store]
+    \makeatletter
+    \newcommand*\myrule at ht{1ex}
+    \newcommand*\myrule at wd{0.1em}
+    \newcommand*\myrule at raise{\z@}
+  \end{enverb}
+  then the keys are defined. We could use |\dimen| registers instead of defining
+  macros, but macros have the advantage that the font dependent dimensions are
+  evaluated at use time.
+  \begin{enverb}[no-tcb,store]
+    \protected\ekvdef{myrule}{ht}{\def\myrule at ht{#1}}
+    \protected\ekvdef{myrule}{wd}{\def\myrule at wd{#1}}
+    \protected\ekvdef{myrule}{raise}{\def\myrule at raise{#1}}
+    \protected\ekvdef{myrule}{lower}{\def\myrule at raise{-#1}}
+  \end{enverb}
+  We also want a way to change the initial values without outputting a rule
+  (since there are unexpandable keys involved it's a good idea to define this
+  |\protected|)
+  \begin{enverb}[no-tcb,store]
+    \protected\ekvsetdef\myruleset{myrule}
+  \end{enverb}
+  and we need an actual frontend that does the job:
+  \begin{enverb}[no-tcb,store]
+    \newcommand*\myrule[1][]
+      {%
+        \begingroup
+          \myruleset{#1}%
+          \rule[\myrule at raise]{\myrule at wd}{\myrule at ht}%
+        \endgroup
+      }
+    \makeatother
+  \end{enverb}
+  Now we can use it:
+  \begin{enverb}[same-line=0.5,restore]
+    a\myrule\par
+    a\myrule[ht=2ex,lower=.5ex]\par
+    \myruleset{wd=5cm}
+    a\myrule
+  \end{enverb}
+\end{example}
+
+
+\subsubsection{An Expandable \kv\ Macro Using
+  \cs[no-index]{ekvsneak}\label{sec:expkv:sneak}}
+
+\begin{example}{An expandable \kv\ macro using \cs[no-index]{ekvsneak}}
+  Let's set up an expandable macro that uses a \kv\ interface. The problems
+  we'll face for this are:
+  \begin{enumerate}
+    \item ignoring duplicate keys
+    \item default values for keys which weren't used
+    \item providing the values as the correct argument to a macro (ordered)
+  \end{enumerate}
+
+  First we need to decide which \kv\ parsing macro we want to do this with,
+  \cs{ekvset} or \cs{ekvparse}. For this example we also want to show the usage
+  of \cs{ekvsneak}, hence we'll choose \cs{ekvset}. And we'll have to use
+  \cs{ekvset} such that it builds a parsable list for our macro internals. To
+  gain back control after \cs{ekvset} is done we have to put an internal of our
+  macro at the start of that list, so we use an internal key that uses
+  \cs{ekvsneakPre} after any user input.
+
+  To ignore duplicates will be easy if the value of the key used last will be
+  put first in the list, so we'll use \cs{ekvsneakPre} for the real values as
+  well. If for some reason we wanted a key for which the first usage was the
+  binding one we'd use \cs{ekvsneak} for that one.
+
+  Providing default values can be done in different ways. We'll use a simple
+  approach in which we'll just put the outcome of our keys if they were used
+  with default values before our end marker.
+
+  Ordering the keys can be done simply by searching for a specific token for
+  each argument (that token acts as a flag), so our sneaked out values will
+  include these specific tokens acting as markers.
+
+  Now we got an answer to each of our initial problems. Everything that's left
+  is deciding what our macro should actually do. For this example we'll define a
+  macro that calculates the sine of a number rounded to a specified precision.
+  The macro should also understand input in radian and degree, and we could also
+  decide to evaluate a different function. For the real hard part of this
+  (expandably calculating trigonometric functions) we'll use \pkg{xfp}.
+
+  First we set up our keys according to our earlier considerations and set up
+  the user facing macro |\sine|. The end marker of the parsing list will be a
+  |\sine at stop| token (which we don't need to define) and we put our default
+  values right before it. The user macro |\sine| uses |\ekvoptargTF| to check
+  for the optional argument short cutting a bit if no optional argument was
+  found. If you'd so prefer you could use \pkg{ltcmd}'s
+  |\NewExpandableDocumentCommand| to expandably get an optional argument as
+  well.
+  \begin{enverb}[no-tcb,store]
+    \RequirePackage{xfp}
+    \makeatletter
+    \ekvdef{sine}{f}{\ekvsneakPre{\f{#1}}}
+    \ekvdef{sine}{round}{\ekvsneakPre{\rnd{#1}}}
+    \ekvdefNoVal{sine}{degree}{\ekvsneakPre{\deg{d}}}
+    \ekvdefNoVal{sine}{radian}{\ekvsneakPre{\deg{}}}
+    \ekvdefNoVal{sine}{internal}{\ekvsneakPre{\sine at rnd}}
+    \newcommand*\sine{\ekvoptargTF\sine at args{\sine at final{sin}{d}{3}}}
+    \newcommand*\sine at args[2]
+      {\ekvset{sine}{#1,internal}\rnd{3}\deg{d}\f{sin}\sine at stop{#2}}
+  \end{enverb}
+
+  Now we need to define some internal macros to extract the value of each key's
+  last usage (remember that this will be the argument after the first matching
+  flag). For that we use one delimited macro per key.
+  \begin{enverb}[no-tcb,store]
+    \def\sine at rnd#1\rnd#2#3\sine at stop{\sine at deg#1#3\sine at stop{#2}}
+    \def\sine at deg#1\deg#2#3\sine at stop{\sine at f#1#3\sine at stop{#2}}
+    \def\sine at f#1\f#2#3\sine at stop{\sine at final{#2}}
+  \end{enverb}
+  After the macros |\sine at rnd|, |\sine at deg|, and |\sine at f| the macro
+  |\sine at final| will see
+  |\sine at final|\marg{f}\marg{degree/radian}\marg{round}\marg{num}. Now
+  |\sine at final| has to expandably deal with those arguments such that the
+  |\fpeval| macro of \pkg{xfp} gets the correct input. Luckily this part is
+  pretty easy after the build up we've done until now. In |\fpeval| the
+  trigonometric functions have names such as |sin| or |cos|, and the degree
+  taking alternatives just have an appended |d| (so |sind| or |cosd|). So
+  putting \meta{f} and \meta{degree/radian} together will form the correct
+  names.
+  \begin{enverb}[no-tcb,store]
+    \newcommand*\sine at final[4]{\fpeval{round(#1#2(#4),#3)}}
+    \makeatother
+  \end{enverb}
+  Let's give our macro a test:
+  \begin{enverb}[restore,inter=\def\RequirePackage#1{}]
+    \sine{60}\par
+    \sine[round=10]{60}\par
+    \sine[f=cos,radian]{pi}\par
+    \edef\myval{\sine[f=tan]{1}}\texttt{\meaning\myval}
+  \end{enverb}
+\end{example}
+
+Please note that setting this up a lot more user friendly is easily possible by
+utilizing \expkvc\ (see \autoref{sec:expkv-cs}).


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-main.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-opt.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-opt.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-opt.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,229 @@
+\latexekv\expkvo{-opt}
+
+\expkvo\ allows to parse \LaTeXe\ class and package options as \kv\ lists using
+sets of \expkv.
+
+With the 2021-05-01 release of \LaTeXe\ there were some very interesting changes
+to the package and class options code. It is now possible to use braces inside
+the options, and we can access options without them being preprocessed. As a
+result, some but not all restrictions were lifted from the possible option
+usage. What will still fail is things that aren't save from an |\edef| expansion
+(luckily, the \expnotation\ can be used to get around that as well). One feature
+of \expkvo\ that doesn't work any more is the possibility to parse the unused
+option list, because that one doesn't contain the full information any more.
+\expkvo\ will fall back to v0.1 if the kernel is older than 2021-05-01.
+
+Another very interesting change in \LaTeXe\ was the addition of \pkg{ltkeys} and
+its |\ProcessKeyOptions| with the possibility to parse future options with it
+instead of getting the dreaded |Option clash| error. The idea is brilliant and
+changes made in the 2022-10-22 version allow us to provide the same feature
+without having to hack any kernel internals, so starting with kernel version
+2022-11-01 \expkvo\ supports this as well.
+
+\expkvo\ shouldn't place any restrictions on the keys, historic shortcomings of
+the kernel cannot be helped though, so the supported things vary with the kernel
+version (see above). The one thing that \expkvo\ doesn't support, which \expkv\
+alone would, is active commas or equals signs. But there is no good reason why
+any of the two should be active in the preamble.
+
+You can use \LaTeXe's rollback support, so to load v0.1 explicitly use:
+\begin{enverb}[no-tcb]
+  \usepackage{expkv-opt}[=v0.1]
+\end{enverb}
+which will load the last version of \expkvo\ that doesn't use the raw option
+lists (this shouldn't be done by a package author, but only by a user on a
+single-document basis if there are some incompatibilities, which is unlikely).
+
+
+\subsection{Macros\label{sec:o:macros}}
+
+\subsubsection{Option Processors\label{sec:o:processors}}
+
+\expkvo's behaviour if it encounters a defined or an undefined \key\ depends on
+which list is being parsed and whether the current file is a class or not. Of
+course in every case a defined \key's callback will be invoked  but an
+additional action might be executed. For this reason the rule set of every macro
+will be given below the short description which list it will parse.
+
+During each of the processing macros the current list element (not processed in
+any way) is stored within the macro |\CurrentOption|.
+
+\begin{function}{\ekvoProcessOptions}
+  \begin{syntax}
+    \cs{ekvoProcessOptions}\marg{set}
+  \end{syntax}
+  This runs |\ekvoProcessGlobalOptions|, then |\ekvoProcessLocalOptions|, and
+  finally |\ekvoProcessFutureOptions|. If you're using |\ekvoUseUnknownHandlers|
+  it'll affect all three option processors. Else the respective default
+  unknown-rules are used.
+\end{function}
+
+\begin{function}{\ekvoProcessLocalOptions}
+  \begin{syntax}
+    \cs{ekvoProcessLocalOptions}\marg{set}
+  \end{syntax}
+  This parses the options which are directly passed to the current class or
+  package for an \expkv\ \set.
+\end{function}
+\expkvorules
+  {%
+     cd = {remove the option from the list of unused global options if the local
+       option list matches the option list of the main class and the unused
+       global options list is not empty; else \emph{nothing}}
+    ,cu = add the key to the list of unused global options (if the local option
+      list matches the option list of the main class)
+    ,pu = throw an error
+  }
+
+\begin{function}{\ekvoProcessGlobalOptions}
+  \begin{syntax}
+    \cs{ekvoProcessGlobalOptions}\marg{set}
+  \end{syntax}
+  In \LaTeXe\ the options given to |\documentclass| are global options. This
+  macro processes the global options for an \expkv\ \set.
+\end{function}
+\expkvorules{d = remove the option from the list of unused global options}
+
+\begin{function}{\ekvoProcessFutureOptions}
+  \begin{syntax}
+    \cs{ekvoProcessFutureOptions}\marg{set}
+  \end{syntax}
+  This parses the option list of every future call of the package with
+  |\usepackage| or similar with an \expkv\ \set, circumventing the
+  |Option clash| error that'd be thrown by \LaTeXe. It is only available for
+  kernel versions starting with 2022-11-01. It is mutually exclusive with
+  \LaTeXe's |\ProcessKeyOptions| (which ever comes last defines how future
+  options are parsed).
+\end{function}
+\expkvorules{u = throw an error}
+
+\begin{function}{\ekvoProcessOptionsList}
+  \begin{syntax}
+    \cs{ekvoProcessOptionsList}\meta{list}\marg{set}
+  \end{syntax}
+  Process the \kv\ list stored in the macro \meta{list}.
+\end{function}
+\expkvorules{}
+
+
+\subsubsection{Other Macros\label{sec:o:others}}
+
+\begin{function}{\ekvoUseUnknownHandlers}
+  \begin{syntax}
+    \cs{ekvoUseUnknownHandlers}\meta{cs_1}\meta{cs_2}\quad{\normalfont\itshape or}
+    \cs{ekvoUseUnknownHandlers}*
+  \end{syntax}
+  With this macro you can change the action \expkvo\ executes if it encounters
+  an undefined \key\ for the next (and only the next) list processing macro. The
+  macro \meta{cs_1} will be called if an undefined \Nkey\ is encountered and get
+  one argument being the \key\ (without being |\detokenize|d). Analogous the
+  macro \meta{cs_2} will be called if an undefined \Vkey\ was parsed and get two
+  arguments, the first being the \key\ (without being |\detokenize|d) and the
+  second the \val.
+  \par
+  If you use the starred variant, it'll not take further arguments. In this case
+  the undefined handlers defined via |\ekvdefunknown| and |\ekvdefunknownNoVal|
+  in the parsing set get used, and if those aren't available they'll simply do
+  nothing.
+\end{function}
+
+\begin{function}{\ekvoVersion,\ekvoDate}
+  These two macros store the version and date of the package.
+\end{function}
+
+
+\subsection{Examples}
+
+\begin{example}{A package using \expkvo}
+  Let's say we want to create a package that changes the way footnotes are
+  displayed in \LaTeX. For this it will essentially just redefine |\thefootnote|
+  and we'll call this package \pkg{ex-footnote}. First we report back which
+  package we are:
+  \begin{enverb}[no-tcb]
+    \ProvidesPackage{ex-footnote}[2020-02-02 v1 change footnotes]
+  \end{enverb}
+  Next we'll need to provide the options we want the package to have.
+  \begin{enverb}[no-tcb]
+    \RequirePackage{color}
+    \RequirePackage{expkv-opt}% also loads expkv
+    \ekvdef{ex-footnote}{color}{\def\exfn at color{#1}}
+    \ekvdef{ex-footnote}{format}{\def\exfn at format{#1}}
+  \end{enverb}
+  We can provide initial values just by defining the two macros storing the
+  value.
+  \begin{enverb}[no-tcb]
+    \newcommand*\exfn at color{}
+    \newcommand*\exfn at format{arabic}
+  \end{enverb}
+  Next we need to process the options given to the package. The package should
+  only obey options directly passed to it, so we're using
+  |\ekvoProcessLocalOptions| and |\ekvoProcessFutureOptions|:
+  \begin{enverb}[no-tcb]
+    \ekvoProcessLocalOptions {ex-footnote}
+    \ekvoProcessFutureOptions{ex-footnote}
+  \end{enverb}
+  Now everything that's still missing is actually changing the way footnotes
+  appear:
+  \begin{enverb}[no-tcb]
+    \renewcommand*\thefootnote
+      {%
+        \ifx\exfn at color\@empty
+          \csname\exfn at format\endcsname{footnote}%
+        \else
+          \textcolor{\exfn at color}{\csname\exfn at format\endcsname{footnote}}%
+        \fi
+      }
+  \end{enverb}
+  So the complete code of the package would look like this:
+  \begin{enverb}[no-tcb]
+    \ProvidesPackage{ex-footnote}[2020-02-02 v1 change footnotes]
+
+    \RequirePackage{color}
+    \RequirePackage{expkv-opt}% also loads expkv
+
+    \ekvdef{ex-footnote}{color}{\def\exfn at color{#1}}
+    \ekvdef{ex-footnote}{format}{\def\exfn at format{#1}}
+    \newcommand*\exfn at color{}
+    \newcommand*\exfn at format{arabic}
+
+    \ekvoProcessLocalOptions {ex-footnote}
+    \ekvoProcessFutureOptions{ex-footnote}
+
+    \renewcommand*\thefootnote
+      {%
+        \ifx\exfn at color\@empty
+          \csname\exfn at format\endcsname{footnote}%
+        \else
+          \textcolor{\exfn at color}{\csname\exfn at format\endcsname{footnote}}%
+        \fi
+      }
+  \end{enverb}
+  And it could be used with one (or thanks to |\ekvoProcessFutureOptions| all)
+  of the following lines:
+  \begin{enverb}[no-tcb]
+    \usepackage{ex-footnote}
+    \usepackage[format=fnsymbol]{ex-footnote}
+    \usepackage[color=green]{ex-footnote}
+    \usepackage[color=red,format=roman]{ex-footnote}
+  \end{enverb}
+\end{example}
+
+\begin{example}{Parsing the global options}
+  This document was compiled with the global options
+  \texttt{[\detokenize\expandafter\expandafter\expandafter{\csname @raw at classoptionslist\endcsname]}}
+  in use. If we define the following keys
+  \begin{enverb}[store,no-tcb]
+    \ekvdef{optexample}{exfoo}
+      {Global option \texttt{exfoo} got \texttt{\detokenize{#1}}.\par}
+    \ekvdefNoVal{optexample}{exbar}
+      {Global option \texttt{exbar} set.\par}
+  \end{enverb}
+  we can use those options to control the result of the following:
+  \begin{enverb}[restore,same-line=.55]
+    \ekvoProcessGlobalOptions{optexample}
+  \end{enverb}
+  Please note that under normal conditions
+  \cs[no-index]{ekvoProcessGlobalOptions} is only useable in the preamble; this
+  example is only for academic purposes, you'll not be able to reproduce this
+  with the exact code shown above.
+\end{example}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-opt.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-pop.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-pop.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-pop.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,439 @@
+\genericekv\expkvp{-pop}
+
+The \expkvp\ is mainly written to lay the basis for \expkvc's and \expkvd's
+key-defining front ends. Historically the two packages shared pretty similar
+code. To unify this and reduce the overall code amount some auxiliary package
+was originally planned, but then I realised that with little to no overhead
+(apart from documentation) this can also be provided to users. Well, and then I
+thought, why not make the whole thing expandable as well. And here we are.
+
+So what's the idea? This package provides a \textbf{p}refix \textbf{o}riented
+\textbf{p}arser\footnote{Naming packages is hard, especially when the name
+should fit a particular naming scheme. Big thanks to samcarter for helping
+me: \url{https://topanswers.xyz/tex?q=1985}. The author apologises that there is
+no \texttt{expkv-pnk}, \texttt{expkv-rok}, \texttt{expkv-jaz} or any other music
+themed name in \expkvbundle.} with two kinds of prefixes. The first is called a
+\prefix, of which an item can have arbitrary many, the second a \type, of which
+every item has only one. To distinguish the concept of an optional \prefix\ from
+the generic term \enquote{prefix} I'll use this formatting whenever the special
+kind of prefix is meant.
+
+Another peculiarity of \expkvp\ compared to the other packages in
+\expkvbundle\ is that it doesn't separate \Nkey{}s from \Vkey{}s as
+strictly. Instead a |NoVal|-marker is used as the value. If this is not what you
+want you can use \cs{ekvpValueAlwaysRequired} (see there).
+
+
+\subsection{Parsing Rules}
+
+A parser is processing only the \key\ of a \kv\ pair. The \key\ is split at
+spaces (braces might be lost by this process!). Each split off piece is checked
+whether it's a defined prefix. If it's a \type\ parsing of the \key\ stops and
+the remainder is considered a \meta{name}. If it's a \prefix\ it'll be recorded
+and parsing goes on. If it's neither parsing is also stopped (and the last
+parsed space delimited part is put back -- braces might've been lost at this
+step). If a no-type rule has been defined (\cs{ekvpDefNoType}) that one is
+executed else an error is thrown.
+
+The \prefix\ or \type\ has to match after being |\detokenize|d, whereas the
+\meta{name} will be unchanged (except for stripping off the prefixes). If only a
+\key\ is given (so no =\val\ used) the same is done, and instead of \val\ a
+no-value marker is used (if that accidentally ends up in the input stream this
+looks like this: \csname c\string_novalue\string_tl\endcsname; this is the same
+as the marker used by \pkg{expl3} for those familiar with it).
+
+A \prefix\ has two parts to it, a \meta{pre} and a \meta{post} code, whereas a
+\type\ only results in a \type-action (or the no-type action if that's defined
+and no \type\ found). The parsing result can also be seen in
+\autoref{fig:p:result}.
+
+\begin{figure}[b]
+  \centering
+  \def\plevel#1{\raisebox{1ex}{#1}}%
+  \def\ts#1{\textsubscript{$#1$}}%
+  \begingroup
+    \ttfamily
+    pre\ts1
+    \plevel
+      {%
+        pre\ts2
+        \plevel
+          {%
+            \ldots\space
+            \plevel
+              {%
+                pre\ts n
+                \plevel{\type-action}
+                post\ts n
+              }%
+            \ldots\space
+          }%
+        post\ts2
+      }%
+    post\ts{1}%
+  \endgroup
+  \caption
+    {%
+      Structure of a single \kv\ pair's parsing result with $n$~\prefix{}es%
+      \label{fig:p:result}%
+    }
+\end{figure}
+
+Please note that \expkvp's parsers are fully expandable as long as your
+\prefixes\ and \types\ are. Additionally \expkvp\ doesn't provide means to
+define parsers, \prefixes, or \types\ |\protected|. As a result, make sure
+you'll always call |\ekvpParse| inside of a |\protected| macro if you need
+anything that's unexpandable or else your code might not do what you intended
+since some states may not be updated when expandable code tries to access them.
+The macro |\ekvpProtect| can help to overcome this issue, but it's more of a
+last resort than a clean solution.
+
+\subsection{Defining Parsers}
+
+\begin{function}{\ekvpNewParser}
+  \begin{syntax}
+    \cs{ekvpNewParser}\marg{parser}
+  \end{syntax}
+  Defines a new parser called \meta{parser}. Every parser has to be defined this
+  way. Throws an error if the parser is already defined.
+\end{function}
+
+\begin{function}{\ekvpDefType}
+  \begin{syntax}
+    \cs{ekvpDefType}\marg{parser}\marg{type}\marg{code}
+  \end{syntax}
+  Defines a \type\ that is called \meta{type} for the parser \meta{parser}. If
+  the \type\ is parsed the \meta{code} will be used as a \type-action. Inside of
+  \meta{code} you can use |#1| to refer to the \meta{name} (the remainder of the
+  \key\ after stripping off all the prefixes), |#2| to use the unaltered \key,
+  and |#3| to access the \val\ which was given to your \key.
+\end{function}
+
+\begin{function}{\ekvpDefPrefix}
+  \begin{syntax}
+    \cs{ekvpDefPrefix}\marg{parser}\marg{prefix}\marg{pre}\marg{post}
+  \end{syntax}
+  Defines a \prefix\ that is called \meta{prefix} for the parser \meta{parser}.
+  If the \prefix\ is encountered the code in \meta{pre} will be put before the
+  \type-action and the code in \meta{post} will be put behind it.
+  If multiple \prefix{}es are used the \meta{pre} of the first will be put first
+  and the \meta{post} of the first will be put last. Inside of \meta{pre} and
+  \meta{post} |#1| is replaced with the found \type, |#2| the \meta{name}, and
+  |#3| the unaltered \key. If no valid type was found and the no-type rule
+  defined with \cs{ekvpDefNoType} is executed the argument |#1| will be empty.
+\end{function}
+
+\begin{function}{\ekvpDefAutoPrefix}
+  \begin{syntax}
+    \cs{ekvpDefAutoPrefix}\marg{parser}\marg{pre}\marg{post}
+  \end{syntax}
+  You can also define a \prefix-like rule that is executed on each element
+  automatically. So the \meta{pre} and \meta{post} code of this will be inserted
+  for every valid element of the \kv\ list. Just like for \cs{ekvpDefPrefix} you
+  can access the \type\ with |#1|, the \meta{name} with |#2|, and the unaltered
+  \key\ with |#3|.
+\end{function}
+
+\begin{function}{\ekvpDefPrefixStore}
+  \begin{syntax}
+    \cs{ekvpDefPrefixStore}\marg{parser}\marg{prefix}\meta{cs}\marg{pre}\marg{post}
+  \end{syntax}
+  This is a shortcut to define a \prefix\ named \meta{prefix} for \meta{parser}
+  that'll store \meta{pre} inside of \meta{cs} (which should be a single control
+  sequence) before the \type-action and afterwards store \meta{post} in it. Both
+  definitions (in \meta{pre} and in \meta{post}) are put inside |\ekvpProtect|.
+\end{function}
+
+\begin{function}{\ekvpDefPrefixLet}
+  \begin{syntax}
+    \cs{ekvpDefPrefixLet}\marg{parser}\marg{prefix}\meta{cs}\meta{pre}\meta{post}
+  \end{syntax}
+  This is similar to \cs{ekvpDefPrefixStore}, but instead of storing in the
+  \meta{cs} it'll be let to the single tokens specified by \meta{pre} and
+  \meta{post}. If either \meta{pre} or \meta{post} contains more than a single
+  token the remainder is put after the |\let| statement. Both assignments (in
+  \meta{pre} and in \meta{post}) are put inside |\ekvpProtect|.
+\end{function}
+
+\begin{function}{\ekvpLet}
+  \begin{syntax}
+    \cs{ekvpLet}\marg{parser_1}\marg{type}\marg{name_1}\oarg{parser_2}\marg{name_2}
+  \end{syntax}
+  Copies the definition of a \prefix\ or \type. The \meta{type} should be one of
+  |prefix|, or |type|. The \prefix\ or \type\ \meta{name_1} for \meta{parser_1}
+  will be let equal to the \prefix\ or \type\ \meta{name_2} of \meta{parser_2}.
+  If you omit the optional \meta{parser_2} it will default to \meta{parser_1}.
+\end{function}
+
+
+\subsection{Changing Default Behaviours}
+
+\begin{function}{\ekvpValueAlwaysRequired}
+  \begin{syntax}
+    \cs{ekvpValueAlwaysRequired}\marg{parser}
+  \end{syntax}
+  By default a special no-value marker will be provided for \val\ if no value
+  was given to a key. If this is used instead an error will be thrown that a
+  value is required.
+\end{function}
+
+\begin{function}{\ekvpDefNoValue}
+  \begin{syntax}
+    \cs{ekvpDefNoValue}\marg{parser}\marg{code}
+  \end{syntax}
+  This is a third alternative to the default behaviour and
+  \cs{ekvpValueAlwaysRequired}. With this macro you can stop normal parsing if
+  no value was specified and instead run \meta{code}. Inside of \meta{code} the
+  unprocessed \Nkey\ is available as |#1|. No further processing of this \kv\
+  list element takes place.
+\end{function}
+
+\begin{function}{\ekvpUseNoValueMarker}
+  \begin{syntax}
+    \cs{ekvpUseNoValueMarker}\marg{parser}\marg{marker}
+  \end{syntax}
+  This macro changes the no-value marker from the package default to
+  \meta{marker}. Note that macros like \cs{ekvpAssertValue} don't work with
+  markers different from the default one.
+\end{function}
+
+\begin{function}{\ekvpDefNoValuePrefix}
+  \begin{syntax}
+    \cs{ekvpDefNoValuePrefix}\marg{parser}\marg{pre}\marg{post}
+  \end{syntax}
+  It is also possible to handle \Nkey{}s as if this was some special \prefix.
+  So if a \Nkey\ is encountered you'll have \meta{pre} and \meta{post} put
+  before and behind the \type-action (as the outermost \prefix). The no-value
+  marker will be forwarded as \val. If you want to change a parser's marker and
+  use this you have to use \cs{ekvpUseNoValueMarker} before calling
+  \cs{ekvpDefNoValuePrefix}, and you must not use \cs{ekvpDefNoValue} or
+  \cs{ekvpValueAlwaysRequired} before using \cs{ekvpDefNoValuePrefix} (both
+  result in undefined behaviour).
+\end{function}
+
+\begin{function}{\ekvpDefNoType}
+  \begin{syntax}
+    \cs{ekvpDefNoType}\marg{parser}\marg{code}
+  \end{syntax}
+  This defines an action if no valid \type\ was found, otherwise this behaves
+  like \cs{ekvpDefType} with the same arguments |#1| (\meta{name}), |#2|
+  (unaltered \key), and |#3| (\val) in \meta{code}. If this isn't used for the
+  \meta{parser} instead an error will be thrown whenever no \type\ is found.
+\end{function}
+
+
+\subsection{Markers}
+
+\expkvp\ will place three markers for each list element that was parsed and
+defines an auxiliary to gobble up to that marker. After each marker an
+additional group is placed containing the current list element (excluding the
+\val). The gobblers gobble that group as well. Those markers are:
+
+\begin{function}{\ekvpEOP,\ekvpGobbleP}
+  Is placed after all the \prefix{}es' \meta{pre} code, directly before the
+  \type-action.
+\end{function}
+
+\begin{function}{\ekvpEOT,\ekvpGobbleT}
+  Is placed after the \type-action, directly before the last \prefix's
+  \meta{post} code.
+\end{function}
+
+\begin{function}{\ekvpEOA,\ekvpGobbleA}
+  Is placed at the end of the complete result of the current element, so after
+  all the \prefix{}es' \meta{post} code.
+\end{function}
+
+
+\subsection{Helpers in Actions}
+
+\begin{function}{\ekvpIfNoVal}
+  \begin{syntax}
+    \cs{ekvpIfNoVal}\marg{arg}\marg{true}\marg{false}
+  \end{syntax}
+  This will expand to \meta{true} if the \meta{arg} is the special no-value
+  marker, otherwise \meta{false} is left in the input stream.
+\end{function}
+
+\begin{function}{\ekvpAssertIf,\ekvpAssertIfNot}
+  \begin{syntax}
+    \cs{ekvpAssertIf}\oarg{marker}\marg{if}\marg{message}
+  \end{syntax}
+  This macro will run the \TeX-if test specified by \meta{if} (should expand to
+  any \TeX-style if, e.g., \cs[no-index]{iftrue} or
+  \cs[no-index]{ifx}\meta{A}\meta{B}). If the test is true everything's fine,
+  else an error message is thrown using \meta{message} followed by the current
+  element and everything up to \meta{marker} is gobbled (\meta{marker} can be
+  any of |EOT|, which is the default, |EOP|, or |EOA|). The |Not| variant will
+  invert the logic, so if the \TeX-style if is true this will throw the error.
+\end{function}
+
+\begin{function}{\ekvpAssertTF,\ekvpAssertTFNot}
+  \begin{syntax}
+    \cs{ekvpAssertTF}\oarg{marker}\marg{if}\marg{message}
+  \end{syntax}
+  This is pretty similar to \cs{ekvpAssertIf}, but \meta{if} should be a test
+  that uses its first argument if it's true and its second otherwise (so an
+  error is thrown if the second argument is used, nothing happens otherwise).
+  The |Not| variant is again inversed.
+\end{function}
+
+\begin{function}{\ekvpAssertValue,\ekvpAssertNoValue}
+  \begin{syntax}
+    \cs{ekvpAssertValue}\oarg{marker}\marg{arg}
+  \end{syntax}
+  Asserts that \meta{arg} is not the no-value marker (\cs{ekvpAssertValue}) or
+  is the no-value marker (\cs{ekvpAssertNoValue}), otherwise throws an error and
+  gobbles everything up to \meta{marker} (like \cs{ekvpAssertIf}).
+\end{function}
+
+\begin{function}{\ekvpAssertOneValue,\ekvpAssertTwoValues}
+  \begin{syntax}
+    \cs{ekvpAssertOneValue}\oarg{marker}\marg{arg}
+  \end{syntax}
+  Asserts that \meta{arg} contains exactly one or two values (which could both
+  be either single tokens or braced groups -- spaces between the two values in
+  the \cs{ekvpAssertTwoValues} case are ignored), if the number of values
+  doesn't match an error is thrown and everything up to \meta{marker} gobbled.
+\end{function}
+
+\begin{function}{\ekvpProtect}
+  \begin{syntax}
+    \cs{ekvpProtect}\marg{code}
+  \end{syntax}
+  This macro protects \meta{code} from further expanding in every context a
+  |\protected| macro wouldn't expand. It needs at least two steps of expansion.
+  When a |\protected| macro would expand this will remove the braces around
+  \meta{code} and \TeX\ will process \meta{code} the same way it normally would.
+  After the first step of expansion it'll leave two macros, and after each
+  further full expansion these two macros stay there. Since \expkvp\ offers no
+  method to define \prefixes\ or \types\ |\protected| you can instead use this
+  macro. But if your parser needs any assignments you should nest the
+  |\ekvpParse| call in a |\protected| macro anyway.
+\end{function}
+
+\subsection{Using Parsers}
+
+\begin{function}{\ekvpParse}
+  \begin{syntax}
+    \cs{ekvpParse}\marg{parser}\kvarg
+  \end{syntax}
+  Parses the \kv\ list as defined for \meta{parser}. This expands in exactly two
+  steps, and returns inside of |\unexpanded|, so doesn't expand any further in
+  an |\edef| or |\expanded|. After the two steps it'll directly leave the code
+  as though every \prefix's \meta{pre} and \meta{post} code and the \type-action
+  were input directly along with the different markers.
+\end{function}
+
+\subsection{The Boring Macros}
+Just for the sake of completeness.
+\begin{function}{\ekvpDate,\ekvpVersion}
+  Store the date and version, respectively.
+\end{function}
+
+\subsection{Examples}
+\begin{example}{Defining a parser similar to \expkvd}
+  \ekvset{enverb}{store,no-tcb}%
+  Let's define a parser that is similar to \expkvd's |\ekvdefinekeys|. First we
+  define a new parser named |exdef|:
+  \begin{enverb}
+    \ekvpNewParser{exdef}
+  \end{enverb}
+  We'll need to provide our prefixes, |long| and |protected|. The following
+  initialises them and defines their action.
+  \begin{enverb}
+    \newcommand*\exLong{}
+    \newcommand*\exProtected{}
+    \ekvpDefPrefixLet{exdef}{long}\exLong\long\empty
+    \ekvpDefPrefixLet{exdef}{protected}\exProtected\protected\empty
+  \end{enverb}
+  Now we define a few types, I'll go with |noval|, |store|, and |code| for
+  starters. We exploit the fact that |\ekvdef| and |\ekvdefNoVal| will expand
+  the first argument, so we can simply store the set name in a macro.
+  \begin{enverb}
+    \ekvpDefType{exdef}{code}
+      {%
+        \ekvpAssertValue{#3}%
+        \exProtected\exLong\ekvdef\exSetName{#1}{#3}%
+      }
+    \ekvpDefType{exdef}{noval}
+      {%
+        \ekvpAssertValue{#3}%
+        \ekvpAssertIfNot{\ifx\exLong\long}{`long' not accepted}%
+        \exProtected\ekvdefNoVal\exSetName{#1}{#3}%
+      }
+    \ekvpDefType{exdef}{store}
+      {%
+        \ekvpAssertOneValue{#3}%
+        \ifdefined#3\else
+          \let#3\empty
+        \fi
+        \protected\exLong\ekvdef\exSetName{#1}{\edef#3{\unexpanded{##1}}}%
+      }
+  \end{enverb}
+  Now we need a user facing macro that puts the pieces together (this uses
+  |\NewDocumentCommand| instead of |\newcommand| because the former defines
+  macros |\protected|).
+  \begin{enverb}
+    \NewDocumentCommand\exdefinekeys{m +m}
+      {\def\exSetName{#1}\ekvpParse{exdef}{#2}}
+  \end{enverb}
+  Now we got that sorted so we can use our little parser:
+  \ekvset{enverb}{no-store,undo-no-tcb}%
+  \begin{enverb}[restore]
+    \newif\ifbar
+    \exdefinekeys{exampleset}
+      {
+         long store foo = \myfoo
+        ,protected noval bar = \bartrue
+        ,code baz = baz was called with \detokenize{#1}
+      }
+    \ekvset{exampleset}{foo=Foobar,bar,baz=\empty}
+    \ifbar bar was true so: \myfoo\fi
+  \end{enverb}
+\end{example}
+
+\begin{example}{Visualising the expandability of \cs[no-index]{ekvpParse}}
+  \ekvset{enverb}{store,no-tcb}%
+  With this example we want to take a closer look at the expansion of
+  |\ekvpParse|. So please bear with me if this doesn't make much sense
+  otherwise. One of the issues is that \prefixes\ are a somewhat unordered
+  concept, and only \types\ must come last. We could juggle with flags (an
+  expandable data-storage, see \autoref{sec:c:flags}) to overcome this somehow
+  just to define some pseudo-syntax here, but I guess that's not worth it.
+  Anyhow, here goes nothing.\par
+  First we need a parser
+  \begin{enverb}
+    \ekvpNewParser{exexp}
+  \end{enverb}
+  and a \prefix. We could define one that ensures the name starts of with
+  a letter. We also want each element to start a new line, which we do using an
+  auto prefix.
+  \begin{enverb}
+    \newcommand\ifletter{}
+    \long\def\ifletter#1#2\stop{\ifcat a\noexpand#1}
+    \ekvpDefPrefix{exexp}{letter}
+      {\ekvpAssertIf{\ifletter#2\stop}{not a letter}}
+      { (really a letter)}
+    \ekvpDefAutoPrefix{exexp}{\noindent}{\par}
+  \end{enverb}
+  Finally we define a \type\ and a |NoType| rule:
+  \begin{enverb}
+    \ekvpDefType{exexp}{*}{$#1\cdot#3 = \the\numexpr#1*#3\relax$}
+    \ekvpDefNoType{exexp}{the #3th letter is #1}
+  \end{enverb}
+  Now we want to see whether the thing is expandable:
+  \ekvset{enverb}{no-store,undo-no-tcb}%
+  \begin{enverb}[restore,below]
+    \raggedright
+    \edef\foo{\ekvpParse{exexp}{letter e = 5, * 4 = \empty3}}
+    1st full expansion
+    \texttt{\meaning\foo}\par
+    \medskip
+    \edef\foo{\foo}
+    2nd full expansion
+    \texttt{\meaning\foo}\par
+    \medskip
+    \foo
+  \end{enverb}
+\end{example}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/pkg-pop.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-enverb.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-enverb.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-enverb.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,348 @@
+\RequirePackage{expkv-def}
+
+\ExplSyntaxOn
+\cs_new_eq:NN \enverb at count \tl_count:n
+\cs_set:Npx \enverb at othercr { \char_generate:nn {13} {12} }
+\ExplSyntaxOff
+%% key setup
+\ekvdefinekeys{enverb}
+  {
+     boolTF auto-ignore    = \enverb at ifautoignore
+    ,initial auto-ignore
+    ,protected code ignore = \let\enverb at ifautoignore\@secondoftwo
+    ,eint more-ignore      = \enverb at moreignore
+    ,initial more-ignore   = 2
+    ,also eint ignore      = \enverb at ignore
+    ,boolTF same-line = \enverb at ifsameline
+    ,unknown-choice same-line =
+      \let\enverb at ifsameline\@firstoftwo\edef\enverb at codeshare{\unexpanded{#1}}
+    ,initial same-line = 0.75
+    ,invboolTF other-line = \enverb at ifsameline
+    ,nmeta below = {same-line=false, no-aboveskip, no-belowskip}
+    ,nmeta undo-below = {same-line=true, aboveskip, belowskip}
+    ,store same-line-lst = \enverb at options@lst at same
+    ,store same-line-tcb = \enverb at options@tcb at same
+    ,initial same-line-lst = {aboveskip=0pt,belowskip=0pt}
+    ,initial same-line-tcb = {nobeforeafter,box align=center}
+    ,store other-line-lst = \enverb at options@lst at other
+    ,store other-line-tcb = \enverb at options@tcb at other
+    ,meta slst = same-line-lst={#1}
+    ,meta stcb = same-line-tcb={#1}
+    ,meta olst = other-line-lst={#1}
+    ,meta otcb = other-line-tcb={#1}
+    ,store lst = \enverb at options@lst
+    ,store tcb = \enverb at options@tcb
+    ,long store bol = \enverb at bol@content
+    ,long store eol = \enverb at eol@content
+    ,einitial eol   = \enverb at othercr
+    ,boolTF no-lst  = \enverb at ifno@lst
+    ,also nmeta no-lst = below
+    ,boolTF no-tcb  = \enverb at ifno@tcb
+    ,also nmeta no-tcb = below
+    ,nmeta undo-no-tcb = {no-tcb=false, undo-below}
+    ,store inter   = \enverb at inter
+    ,data  gappend = \enverb at append
+    ,dataT pre-tcb = \enverb at pretcb
+    ,store after   = \enverb at after
+    ,nmeta store   = gappend=\enverb at store
+    ,noval no-store = \let\enverb at append\@secondoftwo
+    ,nmeta restore = {pre-tcb=\enverb at store,after=\enverb at clear@store}
+    ,code aboveskip = \edef\enverb at aboveskip{\vskip\unexpanded{#1}\relax}
+    ,code belowskip = \edef\enverb at belowskip{\vskip\unexpanded{#1}\relax}
+    ,default aboveskip = \medskipamount
+    ,default belowskip = \medskipamount
+    ,initial aboveskip
+    ,initial belowskip
+    ,noval no-aboveskip = \let\enverb at aboveskip\@empty
+    ,noval no-belowskip = \let\enverb at belowskip\@empty
+  }
+\protected\long\ekvsetdef\enverbsetup{enverb}
+\protected\def\enverb at clear@store{\global\let\enverb at store\@empty}
+\enverb at clear@store
+
+%% start of nested environments
+\newcommand\enverb at tcb
+  {%
+    \expanded
+      {%
+        \noexpand\begin{exresult}%
+          [{%
+            \enverb at options@tcb,%
+            \enverb at ifsameline\enverb at options@tcb at same\enverb at options@tcb at other
+          }]%
+      }%
+      {\linewidth\enverb at ifsameline{-\enverb at codeshare\linewidth}{}}%
+  }
+\newcommand\enverb at lst
+  {%
+    \expanded
+      {%
+        \noexpand\begin{lstlisting}%
+          [{%
+            \enverb at options@lst,%
+            \enverb at ifsameline\enverb at options@lst at same\enverb at options@lst at other
+          }]%
+      }%
+  }
+
+%% auxiliary error function
+\newcommand\enverb at error[1]
+  {%
+    \GenericError
+      {(enverb)\@spaces\@spaces\@spaces\@spaces}%
+      {Environment enverb error: #1}%
+      {Just use it correctly!}%
+      {Read the sources.}%
+  }
+
+%% setup for weird category code regime
+\begingroup
+\lccode`\~=`\^^M
+\catcode`\:=13
+\lccode`\:=`\ % <- space
+\catcode`\;=13
+\lccode`\;=`\^^I % <- tab
+\lowercase{\endgroup
+%% code for spaces and CR
+\def\enverb at body@space{}%
+\def\enverb at body@tab{}%
+\def\enverb at body@newline#1~%
+  {\enverb at ifnotend{#1}{\enverb at bol\unexpanded{#1}\enverb at eol~}}%
+%% activate the category code regime of the body
+\protected\def\enverb at body@setup
+  {%
+    \let\enverb at collected@body\@empty
+    \let\do\@makeother\dospecials
+    \catcode`\^^M=13 \let~\enverb at body@newline
+    \catcode`\   =13 \let:\enverb at body@space
+    \catcode`\^^I=13 \let;\enverb at body@tab
+    \let\enverb at bol\relax
+    \let\enverb at eol\relax
+  }
+%% check for optional argument
+\newcommand\enverb at search@oarg at a
+  {%
+    \ifx:\next
+      \ifenverb at firsteol
+      \else
+        \enverb at body@add{:}%
+      \fi
+      \let\next\enverb at search@oarg at b
+    \else
+      \ifx~\next
+        \ifenverb at firsteol
+          \enverb at firsteolfalse
+        \else
+          \enverb at body@add{~}%
+        \fi
+        \let\next\enverb at search@oarg at b
+      \else
+        \ifx[\next\@gobble]%
+          \let\next\enverb at oarg
+        \else
+          \ifenverb at firsteol
+            \let\next\enverb at body@after at begin
+          \else
+            \let\next\enverb at body
+          \fi
+        \fi
+      \fi
+    \fi
+    \next
+  }
+%% start body collection
+\newcommand\enverb at body
+  {\edef\enverb at collected@body{\iffalse}\fi\expandafter~\enverb at collected@body}
+%% check the line after an oarg
+\def\enverb at body@after at oarg#1~%
+  {\enverb at ensure@blank{#1}{closing bracket}\enverb at body}
+%% check the line after the \begin statement
+\def\enverb at body@after at begin#1~%
+  {\enverb at ensure@blank{#1}{\string\begin}\enverb at body}
+}
+%% quick check for empty line
+\newcommand\enverb at ensure@blank[2]
+  {%
+    \expandafter\enverb at ifempty\expanded{{#1}}{}%
+      {%
+        \expanded{%
+        \noexpand\enverb at error
+          {%
+            Line after #2 not empty.\noexpand\MessageBreak
+            Contains: \detokenize\expandafter{\romannumeral`\^^@#1}%
+          }%
+        }%
+      }%
+  }
+%% quick check for empty argument
+\newcommand\enverb at ifempty[1]
+  {%
+    \enverb at ifempty@\enverb at ifempty@A#1\enverb at ifempty@B.\enverb at ifempty@true
+      \enverb at ifempty@A\enverb at ifempty@B
+  }
+\def\enverb at ifempty@#1\enverb at ifempty@A\enverb at ifempty@B#2#3{#3}
+\def\enverb at ifempty@true\enverb at ifempty@A\enverb at ifempty@B#1#2{#1}
+\newcommand\enverb at gadd[2]{\xdef#1{\unexpanded\expandafter{#1#2}}}
+\newcommand\enverb at body@add[1]
+  {%
+    \edef\enverb at collected@body
+      {\unexpanded\expandafter{\enverb at collected@body#1}}%
+  }
+% start of environment `enverb'
+\newcommand\enverb
+  {%
+    \begingroup
+      \def\tmp{enverb}%
+      \expandafter
+    \endgroup
+    \expandafter\enverb at ifnotend@setup at perhaps\expanded
+      {{\string{\@currenvir\string}}}%
+    \begingroup
+    \enverb at body@setup
+    \enverb at firsteoltrue
+    \let\enverb at collected@oarg\@empty
+    \enverb at search@oarg
+  }
+\newif\ifenverb at firsteol
+\newcommand\enverb at search@oarg{\futurelet\next\enverb at search@oarg at a}
+\newcommand\enverb at search@oarg at b{\expandafter\enverb at search@oarg\@gobble}
+\newcommand\enverb at oarg{\endgroup\enverb at oarg@}
+\NewDocumentCommand\enverb at oarg@{O{}}
+  {%
+    \edef\enverb at collected@oarg{\unexpanded{#1}}%
+    \begingroup
+    \enverb at body@setup
+    \enverb at body@after at oarg
+  }
+\def\enverb at ifnotend#1%
+  {%
+    \def\enverb at ifnotend##1%
+      {%
+        \enverb at ifnotend@
+          ##1\enverb at mark\enverb at ifnotend@maybe
+          #1\enverb at mark\@thirdofthree
+          \enverb at stop
+      }%
+    \def\enverb at ifnotend@##1#1##2\enverb at mark##3##4\enverb at stop{##3{##1}{##2}}%
+  }
+\expandafter\enverb at ifnotend\expanded{{\expandafter\@gobble\string\\end}}
+\newcommand\enverb at ifnotend@maybe[2]
+  {\expandafter\enverb at ifnotend@perhaps\expandafter{\romannumeral`\^^@#2}{#1}}
+\newcommand\enverb at ifnotend@setup at perhaps[1]
+  {%
+    \def\enverb at ifnotend@perhaps##1%
+      {%
+        \enverb at ifnotend@perhaps@\enverb at mark##1\enverb at mark\enverb at ifnotend@end
+          \enverb at mark#1\enverb at mark\@thirdofthree
+          \enverb at stop
+      }%
+    \def\enverb at ifnotend@perhaps@
+        ##1\enverb at mark#1##2\enverb at mark##3##4\enverb at stop
+      {##3{##2}}%
+  }
+\providecommand\@thirdofthree[3]{#3}
+\outer\def\myabsolutestop{\stop}
+\newcommand\enverb at ifnotend@end[3]
+  {%
+    \iffalse{\fi}%
+    \enverb at ensure@blank{#1}{\string\end}%
+    \expanded
+      {%
+        \endgroup
+        \enverbsetup
+          {\unexpanded\expandafter{\enverb at collected@oarg}}%
+        \noexpand\enverb at output
+          {\unexpanded\expandafter{\enverb at collected@body}}%
+      }%
+      {#2}%
+    \expandafter\end\expandafter{\@currenvir}%
+  }
+\long\def\enverb at output#1#2%
+  {%
+    \enverb at ifautoignore
+      {\enverb at setup@ignore{\enverb at count{#2}+\enverb at moreignore}}%
+      {\enverb at setup@ignore\enverb at ignore}%
+    \edef\enverb at line##1\enverb at eol
+      {%
+        \noexpand\detokenize{##1}%
+        \noexpand\unexpanded{\unexpanded\expandafter{\enverb at eol@content}}%
+      }%
+    \edef\enverb at collected@body{#1}%
+    \expanded
+      {\unexpanded{\enverb at append\enverb at gadd\@gobble}\expandafter}%
+      \expandafter{\enverb at collected@body}%
+    \par
+    \enverb at aboveskip
+    \enverb at ifno@lst{}%
+      {%
+        \enverb at ifsameline
+          {\noindent\begin{minipage}[c]{\enverb at codeshare\linewidth}}%
+          {}%
+        \begingroup
+          \everyeof{\noexpand}%
+          \expandafter
+        \endgroup
+        \scantokens\expanded
+          {{%
+            \noexpand\csname enverb at lst\endcsname
+              \enverb at othercr
+              \enverb at collected@body
+            \string\end{lstlisting}\enverb at othercr
+          }}%
+        \enverb at ifsameline{\end{minipage}}{}%
+      }%
+    \enverb at inter
+    \enverb at ifno@tcb{}%
+      {%
+        \begingroup
+          \everyeof{\noexpand}%
+          \newlinechar=\endlinechar
+          \expandafter
+        \endgroup
+        \scantokens\expanded
+          {{%
+            \noexpand\csname enverb at tcb\endcsname
+              \enverb at pretcb{\unexpanded\expandafter}%
+              \enverb at collected@body
+            \noexpand\end{exresult}%
+          }}%
+      }%
+    \par
+    \enverb at belowskip
+    \enverb at after
+    \@endpetrue
+  }
+\providecommand\@firstofnine[9]{#1}
+\newcommand\enverb at setup@ignore[1]
+  {\expandafter\enverb at setup@ignore@\the\numexpr#1\relax;\enverb at line}
+\def\enverb at setup@ignore@#1;#2%
+  {%
+    \ifnum#1>9
+      \expandafter\@firstoftwo
+    \else
+      \expandafter\@secondoftwo
+    \fi
+    {\expandafter\enverb at setup@ignore@\the\numexpr#1-8;{\@firstofnine{#2}}}%
+    {%
+      \let\enverb at bol@gobble\@empty % just so that renewcommand doesn't go nuts
+      \expanded
+        {%
+          \unexpanded{\renewcommand\enverb at bol@gobble}\ifnum#1>\z@[#1]\fi
+            {%
+              \noexpand\unexpanded
+                {\unexpanded\expandafter{\enverb at bol@content}}%
+              \unexpanded{#2}%
+            }%
+          \unexpanded{\def\enverb at bol##1\enverb at eol}%
+            {%
+              \noexpand\unexpanded
+                {\unexpanded\expandafter{\enverb at bol@content}}%
+              \unexpanded{\expandafter\enverb at ifempty\expanded}{{##1}}%
+                {\noexpand\enverb at line}%
+                {\noexpand\enverb at bol@gobble}%
+              ##1\unexpanded{\enverb at eol}%
+            }%
+        }%
+    }%
+  }
+\let\endenverb\@empty


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-enverb.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-examples.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-examples.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-examples.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,16 @@
+\makeatletter
+\newcounter{example}[section]
+\newcommand*\example[1]
+  {%
+    \par\smallskip
+    \refstepcounter{example}%
+    \addcontentsline{exs}{example}{#1}%
+    \noindent\textit{Example:} \ignorespaces
+  }
+\newcommand*\l at example{\@dottedtocline{0}{1.5em}{2.3em}}
+\newcommand\listofexamples
+  {%
+    \addsec{List of Examples}%
+    \@starttoc{exs}%
+  }
+\makeatother


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-examples.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-l3doctweaks.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-l3doctweaks.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-l3doctweaks.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,39 @@
+\ExplSyntaxOn
+\cs_new_protected:Npn \__expkvdoc_patchfootnote:% >>=
+  {
+    \cs_set:Npx \footnote
+      {
+        \exp_not:n { \ClassError {expkvdoc} {Footnote~ in~ function} {} }
+        \exp_not:o { \footnote }
+      }
+  }% =<<
+\AddToHook{env/function/begin}{\__expkvdoc_patchfootnote:}
+
+\group_begin:
+\cs_set_protected:Npn \__expkvdoc_tmp:nN #1#2
+  {
+    \__kernel_tl_set:Nx #2 { \tl_to_str:n {#1} }
+    \tl_replace_all:Nxn #2 { \c_underscore_str } { / }
+    \tl_remove_all:Nx   #2 { \c_backslash_str }
+    \tl_put_left:Nn #2 { doc/function// }
+  }
+\cs_if_eq:NNTF \__expkvdoc_tmp:nN \__codedoc_get_hyper_target:nN
+  {
+    \cs_gset:Npn \__codedoc_get_hyper_target:nN #1#2
+      {
+        \__kernel_tl_set:Nx #2 { \tl_to_str:n {#1} }
+        \tl_replace_all:Nxn #2 { \c_underscore_str } { / }
+        \tl_remove_all:Nx   #2 { \c_backslash_str }
+        \tl_put_left:Nx #2 { doc/function/ \g__expkvdoc_module_str / }
+      }
+  }
+  {
+    \ClassWarning{expkvdoc}
+      {
+        Didn't~ patch~ l3doc's~ hyper~ targets.~ You~ might~ get~ duplicate~
+        labels.
+      }
+  }
+\group_end:
+
+\ExplSyntaxOff


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-l3doctweaks.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-logos.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-logos.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-logos.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,107 @@
+\definecolor{ekvred}{HTML}{9F393D}
+\colorlet{ekvgrey}{black!75}
+\makeatletter
+\newcommand*\kvstyle%>>=
+  {\normalfont\rmfamily\bfseries\color{ekvred}}%=<<
+\newcommand*\expFormat % used for the title only >>=
+  {%
+    {%
+      \rmfamily
+      \bfseries
+      {\color{ekvgrey}e\kern-.05em x\kern-.05em}%
+      \lower.493ex\hbox{{\color{ekvgrey}P}}%
+    }%
+  }%=<<
+\newcommand\expnotation% >>=
+  {%
+    \begingroup
+    \BeginAccSupp{ActualText=exp|notation,E=expansion-notation}%
+      \rmfamily
+      \bfseries
+      \color{ekvgrey}%
+      e\kern-.05em x\kern-.05em%
+      \lower.493ex\hbox{{\color{ekvgrey}P}}%
+      \kern-.05em:%
+      \kern.05em\textsc{notation}%
+    \EndAccSupp{}%
+    \endgroup
+  }% =<<
+\newcommand\expkvLogoFormat[1]% >>=
+  {%
+    \begingroup
+      \rmfamily
+      \bfseries
+      {\color{ekvgrey}e\kern-.05em x\kern-.05em}%
+      \lower.493ex\hbox{{\color{ekvgrey}P}\kern-.1em{\color{ekvred}k}}%
+      \kern-.18em{\color{ekvred}v}%
+      \IfValueT{#1}
+        {%
+          \begingroup
+            \color{ekvgrey}%
+            \kern.05em\rule[-.1ex]{.08em}{1.2ex}%
+            \kern.05em\textsc{#1}%
+          \endgroup
+        }%
+    \endgroup
+  }% =<<
+\NewDocumentCommand \expkvLogo { o }%>>=
+  {%
+    \mbox
+      {%
+        \BeginAccSupp{ActualText=expkv\IfValueT{#1}{-#1}}%
+          \ifodd\ekvdoc at insection
+            \href{https://gitlab.com/islandoftex/texmf/expkv-bundle}%
+              {\expkvLogoFormat{#1}}%
+          \else
+            \hyperref[sec:expkv\IfValueT{#1}{-#1}]{\expkvLogoFormat{#1}}%
+          \fi
+        \EndAccSupp{}%
+      }%
+  }%=<<
+\newcommand*\expkv%>>=
+  {%
+    \texorpdfstring
+      {\expkvLogo}
+      {expkv}%
+  }%=<<
+\newcommand*\expkvpkg[1]%>>=
+  {%
+    \texorpdfstring
+      {\expkvLogo[{#1}]}%
+      {expkv-#1}%
+  }%=<<
+\newcommand*\expkvbundle% >>=
+  {%
+    \texorpdfstring
+      {\begingroup\chardef\ekvdoc at insection1 \expkvpkg{bundle}\endgroup}%
+      {\expkvpkg{bundle}}%
+  }% =<<
+\newcommand*\expkvc{\expkvpkg{cs}}
+\newcommand*\expkvd{\expkvpkg{def}}
+\newcommand*\expkvo{\expkvpkg{opt}}
+\newcommand*\expkvp{\expkvpkg{pop}}
+\ExplSyntaxOn
+\cs_new_protected:Npn \pkglogo #1%>>=
+  {
+    \texorpdfstring
+      {
+        \mbox
+          {
+            \BeginAccSupp{ActualText=#1}
+            \rmfamily
+            \str_case:nn {#1}
+              {
+                {yax}
+                  {
+                    Y\kern-.1em
+                    \raise.15em\hbox{\scshape a}
+                    \kern-.1em \lower.15em\hbox{X}%
+                  }
+              }
+            \EndAccSupp{}
+          }
+      }
+      {#1}
+  }%=<<
+\newcommand*\yax{\pkglogo{yax}}
+\ExplSyntaxOff


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-logos.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-lst.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-lst.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-lst.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,218 @@
+\def\mylstwd{.55em}
+\lstdefinelanguage{expkv}[primitive]{TeX}
+  {
+    ,moretexcs=[2]% e-TeX
+      {
+        expanded,
+        numexpr,
+        protected,
+        unexpanded,
+        ifdefined,
+        detokenize,
+      }
+    ,moretexcs=[3]% plain/LaTeX/ConTeXt
+      {
+        approx,
+        begin,end,
+        cdot,
+        emph,empty,
+        item,
+        LaTeX,
+        makeatletter,makeatother,multicolumn,
+        newcommand,renewcommand,newdimen,newif,newcount,NewDocumentCommand,
+        usepackage,RequirePackage,ProvidesPackage,
+        raggedright,
+        rule,
+        space,stop,
+        smallskip,medskip,bigskip,
+        TeX,
+        textit,texttt,
+        usepackage,
+        usemodule,
+        @gobble, at gobbletwo, at firstofone, at empty,
+        ExplSyntaxOn,ExplSyntaxOff,
+      }
+    ,moretexcs=[4]% used packages
+      {
+        % xfp
+        fpeval,
+        % keyval
+        setkeys,
+        % kvsetkeys
+        kvsetkeys,
+        % color
+        textcolor,
+        % yax
+        defactiveparameter,storevalue,setparameterlist,
+        % graphics
+        includegraphics,
+      }
+    ,moretexcs=[5]% expkv macros
+      {
+        ekvdef,ekvdefNoVal,%
+        ekvlet,ekvletNoVal,ekvletkv,ekvletkvNoVal,%
+        ekvdefunknown,ekvdefunknownNoVal,%
+        ekvletunknown,ekvletunknownNoVal,%
+        ekvredirectunknown,ekvredirectunknownNoVal,%
+        ekvset,ekvsetSneaked,%
+        ekvsetdef,ekvsetSneakeddef,ekvsetdefSneaked,%
+        ekvcompile,%
+        ekvparse,%
+        ekvVersion,ekvDate,%
+        ekvifdefined,ekvifdefinedNoVal,ekvifdefinedset,%
+        ekvbreak,ekvbreakPreSneak,ekvbreakPostSneak,%
+        ekvsneak,ekvsneakPre,%
+        ekvchangeset,%
+        ekvmorekv,%
+        ekvoptarg,ekvoptargTF,%
+        ekvcsvloop,%
+        ekverr,%
+        ekv at name,%
+      }
+    ,moretexcs=[6]% expkv-cs macros
+      {
+        ekvcSecondaryKeys,%
+        ekvcSplit,ekvcSplitAndForward,ekvcSplitAndUse,%
+        ekvcHash,ekvcHashAndForward,ekvcHashAndUse,%
+        ekvcValue,ekvcValueFast,ekvcValueSplit,ekvcValueSplitFast,%
+        ekvcChange,%
+        ekvcPass,%
+      }
+    ,moretexcs=[7]% expkv-def macros
+      {
+        ekvdefinekeys
+      }
+    ,moretexcs=[8]% expkv-pop macros
+      {
+        ekvpNewParser,
+        ekvpDefType,
+        ekvpDefPrefix,ekvpDefAutoPrefix,ekvpDefPrefixStore,ekvpDefPrefixLet,
+        ekvpLet,
+        ekvpValueAlwaysRequired,ekvpDefNoValue,ekvpUseNoValueMarker,
+        ekvpDefNoValuePrefix,ekvpDefNoType,ekvpDefNoValue,
+        ekvpEOP,ekvpGobbleP,ekvpEOT,ekvpGobbleT,ekvpEOA,ekvpGobbleA,
+        ekvpIfNoVal,
+        ekvpAssertIf,ekvpAssertIfNot,ekvpAssertTF,ekvpAssertTFNot,
+        ekvpAssertValue,ekvpAssertNoValue,
+        ekvpAssertOneValue,ekvpAssertTwoValues,
+        ekvpParse,
+      }
+    ,moretexcs=[9]% expkv-opt macros
+      {
+        ekvoProcessOptions,%
+        ekvoProcessLocalOptions,ekvoProcessGlobalOptions,%
+        ekvoProcessFutureOptions,ekvoProcessOptionsList,%
+        ekvoUseUnknownHandlers,%
+        ekvoVersion,ekvoDate,%
+      }
+    ,alsoletter={_:}
+    ,moretexcs=[10]% expl3
+      {
+        cs_new_eq:NN,
+        tl_count_tokens:n,
+      }
+  }
+\colorlet{codeparam}{cyan!65!black}
+\lstdefinestyle{expkv}
+  {
+     texcsstyle=*[5]{\bfseries\color{ekvred}}  % expkv
+    ,texcsstyle=*[6]{\color{ekvred}}           % expkv-cs
+    ,texcsstyle=*[7]{\color{ekvred}}           % expkv-def
+    ,texcsstyle=*[8]{\color{ekvred}}           % expkv-pop
+    ,texcsstyle=*[9]{\color{ekvred}}           % expkv-opt
+  }
+\lstdefinestyle{expkv-cs}
+  {
+     texcsstyle=*[5]{\color{ekvred}}           % expkv
+    ,texcsstyle=*[6]{\bfseries\color{ekvred}}  % expkv-cs
+    ,texcsstyle=*[7]{\color{ekvred}}           % expkv-def
+    ,texcsstyle=*[8]{\color{ekvred}}           % expkv-pop
+    ,texcsstyle=*[9]{\color{ekvred}}           % expkv-opt
+  }
+\lstdefinestyle{expkv-def}
+  {
+     texcsstyle=*[5]{\color{ekvred}}           % expkv
+    ,texcsstyle=*[6]{\color{ekvred}}           % expkv-cs
+    ,texcsstyle=*[7]{\bfseries\color{ekvred}}  % expkv-def
+    ,texcsstyle=*[8]{\color{ekvred}}           % expkv-pop
+    ,texcsstyle=*[9]{\color{ekvred}}           % expkv-opt
+  }
+\lstdefinestyle{expkv-pop}
+  {
+     texcsstyle=*[5]{\color{ekvred}}           % expkv
+    ,texcsstyle=*[6]{\color{ekvred}}           % expkv-cs
+    ,texcsstyle=*[7]{\color{ekvred}}           % expkv-def
+    ,texcsstyle=*[8]{\bfseries\color{ekvred}}  % expkv-pop
+    ,texcsstyle=*[9]{\color{ekvred}}           % expkv-opt
+  }
+\lstdefinestyle{expkv-opt}
+  {
+     texcsstyle=*[5]{\color{ekvred}}           % expkv
+    ,texcsstyle=*[6]{\color{ekvred}}           % expkv-cs
+    ,texcsstyle=*[7]{\color{ekvred}}           % expkv-def
+    ,texcsstyle=*[8]{\color{ekvred}}           % expkv-pop
+    ,texcsstyle=*[9]{\bfseries\color{ekvred}}  % expkv-opt
+  }
+\lstdefinestyle{expkv-all}
+  {
+     texcsstyle=*[5]{\bfseries\color{ekvred}}  % expkv
+    ,texcsstyle=*[6]{\bfseries\color{ekvred}}  % expkv-cs
+    ,texcsstyle=*[7]{\bfseries\color{ekvred}}  % expkv-def
+    ,texcsstyle=*[8]{\bfseries\color{ekvred}}  % expkv-pop
+    ,texcsstyle=*[9]{\bfseries\color{ekvred}}  % expkv-opt
+  }
+\lstset
+  {
+    ,language=expkv
+    ,style=expkv
+    ,flexiblecolumns=false
+    ,basewidth=\mylstwd
+    %,basicstyle=\fontfamily{lmtt}\selectfont
+    %,basicstyle=\fontfamily{GoMono-TLF}\selectfont%\itshape
+    %,basicstyle=\fontfamily{jkp}\selectfont%\itshape
+    %,basicstyle=\fontfamily{jkptt}\selectfont%\itshape
+    ,basicstyle=\fontfamily{txtt}\selectfont%\itshape
+    ,texcsstyle=*[1]{\bfseries\color{ekvgrey}} % primitives
+    ,texcsstyle=*[2]{\bfseries\color{ekvgrey}} % e-TeX
+    ,texcsstyle=*[3]{\bfseries\color{ekvgrey}} % plain/LaTeX macros
+    ,texcsstyle=*[4]{\bfseries\color{ekvgrey}} % macros of other packages
+    ,texcsstyle=*[10]{\bfseries\color{ekvgrey}} % macros of expl3
+    ,commentstyle=\color[gray]{0.4}
+    ,literate=
+              {\{} {{\CodeUpBf\{}}{1}
+              {\}} {{\CodeUpBf\}}}{1}
+              {$}  {{\CodeUpBf\$}}{1}
+              {[}  {{\CodeUp[}}{1}
+              {]}  {{\CodeUp]}}{1}
+              {(}  {{\CodeUp(}}{1}
+              {)}  {{\CodeUp)}}{1}
+              {*}  {{$*$}}{1}
+              {1}  {{\CodeUp{1}}}{1}
+              {2}  {{\CodeUp{2}}}{1}
+              {3}  {{\CodeUp{3}}}{1}
+              {4}  {{\CodeUp{4}}}{1}
+              {5}  {{\CodeUp{5}}}{1}
+              {6}  {{\CodeUp{6}}}{1}
+              {7}  {{\CodeUp{7}}}{1}
+              {8}  {{\CodeUp{8}}}{1}
+              {9}  {{\CodeUp{9}}}{1}
+              {0}  {{\CodeUp{0}}}{1}
+              {##} {{\CodeColored{codeparam}{1}{\#}}}{1}
+              {##1}{{\CodeColored{codeparam}{2}{\#1}}}{2}
+              {##2}{{\CodeColored{codeparam}{2}{\#2}}}{2}
+              {##3}{{\CodeColored{codeparam}{2}{\#3}}}{2}
+              {##4}{{\CodeColored{codeparam}{2}{\#4}}}{2}
+              {##5}{{\CodeColored{codeparam}{2}{\#5}}}{2}
+              {##6}{{\CodeColored{codeparam}{2}{\#6}}}{2}
+              {##7}{{\CodeColored{codeparam}{2}{\#7}}}{2}
+              {##8}{{\CodeColored{codeparam}{2}{\#8}}}{2}
+              {##9}{{\CodeColored{codeparam}{2}{\#9}}}{2}
+              {<key>}{{$\langle$}key{$\rangle$}}{5}
+              {<set>}{{$\langle$}set{$\rangle$}}{5}
+              {<set1>}{{$\langle$}set1{$\rangle$}}{6}
+              {<set2>}{{$\langle$}set2{$\rangle$}}{6}
+    %,literate=*{<key>}{\key}{4}{<set>}{\set}{4}
+  }
+\newcommand*\CodeColored[3]{\textcolor{#1}{\makebox[\dimexpr\mylstwd*#2]{#3}}}
+\newcommand*\CodeUpBf[1]{\makebox[\mylstwd]{\textup{\textbf{#1}}}}
+\newcommand*\CodeUp[1]{\makebox[\mylstwd]{\textup{#1}}}


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-lst.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-noidx.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-noidx.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-noidx.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,50 @@
+\DoNotIndex{\-,\:,\\,\~}
+\DoNotIndex{\advance,\AtEndOfPackage}
+\DoNotIndex{\ClassError,\CurrentOption}
+\DoNotIndex{\DeclareCurrentRelease,\DeclareOption,\DeclareRelease}
+\DoNotIndex{\directlua,\dimexpr}
+\DoNotIndex{\def,\edef,\,,\=,\begingroup,\catcode,\chardef,\csname,\endcsname}
+\DoNotIndex{\endgroup,\endinput,\errmessage,\expandafter,\input,\let,\long}
+\DoNotIndex{\gdef,\global,\glueexpr,\gtoksapp,\gtokspre}
+\DoNotIndex{\hbox}
+\DoNotIndex{\IfFormatAtLeastTF}
+\DoNotIndex{\key}
+\DoNotIndex{\lccode,\lowercase}
+\DoNotIndex{\MessageBreak}
+\DoNotIndex{\N,\newcommand,\newcount,\newtoks,\number,\numexpr}
+\DoNotIndex{\PackageError,\PackageWarning,\ProcessOptions}
+\DoNotIndex{\requestedLaTeXdate,\RequirePackage}
+\DoNotIndex{\setbox}
+\DoNotIndex{\@classoptionslist,\@clsextension,\@currext,\@currname,\@empty}
+\DoNotIndex{\@firstofone,\@firstoftwo,\@gobble,\@gobblethree,\@gobbletwo}
+\DoNotIndex{\@ifstar,\@onlypreamble,\@raw at classoptionslist,\@secondoftwo}
+\DoNotIndex{\@unprocessedoptions,\@unusedoptionlist}
+\DoNotIndex{\pkgcls at parse@date at arg,\pkgcls at targetdate,\pkgcls at targetlabel}
+\DoNotIndex{\protected,\ProvidesFile,\ProvidesPackage,\relax,\space}
+\DoNotIndex{\^,\@,\unexpanded,\string,\expanded,\detokenize,\meaning}
+\DoNotIndex{\lastnamedcs,\romannumeral,\z@}
+\DoNotIndex{\noexpand,\normalexpanded,\normalunexpanded}
+\DoNotIndex{\par,\protect}
+\DoNotIndex{\the,\toksapp,\tokspre}
+\DoNotIndex{\unprotect,\unless,\usemodule}
+\DoNotIndex{\V}
+\DoNotIndex{\writestatus}
+\DoNotIndex{\xdef}
+\DoNotIndex{\Z,\z}
+\DoNotIndex{\ifcsname}
+\DoNotIndex{\if}
+\DoNotIndex{\ifdefined}
+\DoNotIndex{\ifodd}
+\DoNotIndex{\iftrue}
+\DoNotIndex{\ifx}
+\DoNotIndex{\iffalse}
+\DoNotIndex{\ifnum}
+\DoNotIndex{\else}
+\DoNotIndex{\fi}
+\@gobble\fi % ignoring \ifx etc., but only one \fi
+\@gobble\fi % ignoring \ifx etc., but only one \fi
+\@gobble\fi % ignoring \ifx etc., but only one \fi
+\@gobble\fi % ignoring \ifx etc., but only one \fi
+\@gobble\fi % ignoring \ifx etc., but only one \fi
+\@gobble\fi % ignoring \ifx etc., but only one \fi
+\@gobble\fi % ignoring \ifx etc., but only one \fi


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-noidx.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-prefixes.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-prefixes.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-prefixes.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,36 @@
+\AddToHook{env/syntax/begin}{\let\prefixes\prefixline}
+\newcount\prefixes at num
+\newcommand\enfprefix{\textcolor{black}}
+\newcommand\allprefix{\textcolor{gray}}
+\newcommand\notprefix{\textcolor{red!80!black}}
+\@ifdefinable\prefixline
+  {\protected\def\prefixline{\hfill\afterassignment\prefixes@\prefixes at num=}}
+\ExplSyntaxOn
+\newcommand\prefixes at place[1]
+  {%
+    \numexpr
+      \int_mod:nn { \int_div_truncate:nn \prefixes at num {#1} } { 10 }
+    \relax
+  }
+\ExplSyntaxOff
+\newcommand\printprefix[2]
+  {%
+    \ifcase\prefixes at place{#1}\or
+      \enfprefix{#2}\or
+      \allprefix{#2}\or
+      \notprefix{#2}\fi
+  }
+\protected\def\prefixes@
+  {%
+    \ifnum\prefixes at num>10
+      \printprefix{1000}{new}
+      \printprefix {100}{also}
+      \printprefix  {10}{protected}
+      \printprefix   {1}{long}%
+    \else
+      \ifcase\prefixes at num\or
+        \enfprefix{long}\or
+        \allprefix{long}\or
+        \notprefix{long}\fi
+    \fi
+  }


Property changes on: trunk/Master/texmf-dist/doc/latex/expkv-bundle/preamble-prefixes.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-bundle.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-bundle.ins	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-bundle.ins	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,101 @@
+\iffalse meta-comment
+
+Project: expkv-bundle Copyright (C) 2020-2023 Jonathan P. Spratte
+
+This work  may be  distributed and/or  modified under  the conditions  of the
+LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+(at your option) any later version.  The latest version of this license is in
+the file:
+
+  http://www.latex-project.org/lppl.txt
+
+-----------------------------------------------------------------------------
+
+This file is part of the  "expkv bundle" (The Work in LPPL)  and all files in
+that bundle must be distributed together.
+
+The released version of this bundle is available from CTAN.
+
+-----------------------------------------------------------------------------
+
+The development version of the bundle can be found at
+
+   https://gitlab.com/islandoftex/texmf/expkv-bundle
+
+for those people who are interested.
+
+-----------------------------------------------------------------------------
+
+\fi
+
+\input l3docstrip.tex
+\askforoverwritefalse
+\preamble
+
+----------------------------------------------------------------
+expkv-bundle -- an expandable key=val implementation and friends
+E-mail: jspratte at yahoo.de
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+----------------------------------------------------------------
+
+Copyright (C) 2020-2023 Jonathan P. Spratte
+
+This  work may be  distributed and/or  modified under  the conditions  of the
+LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+(at your option) any later version.  The latest version of this license is in
+the file:
+
+  http://www.latex-project.org/lppl.txt
+
+This work is "maintained" (as per LPPL maintenance status) by
+  Jonathan P. Spratte.
+
+This work consists of the files  expkv-bundle.ins
+                                 expkv.dtx
+                                 expkv-cs.dtx
+                                 expkv-def.dtx
+                                 expkv-opt.dtx
+                                 expkv-pop.dtx
+and the derived files            expkv.sty
+                                 expkv.tex
+                                 t-expkv.tex
+                                 expkv-cs.sty
+                                 expkv-cs.tex
+                                 t-expkv-cs.tex
+                                 expkv-def.sty
+                                 expkv-def.tex
+                                 t-expkv-def.tex
+                                 expkv-opt.sty
+                                 expkv-pop.sty
+                                 expkv-pop.tex
+                                 t-expkv-pop.tex
+
+as well as any documentation files shipped with it.
+
+\endpreamble
+\postamble
+\endpostamble
+
+\keepsilent
+
+\ifdefined\expkvDocNoGenerate\endinput\fi
+
+\generate
+  {%
+    \file  {expkv.sty}    {\from{expkv.dtx}    {pkg}}%
+    \file  {expkv.tex}    {\from{expkv.dtx}    {tex}}%
+    \file{t-expkv.tex}    {\from{expkv.dtx}    {ctx}}%
+    \file  {expkv-cs.sty} {\from{expkv-cs.dtx} {pkg}}%
+    \file  {expkv-cs.tex} {\from{expkv-cs.dtx} {tex}}%
+    \file{t-expkv-cs.tex} {\from{expkv-cs.dtx} {ctx}}%
+    \file  {expkv-def.sty}{\from{expkv-def.dtx}{pkg}}%
+    \file  {expkv-def.tex}{\from{expkv-def.dtx}{tex}}%
+    \file{t-expkv-def.tex}{\from{expkv-def.dtx}{ctx}}%
+    \file  {expkv-pop.sty}{\from{expkv-pop.dtx}{pkg}}%
+    \file  {expkv-pop.tex}{\from{expkv-pop.dtx}{tex}}%
+    \file{t-expkv-pop.tex}{\from{expkv-pop.dtx}{ctx}}%
+    \file  {expkv-opt.sty}{\from{expkv-opt.dtx}{pkg}}%
+  }
+
+\endbatchfile

Added: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-cs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-cs.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-cs.dtx	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,1748 @@
+% \iffalse meta-comment
+%
+% File: expkv-cs.dtx Copyright (C) 2020-2023 Jonathan P. Spratte
+%
+% This work  may be  distributed and/or  modified under  the conditions  of the
+% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+% (at your option) any later version.  The latest version of this license is in
+% the file:
+%
+%   http://www.latex-project.org/lppl.txt
+%
+% ------------------------------------------------------------------------------
+%
+%<*driver>^^A>>=
+\def\expkvDocNoGenerate{}
+\input expkv-bundle.ins
+\generate{\file{expkv-cs.sty}{\from{expkv-cs.dtx}{pkg}}}
+\generate{\file{expkv-cs.tex}{\from{expkv-cs.dtx}{tex}}}
+\generate{\file{t-expkv-cs.tex}{\from{expkv-cs.dtx}{ctx}}}
+\endbatchfile
+%</driver>^^A=<<
+% \fi
+%
+% \section{\expkvc}
+%^^A the LaTeX package >>=
+% \subsection{The \LaTeX\ Package}
+% Just like for \expkv\ we provide a small \LaTeX\ package that sets up things
+% such that we behave nicely on \LaTeX\ packages and files system. It'll
+% |\input| the generic code which implements the functionality.
+% \gobbledocstriptag
+%<*pkg>
+%    \begin{macrocode}
+\RequirePackage{expkv-pop}
+\def\ekvc at tmp
+  {%
+    \ProvidesFile{expkv-cs.tex}%
+      [%
+        \ekvcDate\space v\ekvcVersion\space
+        define expandable key=val macros using expkv%
+      ]%
+  }
+\input{expkv-cs.tex}
+\ProvidesPackage{expkv-cs}%
+  [%
+    \ekvcDate\space v\ekvcVersion\space
+    define expandable key=val macros using expkv%
+  ]
+%    \end{macrocode}
+% \gobbledocstriptag
+%</pkg>
+%^^A=<<
+%^^A the ConTeXt module >>=
+% \subsection{The \ConTeXt\ module}
+% \gobbledocstriptag
+%<*ctx>
+%    \begin{macrocode}
+\writestatus{loading}{ConTeXt User Module / expkv-cs}
+\usemodule[expkv-pop]
+\unprotect
+\input expkv-cs.tex
+\writestatus{loading}
+  {ConTeXt User Module / expkv-cs / Version \ekvcVersion\space loaded}
+\protect\endinput
+%    \end{macrocode}
+% \gobbledocstriptag
+%</ctx>
+%^^A=<<
+%^^A main file >>=
+% \subsection{The Generic Code}
+% The rest of this implementation will be the generic code.
+% \gobbledocstriptag
+%<*tex>
+%
+% Load \expkv\ if the package didn't already do so -- since \expkv\ has
+% safeguards against being loaded twice this does no harm and the overhead
+% isn't that big. Also we reuse some of the internals of \expkv\ to save us from
+% retyping them.
+%    \begin{macrocode}
+\input expkv-pop
+%    \end{macrocode}
+%
+% We make sure that \file{expkv-cs.tex} is only input once:
+%    \begin{macrocode}
+\expandafter\ifx\csname ekvcVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+%    \end{macrocode}
+%
+% \begin{macro}{\ekvcVersion,\ekvcDate}
+% We're on our first input, so lets store the version and date in a macro.
+%    \begin{macrocode}
+\def\ekvcVersion{1.3}
+\def\ekvcDate{2023-01-23}
+%    \end{macrocode}
+% \end{macro}
+%
+% If the \LaTeX\ format is loaded we want to be a good file and report back who
+% we are, for this the package will have defined |\ekvc at tmp| to use
+% |\ProvidesFile|, else this will expand to a |\relax| and do no harm.
+%    \begin{macrocode}
+\csname ekvc at tmp\endcsname
+%    \end{macrocode}
+%
+% Store the category code of |@| to later be able to reset it and change it to
+% 11 for now.
+%    \begin{macrocode}
+\expandafter\chardef\csname ekvc at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+%    \end{macrocode}
+% |\ekvc at tmp| will be reused later, but we don't need it to ever store
+% information long-term after \expkvc\ was initialized.
+%
+% \begin{macro}[internal]{\ekvc at tripledots}
+%   This macro just serves as a marker for a comparison to allow the syntax
+%   for the unknown key handlers.
+%    \begin{macrocode}
+\edef\ekvc at tripledots{\detokenize{...}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at keycount}
+%   We'll need to keep count how many keys must be defined for each macro in the
+%   |split| variants.
+%    \begin{macrocode}
+\newcount\ekvc at keycount
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at long,\ekvc at any@long}
+%   Some macros will have to be defined long. These two will be let to |\long|
+%   when this should be the case.
+%    \begin{macrocode}
+\let\ekvc at long\ekv at empty
+\let\ekvc at any@long\ekv at empty
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at ifdefined}
+%   We want to test whether a macro is already defined. This test checks for a
+%   defined macro that isn't |\relax|.
+%    \begin{macrocode}
+\long\def\ekvc at ifdefined#1%
+  {%
+    \ifdefined#1%
+      \ifx\relax#1%
+        \ekv at fi@gobble
+      \fi
+      \@firstofone
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at ekvset@pre at expander,
+%     \ekvc at ekvset@pre at expander@a,
+%     \ekvc at ekvset@pre at expander@b
+%   }
+%   This macro expands |\ekvset| twice so that the first two steps of expansion
+%   don't have to be made every time the \expkvc\ macros are used. We have to do
+%   a little magic trick to get the macro parameter |#1| for the macro
+%   definition this is used in, even though we're calling |\unexpanded|. We do
+%   that by splitting the expanded |\ekvset| at some marks and place |##1| in
+%   between. At this spot we also add |\ekv at alignsafe| and |\ekv at endalignsafe|
+%   to ensure that macros created with \expkvc\ are alignment safe.
+%    \begin{macrocode}
+\def\ekvc at ekvset@pre at expander#1%
+  {%
+    \expandafter\ekvc at ekvset@pre at expander@a\ekvset{#1}\ekvc at stop\ekvc at stop
+  }
+\def\ekvc at ekvset@pre at expander@a
+  {%
+    \expandafter\ekvc at ekvset@pre at expander@b
+  }
+\def\ekvc at ekvset@pre at expander@b#1\ekvc at stop#2\ekvc at stop
+  {%
+    \ekv at unexpanded\expandafter{\ekv at alignsafe}%
+    \ekv at unexpanded{#1}##1\ekv at unexpanded{#2}%
+    \ekv at unexpanded\expandafter{\ekv at endalignsafe}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcSplitAndUse}
+%   The first user macro we want to set up can be reused for
+%   \cs[no-index]{ekvcSplitAndForward} and \cs[no-index]{ekvcSplit}. We'll split
+%   this one up so that the test whether the macro is already defined doesn't
+%   run twice.
+%    \begin{macrocode}
+\protected\long\def\ekvcSplitAndUse#1#2%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcSplitAndUse@#1{}{#2}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvcSplitAndUse@}
+%   The actual macro setting up things. We need to set some variables, forward
+%   the key list to |\ekvc at SetupSplitKeys|, and afterwards define the front
+%   facing macro to call |\ekvset| and put the initials and the argument sorting
+%   macro behind it. The internals |\ekvc at any@long|, |\ekvc at initials| and
+%   |\ekvc at keycount| will be set correctly by |\ekvc at SetupSplitKeys|.
+%    \begin{macrocode}
+\protected\long\def\ekvcSplitAndUse@#1#2#3%
+  {%
+    \edef\ekvc at set{\string#1}%
+    \ekvc at SetupSplitKeys{#3}%
+    \ekvc at helpers@needed
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded\expandafter
+              {\csname ekvc at split@\the\ekvc at keycount\endcsname}%
+            \ekv at unexpanded\expandafter{\ekvc at initials{}#2}%
+          }%
+      }%
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded{#2}%
+            \ekv at unexpanded\expandafter{\ekvc at initials}%
+          }%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\ekvcSplitAndForward}
+%   This just reuses |\ekvcSplitAndUse@| with a non-empty second argument,
+%   resulting in that argument to be called after the splitting.
+%    \begin{macrocode}
+\protected\long\def\ekvcSplitAndForward#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcSplitAndUse@#1{{#2}}{#3}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcSplit}
+%   The first half is just |\ekvcSplitAndForward| then we define the macro to
+%   which the parsed key list is forwarded. There we need to allow for up to
+%   nine arguments.
+%    \begin{macrocode}
+\protected\long\def\ekvcSplit#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@secondoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {%
+        \expandafter
+        \ekvcSplitAndUse@\expandafter#1\csname ekvc@\string#1\endcsname{#2}%
+        \ifnum\ekvc at keycount<1
+          \ekvc at any@long\expandafter\def\csname ekvc@\string#1\endcsname{#3}%
+        \else
+          \ifnum\ekvc at keycount>9
+            \ekvc at err@toomany{#1}%
+            \let#1\ekvc at undefined
+          \else
+            \ekvcSplit at build@argspec
+            \ekvc at any@long\expandafter
+            \def\csname ekvc@\string#1\expandafter\endcsname\ekvc at tmp{#3}%
+          \fi
+        \fi
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvcSplit at build@argspec,\ekvcSplit at build@argspec@}
+%    \begin{macrocode}
+\protected\def\ekvcSplit at build@argspec
+  {%
+    \begingroup
+      \edef\ekvc at tmp
+        {\endgroup\def\ekv at unexpanded{\ekvc at tmp}{\ekvcSplit at build@argspec@{1}}}%
+    \ekvc at tmp
+  }
+\def\ekvcSplit at build@argspec@#1%
+  {%
+    \ifnum#1>\ekvc at keycount
+      \ekv at fi@gobble
+    \fi
+    \@firstofone
+      {%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@#1\endcsname####}#1%
+        \expandafter\ekvcSplit at build@argspec@\expandafter{\the\numexpr#1+1}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at SetupSplitKeys, \ekvc at SetupSplitKeys@a, \ekvc at SetupSplitKeys@b,
+%     \ekvc at SetupSplitKeys@unknown
+%   }
+%   These macros parse the list of keys and set up the key macros. First we need
+%   to initialise some macros and start an \expkvp\ parser.
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupSplitKeys
+  {%
+    \ekvc at keycount=\ekv at zero
+    \let\ekvc at any@long\ekv at empty
+    \let\ekvc at initials\ekv at empty
+    \ekvpParse at unsafe\ekvp@@p at ekvc@setup at splitkeys
+  }
+%    \end{macrocode}
+%   We're calling a parser here without the safety nets testing for parser
+%   existence, so better define it now.
+%    \begin{macrocode}
+\ekvpNewParser{ekvc at setup@splitkeys}
+\ekvpDefType{ekvc at setup@splitkeys}{short}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupSplitKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefType{ekvc at setup@splitkeys}{long}
+  {%
+    \let\ekvc at long\long
+    \let\ekvc at any@long\long
+    \expandafter\ekvc at SetupSplitKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefNoType{ekvc at setup@splitkeys}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupSplitKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+%    \end{macrocode}
+%   If no value was provided this could either be an error, or the unknown key
+%   forwarding. We have to check this (comparing against |...| inside
+%   |\ekvc at tripledots|) and if this is the unknown key list type, set it up
+%   accordingly (advancing the key count and setting up the unknown handlers of
+%   \expkv). Else we simply throw an error and ignore the incident.
+%    \begin{macrocode}
+\ekvpDefNoValue{ekvc at setup@splitkeys}
+  {%
+    \begingroup
+      \edef\ekvc at tmp{\detokenize{#1}}%
+      \expandafter
+    \endgroup
+    \ifx\ekvc at tripledots\ekvc at tmp
+      \advance\ekvc at keycount1
+%    \end{macrocode}
+%   The |\begingroup\expandafter\endgroup| ensures that the split mark isn't
+%   actually defined (even if it just were with meaning |\relax|).
+%    \begin{macrocode}
+      \begingroup\expandafter\endgroup
+      \expandafter\ekvc at SetupSplitKeys@unknown
+        \csname ekvc at splitmark@\the\ekvc at keycount\endcsname
+      \let\ekvc at any@long\long
+    \else
+      \ekvc at err@value at required{#1}%
+    \fi
+  }
+%    \end{macrocode}
+%
+%   Now everything is parsed down to the point that we got the key name and its
+%   value. We step the key counter and build the mark within a group to not
+%   accidentally define the |\csname|.
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupSplitKeys@a
+  {%
+    \advance\ekvc at keycount1
+    \begingroup\expandafter\endgroup
+    \expandafter\ekvc at SetupSplitKeys@b
+      \csname ekvc at splitmark@\the\ekvc at keycount\endcsname
+  }
+\protected\long\def\ekvc at SetupSplitKeys@b#1#2\ekv at stop#3%
+  {%
+    \long\def\ekvc at tmp##1##2#1##3{##2#1{##1}}%
+%    \end{macrocode}
+%   The short variant needs a bit of special treatment. The key macro will be
+%   short to throw the correct error, but since there might be long macros
+%   somewhere the reordering of arguments needs to be long, so for short keys we
+%   use a two step approach, first grabbing only the short argument, then
+%   reordering.
+%    \begin{macrocode}
+    \ifx\ekvc at long\long
+    \else
+      \expandafter\let\csname ekvc@\ekvc at set(#2)\endcsname\ekvc at tmp
+      \edef\ekvc at tmp##1%
+        {%
+          \ekv at unexpanded\expandafter{\csname ekvc@\ekvc at set(#2)\endcsname}%
+          {##1}%
+        }%
+    \fi
+    \ekvlet\ekvc at set{#2}\ekvc at tmp
+    \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{#3}}}%
+    \ekvc at helpers@needed
+      {\expandafter\ekvc at setup@splitmacro\expandafter{\the\ekvc at keycount}}%
+      {}%
+  }
+%    \end{macrocode}
+%
+%   Here we get everything readily set up, |#1| contains the mark for unknown
+%   keys and they only have to do some reordering.
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupSplitKeys@unknown#1%
+  {%
+    \long\def\ekvc at tmp##1##2##3##4#1##5{##4#1{##5, {##3} = {##1} }}%
+    \ekvletunknown\ekvc at set\ekvc at tmp
+    \long\def\ekvc at tmp##1##2##3#1##4{##3#1{##4, {##2} }}%
+    \ekvletunknownNoVal\ekvc at set\ekvc at tmp
+    \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{}}}%
+    \ekvc at helpers@needed
+      {\expandafter\ekvc at setup@splitmacro\expandafter{\the\ekvc at keycount}}%
+      {}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at defarggobbler}
+%   This is needed to define a macro with 1-9 parameters programmatically.
+%   \LaTeX's \cs[no-index]{newcommand} does something similar for example.
+%    \begin{macrocode}
+\protected\def\ekvc at defarggobbler#1{\def\ekvc at tmp##1#1##2##{##1#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at setup@splitmacro,
+%     \ekvc at split@1, \ekvc at split@2, \ekvc at split@3,
+%     \ekvc at split@4, \ekvc at split@5, \ekvc at split@6,
+%     \ekvc at split@7
+%   }
+%   Since the first few split macros are different from the others we manually
+%   set those up now. All the others will be defined as needed (always
+%   globally).  The split macros just read up until the correct split mark, move
+%   that argument into a list and reinsert the rest, calling the next split
+%   macro afterwards.
+%    \begin{macrocode}
+\begingroup
+\edef\ekvc at tmp
+  {%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@1\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        ##2##3%
+      {##3{##1}##2}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@2\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        ##3##4%
+      {##4{##1}{##2}##3}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@3\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        ##4##5%
+      {##5{##1}{##2}{##3}##4}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@4\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        ##5##6%
+      {##6{##1}{##2}{##3}{##4}##5}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@5\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@5\endcsname}##5%
+        ##6##7%
+      {##7{##1}{##2}{##3}{##4}{##5}##6}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@6\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@5\endcsname}##5%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@6\endcsname}##6%
+        ##7##8%
+      {##8{##1}{##2}{##3}{##4}{##5}{##6}##7}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@7\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@5\endcsname}##5%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@6\endcsname}##6%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@7\endcsname}##7%
+        ##8##9%
+      {##9{##1}{##2}{##3}{##4}{##5}{##6}{##7}##8}%
+  }
+\ekvc at tmp
+\endgroup
+\protected\def\ekvc at setup@splitmacro#1%
+  {%
+    \ekv at ifdefined{ekvc at split@#1}{}%
+      {%
+        \begingroup
+          \def\ekvc at tmp##1%
+            {%
+              \ekv at unexpanded\expandafter
+                {\csname ekvc at splitmark@\the\numexpr#1-##1\relax\endcsname}%
+            }%
+          \edef\ekvc at tmp
+            {%
+              \long\gdef
+                \ekv at unexpanded\expandafter{\csname ekvc at split@#1\endcsname}%
+                  ####1%
+                  \ekvc at tmp{6}####2%
+                  \ekvc at tmp{5}####3%
+                  \ekvc at tmp{4}####4%
+                  \ekvc at tmp{3}####5%
+                  \ekvc at tmp{2}####6%
+                  \ekvc at tmp{1}####7%
+                  \ekvc at tmp{0}####8%
+                  ####9%
+                {%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at split@\the\numexpr#1-7\relax\endcsname}%
+                  ####1{{####2}{####3}{####4}{####5}{####6}{####7}{####8}####9}%
+                }%
+            }%
+          \ekvc at tmp
+        \endgroup
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcHashAndUse}
+%   |\ekvcHashAndUse| works just like |\ekvcSplitAndUse|.
+%    \begin{macrocode}
+\protected\long\def\ekvcHashAndUse#1#2%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcHashAndUse@#1{}{#2}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvcHashAndUse@}
+%   This is more or less the same as |\ekvcSplitAndUse@|. Instead of an empty
+%   group we place a marker after the initials, we don't use the sorting macros
+%   of |split|, but instead pack all the values in one argument.
+%    \begin{macrocode}
+\protected\long\def\ekvcHashAndUse@#1#2#3%
+  {%
+    \edef\ekvc at set{\string#1}%
+    \ekvc at SetupHashKeys{#3}%
+    \ekvc at helpers@needed
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded{\ekvc at hash@pack at argument}%
+            \ekv at unexpanded\expandafter{\ekvc at initials\ekvc at stop#2}%
+          }%
+      }%
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded{#2}%
+            \ekv at unexpanded\expandafter{\ekvc at initials\ekvc at stop}%
+          }%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcHashAndForward}
+%   |\ekvcHashAndForward| works just like |\ekvcSplitAndForward|.
+%    \begin{macrocode}
+\protected\long\def\ekvcHashAndForward#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcHashAndUse@#1{{#2}}{#3}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcHash}
+%   |\ekvcHash| does the same as |\ekvcSplit|, but has the advantage of not
+%   needing to count arguments, so the definition of the internal macro is a bit
+%   more straight forward.
+%    \begin{macrocode}
+\protected\long\def\ekvcHash#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@secondoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {%
+        \expandafter
+        \ekvcHashAndUse@\expandafter#1\csname ekvc@\string#1\endcsname{#2}%
+        \ekvc at any@long\expandafter\def\csname ekvc@\string#1\endcsname
+            ##1\ekvc at stop
+          {#3}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at hash@pack at argument}
+%   All this macro does is pack the values into one argument and forward that to
+%   the next macro.
+%    \begin{macrocode}
+\long\def\ekvc at hash@pack at argument#1\ekvc at stop#2{#2{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at SetupHashKeys,\ekvc at SetupHashKeys@a,\ekvc at SetupHashKeys@b,
+%     \ekvc at SetupHashKeys@unknown
+%   }
+%   This should look awfully familiar as well, since it's just the same as for
+%   the split keys with a few other names here and there.
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupHashKeys
+  {%
+    \let\ekvc at any@long\ekv at empty
+    \let\ekvc at initials\ekv at empty
+    \ekvpParse at unsafe\ekvp@@p at ekvc@setup at hashkeys
+  }
+\ekvpNewParser{ekvc at setup@hashkeys}
+\ekvpDefType{ekvc at setup@hashkeys}{short}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupHashKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefType{ekvc at setup@hashkeys}{long}
+  {%
+    \let\ekvc at long\long
+    \let\ekvc at any@long\long
+    \expandafter\ekvc at SetupHashKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefNoType{ekvc at setup@hashkeys}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupHashKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefNoValue{ekvc at setup@hashkeys}
+  {%
+    \begingroup
+      \edef\ekvc at tmp{\detokenize{#1}}%
+      \expandafter
+    \endgroup
+    \ifx\ekvc at tripledots\ekvc at tmp
+      \ekvc at SetupHashKeys@unknown
+      \let\ekvc at any@long\long
+    \else
+      \ekvc at err@value at required{#1}%
+    \fi
+  }
+%    \end{macrocode}
+%   Again we build the marker, this time instead of a numbered one a named
+%   hashmark, inside a group to not actually define the macro used as a marker.
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupHashKeys@a#1\ekv at stop
+  {%
+    \begingroup\expandafter\endgroup
+    \expandafter\ekvc at SetupHashKeys@b\csname ekvc at hashmark@#1\endcsname{#1}%
+  }
+%    \end{macrocode}
+%   Yes, even the defining macro looks awfully familiar. Instead of numbered we
+%   have named marks. Still the key macros grab everything up to their
+%   respective mark and reorder the arguments. The same quirk is applied for
+%   short keys. And instead of the |\ekvc at setup@splitmacro| we use
+%   |\ekvc at setup@hashmacro|.
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupHashKeys@b#1#2#3%
+  {%
+    \long\def\ekvc at tmp##1##2#1##3{##2#1{##1}}%
+    \ifx\ekvc at long\long
+    \else
+      \expandafter\let\csname ekvc@\ekvc at set(#2)\endcsname\ekvc at tmp
+      \edef\ekvc at tmp##1%
+        {%
+          \ekv at unexpanded\expandafter{\csname ekvc@\ekvc at set(#2)\endcsname}%
+          {##1}%
+        }%
+    \fi
+    \ekvlet\ekvc at set{#2}\ekvc at tmp
+    \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{#3}}}%
+    \ekvc at setup@hashmacro{#2}%
+  }
+%    \end{macrocode}
+%   Another temporary definition, this time to get the hashmarks for the unknown
+%   handler without defining them.
+%    \begin{macrocode}
+\def\ekvc at SetupHashKeys@unknown#1%
+  {%
+    \protected\def\ekvc at SetupHashKeys@unknown
+      {%
+        \ekvletunknown\ekvc at set\ekvc at hash@unknown at kv
+        \ekvletunknownNoVal\ekvc at set\ekvc at hash@unknown at k
+        \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{}}}%
+        \ekvc at setup@hashmacro{...}%
+      }%
+    \long\def\ekvc at hash@unknown at kv##1##2##3##4#1##5{##4#1{##5, {##3} = {##1} }}%
+    \long\def\ekvc at hash@unknown at k##1##2##3#1##4{##3#1{##4, {##2} }}%
+  }
+\begingroup\expandafter\endgroup
+\expandafter\ekvc at SetupHashKeys@unknown
+  \csname ekvc at hashmark@\ekvc at tripledots\endcsname
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at setup@hashmacro}
+%   The safe hash macros will be executed inside of an |\unexpanded| expansion
+%   context, so they have to insert braces for that once they are done.
+%   Most of the tests which have to be executed will already be done, but we
+%   have to play safe if the hash doesn't show up in the hash list. Therefore we
+%   use some |\ekvc at mark|s and |\ekvc at stop| to throw errors if the hash isn't
+%   found in the right place. The fast variants have an easier life and just
+%   return the correct value.
+%    \begin{macrocode}
+\protected\def\ekvc at setup@hashmacro#1%
+  {%
+    \ekv at ifdefined{ekvc at fasthash@#1}{}%
+      {%
+        \begingroup
+          \edef\ekvc at tmp
+            {%
+              \long\gdef
+                \ekv at unexpanded\expandafter{\csname ekvc at fasthash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at stop}%
+                {####2}%
+              \long\gdef
+                \ekv at unexpanded\expandafter{\csname ekvc at safehash@#1\endcsname}%
+                  ####1%
+                {%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc@@safehash@#1\endcsname}%
+                  ####1\ekv at unexpanded{\ekvc at mark}{}%
+                  \ekv at unexpanded\expandafter
+                    {%
+                      \csname ekvc at hashmark@#1\endcsname{}%
+                      \ekvc at mark{\ekvc at err@missing at hash{#1}}\ekvc at stop
+                    }%
+                }%
+              \long\gdef
+                \ekv at unexpanded\expandafter
+                  {\csname ekvc@@safehash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at mark}####4####5%
+                  \ekv at unexpanded{\ekvc at stop}%
+                {%
+                  ####4{####2}%
+                }%
+              \long\gdef\ekv at unexpanded\expandafter
+                {\csname ekvc at fastsplithash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at stop}####4%
+                {%
+                  ####4{####2}%
+                }%
+              \long\gdef\ekv at unexpanded\expandafter
+                {\csname ekvc at safesplithash@#1\endcsname}####1%
+                {%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc@@safesplithash@#1\endcsname}%
+                  ####1\ekv at unexpanded{\ekvc at mark\ekvc at safe@after at hash}%
+                  \ekv at unexpanded\expandafter
+                    {%
+                      \csname ekvc at hashmark@#1\endcsname{}%
+                      \ekvc at mark
+                      {\ekvc at err@missing at hash{#1}\ekvc at safe@after at hash}%
+                      \ekvc at stop
+                    }%
+                }%
+              \long\gdef\ekv at unexpanded\expandafter
+                {\csname ekvc@@safesplithash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at mark}####4####5%
+                  \ekv at unexpanded{\ekvc at stop}%
+                {%
+                  ####4{####2}%
+                }%
+            }%
+          \ekvc at tmp
+        \endgroup
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcValue}
+% \begin{macro}[internal]{\ekvcValue@}
+%   All this does is a few consistency checks on the first argument (not empty,
+%   hash macro exists) and then call that hash-grabbing macro that will also
+%   test whether the hash is inside of |#2| or not.
+%    \begin{macrocode}
+\long\def\ekvcValue#1%
+  {%
+    \ekv at unexpanded
+    \expandafter\ekvcValue@\detokenize{#1}\ekvc at stop
+  }
+\def\ekvcValue@#1\ekvc at stop
+  {%
+    \ekv at ifdefined{ekvc at safehash@#1}%
+      {\csname ekvc at safehash@#1\endcsname}%
+      {\ekvc at err@unknown at hash{#1}\@firstoftwo{{}}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcValueFast}
+%   To be as fast as possible, this doesn't test for anything, assuming the user
+%   knows best.
+%    \begin{macrocode}
+\long\def\ekvcValueFast#1#2%
+  {\csname ekvc at fasthash@\detokenize{#1}\endcsname#2\ekvc at stop}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcValueSplit}
+% \begin{macro}[internal]{\ekvcValueSplit@,\ekvcValueSplit at recover}
+%   This splits off a single value.
+%    \begin{macrocode}
+\long\def\ekvcValueSplit#1%
+  {\expandafter\ekvcValueSplit@\detokenize{#1}\ekvc at stop}
+\def\ekvcValueSplit@#1\ekvc at stop
+  {%
+    \ekv at ifdefined{ekvc at safesplithash@#1}%
+      {\csname ekvc at safesplithash@#1\endcsname}%
+      {\ekvc at err@unknown at hash{#1}\ekvcValueSplit at recover}%
+  }
+\long\def\ekvcValueSplit at recover#1#2{#2{}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at safe@after at hash}
+%    \begin{macrocode}
+\long\def\ekvc at safe@after at hash#1#2%
+  {%
+    #2{#1}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcValueSplitFast}
+%   Again a fast approach which doesn't provide too many safety measurements.
+%   This needs to build the hash function and expand it before passing the
+%   results to the next control sequence. The first step only builds the control
+%   sequence.
+%    \begin{macrocode}
+\long\def\ekvcValueSplitFast#1#2%
+  {\csname ekvc at fastsplithash@\detokenize{#1}\endcsname#2\ekvc at stop}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at safehash@,\ekvc at fasthash@,
+%     \ekvc at safesplithash@,\ekvc at fastsplithash@
+%   }
+%   At least in the empty hash case we can provide a meaningful error message
+%   without affecting performance by just defining the macro that would be build
+%   in that case. There is of course a downside to this, the error will not be
+%   thrown by |\ekvcValueFast| in three expansion steps. The safe hash variant
+%   has to also stop the |\unexpanded| expansion.
+%    \begin{macrocode}
+\long\def\ekvc at safehash@#1{\ekvc at err@empty at hash{}}
+\long\def\ekvc at fasthash@#1\ekvc at stop{\ekvc at err@empty at hash}
+\long\def\ekvc at safesplithash@#1#2{\ekvc at err@empty at hash#2{}}
+\long\def\ekvc at fastsplithash@#1\ekvc at stop#2{\ekvc at err@empty at hash#2{}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcSecondaryKeys}
+% \begin{macro}[internal]
+%   {\ekvcSecondaryKeys at a,\ekvcSecondaryKeys at b,\ekvcSecondaryKeys at c}
+%   Secondary keys use yet another \expkvp\ parser, keys will be set up further
+%   down in their own subsection.
+%    \begin{macrocode}
+\ekvpNewParser{ekvc at setup@secondary}
+\ekvpValueAlwaysRequired{ekvc at setup@secondary}
+\protected\long\def\ekvcSecondaryKeys#1%
+  {%
+    \edef\ekvc at set{\string#1}%
+    \let\ekvc at long\ekv at empty
+    \ekvpParse at unsafe\ekvp@@p at ekvc@setup at secondary
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcChange}
+%   This can be used to change the defaults of an \expkvc\ defined macro. It
+%   checks whether there is a set with the correct name and that the macro is
+%   defined. If both is true the real work is done by |\ekvc at change|.
+%    \begin{macrocode}
+\protected\long\def\ekvcChange#1%
+  {%
+    \ekvifdefinedset{\string#1}%
+      {%
+        \ekvc at ifdefined#1%
+          {\ekvc at change#1}%
+          {\ekvc at err@no at key@macro#1\@gobble}%
+      }%
+      {\ekvc at err@no at key@macro#1\@gobble}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at change  ,\ekvc at change@a,\ekvc at change@b,
+%     \ekvc at change@c,\ekvc at change@d,\ekvc at change@e
+%   }
+%   First we need to see whether the macro is currently |\long|. For this we get
+%   the meaning and will parse it. |#1| is the macro name in which we want to
+%   change the defaults.
+%    \begin{macrocode}
+\protected\def\ekvc at change#1%
+  {\expandafter\ekvc at change@a\meaning#1\ekv at stop#1}
+%    \end{macrocode}
+%   A temporary definition to get the stringified |macro:|. |##1| will be the
+%   list of prefixes, we don't care for the exact contents of |##2| and |##3|.
+%    \begin{macrocode}
+\def\ekvc at change@a#1%
+  {%
+    \protected\def\ekvc at change@a##1#1##2->##3\ekv at stop
+      {%
+        \ekvc at change@iflong{##1}%
+          {\ekvc at change@b{}}%
+          {\ekvc at change@b{\long}}%
+      }%
+  }
+\expandafter\ekvc at change@a\expandafter{\detokenize{macro:}}
+%    \end{macrocode}
+%   Next we expand the macro once to get its contents (including the current
+%   default values with their markers) and place |\ekvc at stop| instead of an
+%   argument as a marker for the last step. |#1| is either |\long| or empty,
+%   |#2| is the macro.
+%    \begin{macrocode}
+\protected\def\ekvc at change@b#1#2%
+  {\expandafter\ekvc at change@c\expandafter{#2\ekvc at stop}{#1}#2}
+%    \end{macrocode}
+%   Here we place an unbalanced closing brace after the expansion of the macro.
+%   Then we just parse the \kv-list with |\ekvset|, that will exchange the
+%   values behind the markers. Once those are changed we give control to
+%   |\ekvc at change@d|. The |\ekvset| step might horribly fail if the user defined
+%   some keys that don't behave nice. |#1| is the expansion of the macro, |#2|
+%   is either |\long| or empty, |#3| is the macro, and |#4| is the \kv-list
+%   containing the new defaults.
+%    \begin{macrocode}
+\ekv at exparg{\protected\long\def\ekvc at change@c#1#2#3#4}%
+  {%
+    \expandafter\iffalse\expandafter{\expandafter{\expandafter\fi
+      \ekvset{\string#3}{#4}%
+      \ekvc at change@d{#2}{#3}%
+      #1%
+    }}%
+  }
+%    \end{macrocode}
+%   The final step needs to put an unbalanced opening brace after |\edef|. Also
+%   we have to protect everything from further expanding with the exception of
+%   the redefined macro's argument, which is why we placed the |\ekvc at stop|
+%   earlier. Then we need to also protect the rest of the contents from further
+%   expanding using |\unexpanded| with another unbalanced opening brace.
+%   |#1| will be either empty or |\long| and |#2| is the macro.
+%    \begin{macrocode}
+\protected\def\ekvc at change@d#1#2%
+  {#1\edef#2##1{\expandafter\ekvc at change@e\iffalse}\fi}
+\long\def\ekvc at change@e#1\ekvc at stop
+  {\ekv at unexpanded{#1}##1\ekv at unexpanded\expandafter{\iffalse}\fi}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at change@iflong,\ekvc at change@iflong@}
+%   Checking whether a string contains the string representation of |\long| can
+%   be done by gobbling everything up to the first |\long| and checking whether
+%   the result is completely empty. We need a temporary macro to get the result
+%   of |\string\long| inside the definitions.
+%    \begin{macrocode}
+\def\ekvc at change@iflong#1%
+  {%
+    \protected\def\ekvc at change@iflong##1%
+      {\expandafter\ekv at ifempty\expandafter{\ekvc at change@iflong@##1#1}}%
+    \def\ekvc at change@iflong@##1#1{}
+  }
+\expandafter\ekvc at change@iflong\expandafter{\string\long}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcPass}
+%   This macro can be used to pass a value to a key of some macro (this way
+%   more complicated key codes are possible that in the end pass processed
+%   values on to some macro). The implemantation is pretty straight forward.
+%    \begin{macrocode}
+\long\def\ekvcPass#1#2%
+  {%
+    \ekvifdefined{\string#1}{#2}%
+      {\csname\ekv at name{\string#1}{#2}\endcsname}%
+      {\ekvc at err@unknown at key@or at macro{#1}{#2}\@gobble}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Secondary Key Types}
+%
+% There is a single prefix named |long| and set up pretty simple.
+%    \begin{macrocode}
+\ekvpDefPrefixLet{ekvc at setup@secondary}{long}\ekvc at long\long\ekv at empty
+%    \end{macrocode}
+%
+% \begin{macro}[internal]
+%   {
+%     meta, nmeta,
+%     \ekvc at type@meta, \ekvc at type@meta@
+%   }
+%   The |meta| and |nmeta| key types use |\ekvmorekv| to set other keys in
+%   the same macro's \set. If the \kv\ list ist fixed (|nmeta|) we can expand
+%   |\ekvmorekv| as far as possible (twice), else we expand it only once. This
+%   makes a difference only if the \val\ of the |meta| key isn't forwarded in
+%   braces and commas are active at the time of usage, in which case expanding
+%   |\ekvmorekv| twice would result in wrong behaviour.
+%    \begin{macrocode}
+\ekvpDefType{ekvc at setup@secondary}{meta}
+  {\ekvc at type@meta\ekv at exparg\ekvc at long{##1}\ekvlet{#1}{#3}}
+\ekvpDefType{ekvc at setup@secondary}{nmeta}
+  {\ekvc at assert@not at long\ekvc at type@meta\ekv at expargtwice{}{}\ekvletNoVal{#1}{#3}}
+\protected\long\def\ekvc at type@meta#1#2#3#4#5#6%
+  {%
+    #1\ekvc at type@meta@{\ekvmorekv{#6}}{#2}{#3}%
+    #4\ekvc at set{#5}\ekvc at tmp
+  }
+\protected\long\def\ekvc at type@meta@#1#2#3{#2\def\ekvc at tmp#3{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{alias}
+%   |alias| just checks whether there is a key and/or |NoVal| key defined with
+%   the target name and |\let| the key to those.
+%    \begin{macrocode}
+\ekvpDefType{ekvc at setup@secondary}{alias}
+  {%
+    \ekvc at assert@not at long
+    \ekvc at assert@k at or@p at defined{#3}%
+    \ekvifdefined\ekvc at set{#3}{\ekvletkv\ekvc at set{#1}\ekvc at set{#3}}{}%
+    \ekvifdefinedNoVal\ekvc at set{#3}{\ekvletkvNoVal\ekvc at set{#1}\ekvc at set{#3}}{}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{default}
+%   The |default| key can be used to set a \Nkey\ for an existing \Vkey. It
+%   will just pass the \val\ to the key macro of that other key.
+%    \begin{macrocode}
+\ekvpDefType{ekvc at setup@secondary}{default}
+  {%
+    \ekvc at assert@defined{#1}%
+    \ekvc at assert@not at long
+    \edef\ekvc at tmp
+      {%
+        \ekv at unexpanded\expandafter
+          {\csname\ekv at name\ekvc at set{#1}\endcsname{#3}}%
+      }%
+    \ekvletNoVal\ekvc at set{#1}\ekvc at tmp
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{enum,choice}
+% \begin{macro}[internal]
+%   {
+%     \ekvc at type@enum,\ekvc at h@enum,\ekvc at h@enum@,\ekvc at enum@name,
+%     \ekvc at type@choice@
+%   }
+%   Enums don't need to apply special trickery to make the parts of the names
+%   retrievable, so unlike in \expkvd\ we don't need catcode juggling.
+%   The setup of an |enum| requires unpacking the value in two different
+%   arguments so we need an auxiliary here.
+%    \begin{macrocode}
+\def\ekvc at enum@name#1#2#3{ekvc#1(#2)#3}
+\ekvpDefType{ekvc at setup@secondary}{enum}
+  {\ekvpAssertTwoValues{#3}\ekvc at type@enum\ekvc at type@enum@{#1}#3}
+\ekvpDefType{ekvc at setup@secondary}{choice}
+  {\ekvpAssertTwoValues{#3}\ekvc at type@enum\ekvc at type@choice@{#1}#3}
+\protected\long\def\ekvc at type@enum#1#2#3%
+  {%
+    \ekvc at assert@defined{#3}%
+%    \end{macrocode}
+%   At run time we need another helper and we need to expand the current
+%   |\ekvc at set| now. The helper will build a control sequence from each given
+%   value, those will be set up in the |\ekvcsvloop|.
+%    \begin{macrocode}
+    \ekvc at long\edef\ekvc at tmp##1%
+      {%
+        \ekv at unexpanded{\expandafter\ekvc at h@enum\detokenize}{##1}%
+        \ekv at unexpanded{\ekvc at stop}%
+        {\ekvc at set}{#2}%
+      }%
+    \ekvlet\ekvc at set{#2}\ekvc at tmp
+    \def\ekvc at tmp{0}%
+    \expandafter\ekvcsvloop\expandafter
+      {\expandafter#1\csname\ekv at name\ekvc at set{#3}\endcsname{#2}}%
+  }
+%    \end{macrocode}
+%   Here |#1| will be the key-macro of the underlying primary or secondary key,
+%   |#2| is the |enum| key's name, and |#3| will be the choice. The rest is
+%   pretty obvious.
+%    \begin{macrocode}
+\ekv at exparg{\protected\long\def\ekvc at type@enum@#1#2#3}%
+  {%
+    \expandafter\expandafter\expandafter\edef\expandafter
+        \csname\ekvc at enum@name\ekvc at set{#2}{\detokenize{#3}}\endcsname
+      {\ekv at unexpanded{#1}{\ekvc at tmp}}%
+    \edef\ekvc at tmp{\the\numexpr\ekvc at tmp+1\relax}%
+  }
+\ekv at exparg{\protected\long\def\ekvc at type@choice@#1#2#3}%
+  {%
+    \expandafter\expandafter\expandafter\edef\expandafter
+        \csname\ekvc at enum@name\ekvc at set{#2}{\detokenize{#3}}\endcsname
+      {\ekv at unexpanded{#1{#3}}}%
+  }
+%    \end{macrocode}
+%   The use-time helper will check if the macro for the passed in choice exists,
+%   if it doesn't throws an error, else calls that macro which will set the
+%   correct value.
+%    \begin{macrocode}
+\ekv at if@lastnamedcs
+  {%
+    \ekv at exparg{\def\ekvc at h@enum#1\ekvc at stop#2#3}%
+      {%
+        \expandafter\ifcsname\ekvc at enum@name{#2}{#3}{#1}\endcsname
+          \expandafter\ekvc at h@enum@\lastnamedcs
+        \fi
+        \ekvc at err@unknown at enum{#2}{#3}{#1}%
+      }
+    \def\ekvc at h@enum@#1\fi\ekvc at err@unknown at enum#2#3#4%
+      {%
+        \fi
+        \ifx#1\relax
+          \ekvc at err@unknown at enum{#2}{#3}{#4}%
+          \expandafter\@gobble
+        \fi
+        #1%
+      }
+  }
+  {%
+    \def\ekvc at h@enum#1%
+      {%
+        \def\ekvc at h@enum##1\ekvc at stop##2##3%
+          {%
+            \expandafter\ekvc at h@enum@
+              \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
+              {##2}{##3}{##1}%
+          }%
+      }
+    \expandafter\ekvc at h@enum\expandafter{\ekvc at enum@name{#2}{#3}{#1}}
+    \def\ekvc at h@enum@#1#2#3#4%
+      {%
+        \ifx#1\relax
+          \ekvc at err@unknown at enum{#2}{#3}{#4}%
+          \expandafter\@gobble
+        \fi
+        #1%
+      }
+  }
+%    \end{macrocode}
+%   We don't need |\ekvc at enum@name| anymore, so let's undefine it.
+%    \begin{macrocode}
+\let\ekvc at enum@name\ekvc at undefined
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{aggregate,e-aggregate}
+%   Aggregating isn't easy to define. We'll have to extract the correct mark for
+%   the specified key, branch correctly for short and long keys, and use a small
+%   hack to have the correct arguments on the user interface (|#1| as the
+%   current contents, |#2| as the new value). This is split into a few steps
+%   here.
+%
+%   First, assert that the user input is well-behaved.
+%    \begin{macrocode}
+\ekvpDefType{ekvc at setup@secondary}{aggregate}
+  {%
+    \let\ekvc at type@aggregate at ifexpanded\@secondoftwo
+    \ekvc at type@aggregate{#1}{#3}%
+  }
+\ekvpDefType{ekvc at setup@secondary}{e-aggregate}
+  {%
+    \let\ekvc at type@aggregate at ifexpanded\@firstoftwo
+    \ekvc at type@aggregate{#1}{#3}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekvc at type@aggregate,\ekvc at type@aggregate at a,\ekvc at type@aggregate at b}
+%   The next step stores the user defined processing in a temporary macro that's
+%   used to do the parameter number swapping later. It also builds the names of
+%   the key macro and the helper which would be used for processing a short key.
+%    \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate#1#2%
+  {%
+    \ekvc at assert@not at long
+    \ekvpAssertTwoValues{#2}%
+    \ekvc at type@aggregate at a
+      \ekvc at type@aggregate at long\ekvc at type@aggregate at short
+      {#1}#2%
+  }
+\protected\long\def\ekvc at type@aggregate at a#1#2#3#4#5%
+  {%
+    \ekvc at assert@defined{#4}%
+    \def\ekvc at type@aggregate at tmp##1##2{#5}%
+    \begingroup\expandafter\endgroup
+    \expandafter\ekvc at type@aggregate at b
+      \csname\ekv at name\ekvc at set{#4}\expandafter\endcsname
+      \csname ekvc@\ekvc at set(#4)\endcsname
+      #1#2%
+      {#3}%
+  }
+\protected\long\def\ekvc at type@aggregate at b#1#2#3#4%
+  {%
+    \ekvc at type@aggregate at check@long#1#2%
+      {#3#1}%
+      {#4#2}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at type@aggregate at check@long,
+%     \ekvc at type@aggregate at check@long at a,\ekvc at type@aggregate at check@long at b
+%   }
+%   To check whether the primary key is long we see whether its |\meaning|
+%   contains the helper which would only be there for short keys. For this we
+%   have to get the stringified name of the internal (using |\detokenize|),
+%   and afterwards get the |\meaning| of the macro. A temporary helper does the
+%   real test by gobbling and forwarding the result to |\ekv at ifempty|.
+%    \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate at check@long#1#2%
+  {\expandafter\ekvc at type@aggregate at check@long at a\detokenize{#2}\ekv at stop#1}
+\protected\long\def\ekvc at type@aggregate at check@long at a#1\ekv at stop#2%
+  {%
+    \def\ekvc at type@aggregate at check@long@@##1#1{}%
+    \expandafter\ekvc at type@aggregate at check@long at b\meaning#2\ekv at stop{#1}%
+  }
+\protected\def\ekvc at type@aggregate at check@long at b#1\ekv at stop#2%
+  {\expandafter\ekv at ifempty\expandafter{\ekvc at type@aggregate at check@long@@#1#2}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at type@aggregate at long,\ekvc at type@aggregate at long@}
+%   The long variant just builds the split mark we extract, uses the hack to
+%   swap argument order, and then does the definition via |\ekvlet| and a
+%   temporary macro.
+%    \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate at long#1%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@aggregate at long@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+  }
+\protected\long\def\ekvc at type@aggregate at long@#1#2#3%
+  {%
+    \ekvc at type@aggregate at ifexpanded
+      {%
+        \long\def\ekvc at type@aggregate at tmp##1##2#1##3%
+          {\ekv at expanded{\ekv at unexpanded{##2#1}{#2}}}%
+      }%
+      {\long\def\ekvc at type@aggregate at tmp##1##2#1##3{##2#1{#2}}}%
+    \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekvc at type@aggregate at short,\ekvc at type@aggregate at short@}
+%   The short variant will have to build the marker and the name of the helper
+%   function, and swap the user argument order. Hence here are a few more
+%   |\expandafter|s involved. But afterwards we can do the definition of the key
+%   and the helper macro directly.
+%    \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate at short#1#2%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@aggregate at short@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+      {#2}%
+  }
+\protected\long\def\ekvc at type@aggregate at short@#1#2#3#4%
+  {%
+    \ekvdef\ekvc at set{#4}{#2{##1}}%
+    \ekvc at type@aggregate at ifexpanded
+      {\long\def#2##1##2#1##3{\ekv at expanded{\ekv at unexpanded{##2#1}{#3}}}}%
+      {\long\def#2##1##2#1##3{##2#1{#3}}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{process}
+%   The |process| type can reuse much of |aggregate|, just the last step of
+%   definition differ.
+%    \begin{macrocode}
+\ekvpDefType{ekvc at setup@secondary}{process}
+  {%
+    \ekvpAssertTwoValues{#3}%
+    \ifx\ekvc at long\long
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+      {%
+        \ekvc at type@aggregate at a
+          \ekvc at type@process at long\ekvc at type@process at long
+      }%
+      {%
+        \ekvc at type@aggregate at a
+          \ekvc at type@process at short\ekvc at type@process at short
+      }%
+      {#1}#3%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at type@process at long,\ekvc at type@process at long@}
+%   This defines a temporary macro to grab the current value (found after the
+%   marker |#1|), executes the user code and puts everything back to where it
+%   belongs. Then |\ekvlet| is used to assign that meaning to the key macro.
+%    \begin{macrocode}
+\protected\long\def\ekvc at type@process at long#1%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@process at long@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+  }
+\protected\long\def\ekvc at type@process at long@#1#2#3%
+  {%
+    \long\def\ekvc at type@aggregate at tmp##1##2#1##3{#2##2#1{##3}}%
+    \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at type@process at short,\ekvc at type@process at short@}
+%   We define the key macro directly to just grab the argument once and forward
+%   it to the auxiliary. That one does essentially the same as the long variant.
+%    \begin{macrocode}
+\protected\long\def\ekvc at type@process at short#1#2%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@process at short@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+      {#2}%
+  }
+\protected\long\def\ekvc at type@process at short@#1#2#3#4%
+  {%
+    \ekvdef\ekvc at set{#4}{#2{##1}}%
+    \long\def#2##1##2#1##3{#3##2#1{##3}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{flag-bool}
+%    \begin{macrocode}
+\ekvpDefType{ekvc at setup@secondary}{flag-bool}
+  {%
+    \ekvc at assert@not at long
+    \ekvpAssertOneValue{#3}%
+    \ifdefined#3\else\ekvcFlagNew#3\fi
+    \ekvdef\ekvc at set{#1}%
+      {%
+        \ekv at ifdefined{ekvc at flag@set@##1}%
+          {%
+            \csname ekvc at flag@set@##1\expandafter\endcsname
+              \ekvcFlagHeight#3\ekv at stop#3%
+          }%
+          {\ekvc at err@invalid at bool{##1}}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{flag-true,flag-false,flag-raise}
+% \begin{macro}[internal]{\ekvc at type@flag}
+%    \begin{macrocode}
+\protected\def\ekvc at type@flag#1#2#3%
+  {%
+    \ekvc at assert@not at long
+    \ekvpAssertOneValue{#3}%
+    \ifdefined#3\else\ekvcFlagNew#3\fi
+    \ekv at exparg{\ekvdefNoVal\ekvc at set{#2}}{#1#3}%
+  }
+\ekvpDefType{ekvc at setup@secondary}{flag-true}
+  {\ekvc at type@flag\ekvcFlagSetTrue{#1}{#3}}
+\ekvpDefType{ekvc at setup@secondary}{flag-false}
+  {\ekvc at type@flag\ekvcFlagSetFalse{#1}{#3}}
+\ekvpDefType{ekvc at setup@secondary}{flag-raise}
+  {\ekvc at type@flag\ekvcFlagRaise{#1}{#3}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsubsection{Flags}
+%
+% The basic idea of flags is to store information by the fact that \TeX\
+% expandably assigns the meaning |\relax| to undefined control sequences which
+% were built with |\csname|. This mechanism is borrowed from \pkg{expl3}.
+%
+% \begin{macro}[internal]{\ekvc at flag@name,\ekvc at flag@namescheme}
+%   Flags follow a simple naming scheme which we define here. |\ekvc at flag@name|
+%   will store the name of an internal function that is used to build names of
+%   the second naming scheme defined by |\ekvc at flag@namescheme|.
+%    \begin{macrocode}
+\def\ekvc at flag@name{ekvcf\string}
+\def\ekvc at flag@namescheme#1#2{ekvch#2#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagHeight}
+%   For semantic reasons we use |\number| with another name.
+%    \begin{macrocode}
+\let\ekvcFlagHeight\number
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagNew}
+%   This macro defines a new flag. It stores the function build with the
+%   |\ekvc at flag@name| naming scheme after the internal function
+%   |\ekvc at flag@height| that'll determine the current flag height. It'll also
+%   define the macro named via |\ekvc at flag@name| to build names according to
+%   |\ekvc at flag@namescheme|.
+%    \begin{macrocode}
+\protected\def\ekvcFlagNew#1%
+  {%
+    \edef#1%
+      {%
+        \ekv at unexpanded{\ekvc at flag@height}%
+          \ekv at unexpanded\expandafter{\csname\ekvc at flag@name#1\endcsname}%
+      }%
+    \ekv at expargtwice
+      {\expandafter\def\csname\ekvc at flag@name#1\endcsname##1}%
+      {\expandafter\ekvc at flag@namescheme\expandafter{\string#1}{##1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at flag@height,\ekvc at flag@height@}
+%   This macro gets the height of a flag by a simple loop. The first loop
+%   iteration differs a bit from the following in that it doesn't have to get
+%   the current iteration count. The space at the end of |\ekvc at flag@height|
+%   ends the |\number| evaluation.
+%    \begin{macrocode}
+\def\ekvc at flag@height#1%
+  {%
+    \ifcsname#10\endcsname
+      \ekvc at flag@height at 1\ekv at stop#1%
+    \fi
+    \@firstofone{0} % leave this space
+  }
+\def\ekvc at flag@height@#1\ekv at stop#2\fi\@firstofone#3%
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      \expandafter\ekvc at flag@height@\the\numexpr#1+1\relax\ekv at stop#2%
+    \fi
+    \@firstofone{#1}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagRaise}
+%   Raising a flag simply means letting the |\ekvc at flag@namescheme| macro for
+%   the current height to relax. The result of raising a flag is that its height
+%   is bigger by $1$.
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvcFlagRaise#1}%
+  {%
+    \expandafter\expandafter\expandafter\@gobble\expandafter
+      \csname\ekvc at flag@namescheme{\string#1}{\ekvcFlagHeight#1}\endcsname
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagSetTrue,\ekvcFlagSetFalse}
+% \begin{macro}[internal]{\ekvc at flag@set at true,\ekvc at flag@set at false}
+%   A flag is considered true if its current height is odd, and as false if it
+%   is even. Therefore |\ekvcFlagSetTrue| and |\ekvcFlagSetFalse| only need to
+%   raise the flag if the opposing boolean value is the current one.
+%    \begin{macrocode}
+\def\ekvcFlagSetTrue#1%
+  {\expandafter\ekvc at flag@set at true\ekvcFlagHeight#1\ekv at stop#1}
+\def\ekvcFlagSetFalse#1%
+  {\expandafter\ekvc at flag@set at false\ekvcFlagHeight#1\ekv at stop#1}
+%    \end{macrocode}
+%   We can expand |\ekvc at flag@namescheme| at definition time here, which is why
+%   we're using a temporary definition to set up |\ekvc at flag@set at true| and
+%   |\ekvc at flag@set at false|.
+%    \begin{macrocode}
+\def\ekvc at flag@set at true#1%
+  {%
+    \def\ekvc at flag@set at true##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@gobble
+        \fi
+        \@firstofone{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+    \def\ekvc at flag@set at false##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@firstofone
+        \fi
+        \@gobble{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+  }
+\expandafter\ekvc at flag@set at true\expandafter
+  {\ekvc at flag@namescheme{\string#2}{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagIf}
+%   As already explained, truthiness is defined as a flag's height being odd, so
+%   we just branch accordingly here.
+%    \begin{macrocode}
+\def\ekvcFlagIf#1%
+  {%
+    \ifodd#1%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagIfRaised}
+%   This macro uses flags as a switch, if a flag's current height is bigger than
+%   $0$ this test yields true.
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvcFlagIfRaised#1}%
+  {%
+    \expandafter\ifcsname\ekvc at flag@namescheme{\string#1}0\endcsname
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagReset,\ekvcFlagResetGlobal}
+% \begin{macro}[internal]{\ekvc at flag@reset,\ekvc at flag@reset@}
+%   Resetting works by locally letting all the defined internal macros named
+%   after |\ekvc at flag@namescheme| to undefined.
+%    \begin{macrocode}
+\protected\def\ekvcFlagReset#1%
+  {\expandafter\ekvc at flag@reset\csname\ekvc at flag@name#1\endcsname{}}
+\protected\def\ekvcFlagResetGlobal#1%
+  {\expandafter\ekvc at flag@reset\csname\ekvc at flag@name#1\endcsname\global}
+\protected\def\ekvc at flag@reset#1#2%
+  {%
+    \ifcsname#10\endcsname
+      #2\expandafter\let\csname#10\endcsname\ekvc at undefined
+      \ekvc at flag@reset at 1\ekv at stop#1{#2}%
+    \fi
+  }
+\protected\def\ekvc at flag@reset@#1\ekv at stop#2#3\fi
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      #3\expandafter\let\csname#2{#1}\endcsname\ekvc at undefined
+      \expandafter\ekvc at flag@reset@\the\numexpr#1+1\relax\ekv at stop#2{#3}%
+    \fi
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagGetHeight}
+% \begin{macro}[internal]{\ekvc at flag@get at height@single}
+%   These are just small helpers, first getting the height of the flag and then
+%   passing it on to the user supplied code.
+%    \begin{macrocode}
+\def\ekvcFlagGetHeight#1%
+  {\expandafter\ekvc at flag@get at height@single\ekvcFlagHeight#1\ekv at stop}
+\long\def\ekvc at flag@get at height@single#1\ekv at stop#2{#2{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagGetHeights}
+% \begin{macro}[internal]
+%   {\ekvc at flag@get at heights,\ekvc at flag@get at heights@,\ekvc at flag@get at heights@done}
+%   This works by a simple loop that stops at |\ekv at stop|. As long as that
+%   marker isn't hit, get the next flags height and put it into a list after
+%   |\ekv at stop|. |\ekvc at flag@get at heights@| uses the same marker name for the
+%   end of the height, which shouldn't clash in any case. Once we're done we
+%   remove the remainder of the current iteration and leave the user supplied
+%   code in the input stream with all the flags' heights as a single argument.
+%    \begin{macrocode}
+\def\ekvcFlagGetHeights#1%
+  {%
+    \ekvc at flag@get at heights#1\ekv at stop{}%
+  }
+\def\ekvc at flag@get at heights#1%
+  {%
+    \ekv at gobbleto@stop#1\ekvc at flag@get at heights@done\ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight#1\ekv at stop
+  }
+\def\ekvc at flag@get at heights@#1\ekv at stop#2\ekv at stop#3%
+  {\ekvc at flag@get at heights#2\ekv at stop{#3{#1}}}
+\long\def\ekvc at flag@get at heights@done
+    \ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight\ekv at stop\ekv at stop#1#2%
+  {#2{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsubsection{Helper Macros}
+%
+% \begin{macro}[internal]{\ekvc at extract@mark,\ekvc at extract@mark@}
+%   This is used to extract the mark of a split or hash key from its definition.
+%   This is kind of fragile, it assumes |#1| is always a macro used for hashing
+%   or splitting. Also it assumes that the escape character is a backslash.
+%    \begin{macrocode}
+\def\ekvc at extract@mark#1{\expandafter\ekvc at extract@mark@\meaning#1\ekv at stop}
+\begingroup
+\lccode`;=`#
+\lccode`/=`\\
+\lowercase{\endgroup
+\def\ekvc at extract@mark@#1:#2/#3 ;#4\ekv at stop{#3}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Assertions}
+%
+% \begin{macro}[internal]{\ekvc at assert@not at long}
+%   Some keys don't want to be |long| and we have to educate the user, so let's
+%   throw an error if someone wanted these to be long.
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvc at assert@not at long}%
+  {\ekvpAssertIfNot{\ifx\ekvc at long\long}{`long' not accepted}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at assert@defined,\ekvc at assert@k at or@p at defined}
+%   Since some keys interact with existing other keys we need to assert those
+%   exist.
+%    \begin{macrocode}
+\long\def\ekvc at assert@defined#1%
+  {\ekvpAssertTF{\ekvifdefined\ekvc at set{#1}}{undefined key `#1'}}
+\long\def\ekvc at assert@k at or@p at defined#1%
+  {%
+    \ekvpAssertTF
+      {\ekvifdefined\ekvc at set{#1}\@firstoftwo{\ekvifdefinedNoVal\ekvc at set{#1}}}%
+      {undefined key `#1'}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Messages}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at errm,
+%     \ekvc at err@toomany,\ekvc at err@value at required,
+%     \ekvc at err@already at defined,\ekvc at err@no at key@macro,
+%   }
+%   Boring unexpandable error messages.
+%    \begin{macrocode}
+\protected\long\def\ekvc at errm#1{\errmessage{expkv-cs Error: #1}}
+\protected\long\def\ekvc at err@toomany#1%
+  {\ekvc at errm{Too many keys for macro `\string#1'}}
+\protected\long\def\ekvc at err@value at required#1%
+  {\ekvc at errm{Missing value for key `\ekv at unexpanded{#1}'}}
+\protected\long\def\ekvc at err@already at defined#1%
+  {\ekvc at errm{Macro `\string#1' already defined}}
+\protected\long\def\ekvc at err@no at key@macro#1%
+  {\ekvc at errm{\string#1 is no key=val macro}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at err}
+%   We need a way to throw error messages expandably in some contexts.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekvc at err#1}{\ekverr{expkv-cs}{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvc at err@unknown at hash,\ekvc at err@empty at hash,\ekvc at err@missing at hash,
+%     \ekvc at err@invalid at bool,\ekvc at err@unknown at key@or at macro,
+%     \ekvc at err@unknown at enum
+%   }
+%   And here are the expandable error messages.
+%    \begin{macrocode}
+\long\def\ekvc at err@unknown at hash#1{\ekvc at err{unknown hash `#1'}}
+\long\def\ekvc at err@missing at hash#1{\ekvc at err{hash `#1' not found}}
+\long\def\ekvc at err@empty at hash{\ekvc at err{empty hash}}
+\def\ekvc at err@invalid at bool#1{\ekvc at err{invalid boolean value `#1'}}
+\long\def\ekvc at err@unknown at key@or at macro#1#2%
+  {\ekvc at err{unknown key `#2' for #1}}
+\def\ekvc at err@unknown at enum#1#2#3%
+  {\ekvc at err{unknown choice `#3' for `#2' in #1}}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% Now everything that's left is to reset the category code of |@|.
+%    \begin{macrocode}
+\catcode`\@=\ekvc at tmp
+%    \end{macrocode}
+%
+% \gobbledocstriptag
+%</tex>
+%^^A=<<


Property changes on: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-cs.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-def.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-def.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-def.dtx	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,1369 @@
+% \iffalse meta-comment
+%
+% File: expkv-def.dtx Copyright (C) 2020-2023 Jonathan P. Spratte
+%
+% This work  may be  distributed and/or  modified under  the conditions  of the
+% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+% (at your option) any later version.  The latest version of this license is in
+% the file:
+%
+%   http://www.latex-project.org/lppl.txt
+%
+% ------------------------------------------------------------------------------
+%
+%<*driver>^^A>>=
+\def\expkvDocNoGenerate{}
+\input expkv-bundle.ins
+\generate{\file{expkv-def.sty}{\from{expkv-def.dtx}{pkg}}}
+\generate{\file{expkv-def.tex}{\from{expkv-def.dtx}{tex}}}
+\generate{\file{t-expkv-def.tex}{\from{expkv-def.dtx}{ctx}}}
+\endbatchfile
+%</driver>^^A=<<
+% \fi
+%
+% \section{\expkvd}
+%^^A the LaTeX package >>=
+% \subsection{The \LaTeX\ Package}
+% Just like for \expkv\ we provide a small \LaTeX\ package that sets up things
+% such that we behave nicely on \LaTeX\ packages and files system. It'll
+% |\input| the generic code which implements the functionality.
+% \gobbledocstriptag
+%<*pkg>
+%    \begin{macrocode}
+\RequirePackage{expkv-pop}
+\def\ekvd at tmp
+  {%
+    \ProvidesFile{expkv-def.tex}%
+      [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]%
+  }
+\input{expkv-def.tex}
+\ProvidesPackage{expkv-def}%
+  [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]
+%    \end{macrocode}
+% \gobbledocstriptag
+%</pkg>
+%^^A=<<
+%^^A the ConTeXt module >>=
+% \subsection{The \ConTeXt\ module}
+% \gobbledocstriptag
+%<*ctx>
+%    \begin{macrocode}
+\writestatus{loading}{ConTeXt User Module / expkv-def}
+\usemodule[expkv-pop]
+\unprotect
+\input expkv-def.tex
+\writestatus{loading}
+  {ConTeXt User Module / expkv-def / Version \ekvdVersion\space loaded}
+\protect\endinput
+%    \end{macrocode}
+% \gobbledocstriptag
+%</ctx>
+%^^A=<<
+%^^A main file >>=
+% \subsection{The Generic Code}
+% The rest of this implementation will be the generic code.
+% \gobbledocstriptag
+%<*tex>
+%
+% Load \expkv\ if the package didn't already do so -- since \expkv\ has
+% safeguards against being loaded twice this does no harm and the overhead
+% isn't that big. Also we reuse some of the internals of \expkv\ to save us from
+% retyping them. Additionally load \expkvp, which aids in defining the type
+% system (and \expkvp\ will actually do the \expkv\ loading).
+%    \begin{macrocode}
+\input expkv-pop
+%    \end{macrocode}
+%
+% We make sure that \file{expkv-def.tex} is only input once:
+%    \begin{macrocode}
+\expandafter\ifx\csname ekvdVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+%    \end{macrocode}
+%
+% \begin{macro}{\ekvdVersion,\ekvdDate}
+% We're on our first input, so lets store the version and date in a macro.
+%    \begin{macrocode}
+\def\ekvdVersion{1.0}
+\def\ekvdDate{2023-01-23}
+%    \end{macrocode}
+% \end{macro}
+%
+% If the \LaTeX\ format is loaded we want to be a good file and report back who
+% we are, for this the package will have defined |\ekvd at tmp| to use
+% |\ProvidesFile|, else this will expand to a |\relax| and do no harm.
+%    \begin{macrocode}
+\csname ekvd at tmp\endcsname
+%    \end{macrocode}
+%
+% Store the category code of |@| to later be able to reset it and change it to
+% 11 for now.
+%    \begin{macrocode}
+\expandafter\chardef\csname ekvd at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+%    \end{macrocode}
+% |\ekvd at tmp| will be reused later to handle expansion during the key
+% defining. But we don't need it to ever store information long-term after
+% \expkvd\ was initialized.
+%
+% \begin{macro}[internal]{\ekvd at ifprimitive}
+%    \begin{macrocode}
+\protected\long\def\ekvd at ifprimitive#1%
+  {%
+    \begingroup
+      \edef\ekvd at tmpa{\string #1}%
+      \edef\ekvd at tmpb{\meaning#1}%
+      \expandafter
+    \endgroup
+    \ifx\ekvd at tmpa\ekvd at tmpb
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekvd at long,\ekvd at prot,\ekvd at clear@prefixes,\ekvd at ifalso}
+% \expkvd\ will use |\ekvd at long|, |\ekvd at prot|, and |\ekvd at ifalso| to store
+% whether a key should be defined as |\long| or |\protected| or adds an action
+% to an existing key, and we have to clear them for every new key. By default
+% |long| and |protected| will just be empty, |ifalso| will be
+% |\@secondoftwo|, and |ifnew| will just use its third argument.
+%    \begin{macrocode}
+\protected\def\ekvd at clear@prefixes
+  {%
+    \let\ekvd at long\ekv at empty
+    \let\ekvd at prot\ekv at empty
+    \let\ekvd at ifalso\@secondoftwo
+    \let\ekvd at do@new\@gobbletwo
+  }
+\ekvd at clear@prefixes
+%    \end{macrocode}
+% \end{macro}
+%
+% We define the parser for our front-facing macro and its \prefix{}es here:
+%    \begin{macrocode}
+\ekvpNewParser{ekvd at definekeys}
+\ekvpDefNoValuePrefix{ekvd at definekeys}
+  {\let\ekvd at ifnoarg\@firstoftwo}
+  {\let\ekvd at ifnoarg\@secondoftwo}
+\ekvpDefPrefixLet{ekvd at definekeys}{long}     \ekvd at long\long     \ekv at empty
+\ekvpDefPrefixLet{ekvd at definekeys}{protected}\ekvd at prot\protected\ekv at empty
+\ekvpDefPrefixLet{ekvd at definekeys}{protect}  \ekvd at prot\protected\ekv at empty
+\ekvpDefPrefixLet{ekvd at definekeys}{also}\ekvd at ifalso\@firstoftwo\@secondoftwo
+\ekvpDefPrefixLet{ekvd at definekeys}{new}\ekvd at do@new\ekvd at assert@new\@gobbletwo
+%    \end{macrocode}
+% We ease the process of error throwing a bit for now by using our own macro
+% instead of relying on \expkvp's argument forwarding.
+%    \begin{macrocode}
+\ekvpDefAutoPrefix{ekvd at definekeys}{\edef\ekvd at cur{\detokenize{#3}}}{}
+%    \end{macrocode}
+%
+% \begin{macro}{\ekvdefinekeys}
+%   This is the one front-facing macro which provides the interface to define
+%   keys. It stores the \set\ for which the keys should be defined in
+%   |\ekvd at set| and calls a parser defined with \expkvp.
+%    \begin{macrocode}
+\protected\edef\ekvdefinekeys#1%
+  {%
+    \ekv at unexpanded{\def\ekvd at set}{#1}%
+    \ekv at unexpanded{\ekvpParse at unsafe@auto\ekvp@@p at ekvd@definekeys}%
+    \ekv at unexpanded\expandafter{\csname\ekvp@@p at ekvd@definekeys{ppa}\endcsname}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Key Types}
+%
+% \begin{macro}[internal]{\ekvd at def@type,\ekvd at def@type at fwd}
+%   To reduce some typing the following is a shortcut to |\ekvpDefType|. The
+%   |@fwd| variant will forward the key name and value and remove the
+%   unprocessed key. The other variant automatically sets up a helper macro,
+%   unfortunately this is necessary due to the design decision of \expkvp\ to
+%   not |\detokenize| the key names while \expkvd\ used to do this very early.
+%    \begin{macrocode}
+\protected\def\ekvd at def@type#1#2%
+  {%
+    \ekv at exparg{\ekvpDefType{ekvd at definekeys}{#1}}
+      {%
+        \expandafter\expandafter\csname ekvd at th@#1\endcsname
+          \detokenize{##1}\ekv at stop{##2}{##3}%
+      }%
+    \long\expandafter\def\csname ekvd at th@#1\endcsname##1\ekv at stop##2##3{#2}%
+  }
+\protected\long\def\ekvd at def@type at fwd#1#2%
+  {\ekvpDefType{ekvd at definekeys}{#1}{\ekv at exparg{#2}{\detokenize{##1}}{##3}}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set}
+% \begin{macro}[internal]{\ekvd at type@set}
+%    \begin{macrocode}
+\ekvd at def@type{set}
+  {\ekvd at ifnoarg{\ekvd at type@set{#1}{#1}}{\ekvd at type@set{#1}{#3}}}
+\protected\def\ekvd at type@set#1#2%
+  {%
+    \ekvd at assert@not at long
+    \ekvd at assert@not at protected
+    \ekvd at do@new{NoVal}{#1}%
+    \ekv at ifempty{#2}%
+      {\ekvd at err@missing at definition}%
+      {%
+        \ekvd at ifalso
+          {%
+            \ekv at expargtwice{\ekvd at add@noval{#1}}%
+              {\ekvchangeset{#2}}%
+              \ekvd at assert@not at protected@also
+          }%
+          {\ekv at expargtwice{\ekvdefNoVal\ekvd at set{#1}}{\ekvchangeset{#2}}}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{noval,enoval}
+% \begin{macro}[internal]{\ekvd at type@noval}
+% Another pretty simple type, |noval| just needs to assert that there is a
+% definition and that |long| wasn't specified.
+% There are types where the difference in the variants is so small, that we
+% define a common handler for them, those common handlers are named with
+% |@type@|. |noval| and |enoval| are so similar that we can use such a |@type@|
+% macro, even if we could've done |noval| in a slightly faster way without it.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{noval}{\ekvd at type@noval\def}
+\ekvd at def@type at fwd{enoval}{\ekvd at type@noval\edef}
+\protected\long\def\ekvd at type@noval#1#2#3%
+  {%
+    \ekvd at do@new{NoVal}{#2}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at long
+    \ekvd at prot#1\ekvd at tmp{#3}%
+    \ekvd at ifalso
+      {\ekv at exparg{\ekvd at add@noval{#2}}\ekvd at tmp{}}%
+      {\ekvletNoVal\ekvd at set{#2}\ekvd at tmp}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{code,ecode}
+% \begin{macro}[internal]{\ekvd at type@code}
+% |code| is simple as well, |ecode| has to use |\edef| on a temporary macro,
+% since \expkv\ doesn't provide an |\ekvedef|.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{code}{\ekvd at type@code\def}
+\ekvd at def@type at fwd{ecode}{\ekvd at type@code\edef}
+\protected\long\def\ekvd at type@code#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@arg
+    \ekvd at prot\ekvd at long#1\ekvd at tmp##1{#3}%
+    \ekvd at ifalso
+      {\ekv at exparg{\ekvd at add@val{#2}}{\ekvd at tmp{##1}}{}}%
+      {\ekvlet\ekvd at set{#2}\ekvd at tmp}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{default,qdefault,odefault,fdefault,edefault}
+% \begin{macro}[internal]
+%   {
+%     \ekvd at type@default,\ekvd at t@default,\ekvd at t@qdefault,\ekvd at t@odefault,
+%     \ekvd at t@fdefault
+%   }
+% |\ekvd at type@default| asserts there was an argument, also the key for which one
+% wants to set a default has to be already defined (this is not so important for
+% |default|, but |qdefault| requires it). If everything is good, |\edef| a
+% temporary macro that expands |\ekvd at set| and the |\csname| for the key.
+% The different expansion variants are implemented via |\ekv at unexpanded| and
+% some |\expandafter|s.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{default}{\ekvd at type@default{\ekv at unexpanded\expandafter}{}}
+\ekvd at def@type at fwd{odefault}
+  {\ekvd at type@default{\ekv at unexpanded\expandafter\expandafter\expandafter}{}}
+\ekvpLet{ekvd at definekeys}{type}{qdefault}{odefault}
+\ekvd at def@type at fwd{fdefault}
+  {\ekvd at type@default{\ekv at unexpanded\expandafter}{\romannumeral`\^^@}}
+\protected\long\def\ekvd at type@default#1#2#3#4%
+  {%
+    \ekvd at assert@arg
+    \ekvd at do@new{NoVal}{#3}%
+    \ekvd at assert@not at long
+    \ekvifdefined\ekvd at set{#3}%
+      {%
+        \ekvd at prot\edef\ekvd at tmp
+          {#1{#2\csname\ekv at name\ekvd at set{#3}\endcsname{#4}}}%
+        \ekvd at ifalso
+          {\ekv at exparg{\ekvd at add@noval{#3}}\ekvd at tmp{}}%
+          {\ekvletNoVal\ekvd at set{#3}\ekvd at tmp}%
+      }%
+      {\ekvd at err@undefined at key{#3}}%
+  }
+\ekvd at def@type{edefault}
+  {%
+    \ekvd at assert@arg
+    \ekvd at do@new{NoVal}{#1}%
+    \ekvd at assert@not at long
+    \ekvifdefined\ekvd at set{#1}%
+      {%
+        \ekvd at prot\edef\ekvd at tmp
+          {%
+            \ekv at unexpanded\ekv at expanded
+              {{\csname\ekv at name\ekvd at set{#1}\endcsname{#3}}}%
+          }%
+        \ekvd at ifalso
+          {\ekv at exparg{\ekvd at add@noval{#1}}\ekvd at tmp{}}%
+          {\ekvletNoVal\ekvd at set{#1}\ekvd at tmp}%
+      }%
+      {\ekvd at err@undefined at key{#1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{initial,oinitial,finitial,einitial}
+% \begin{macro}[internal]{\ekvd at type@initial}
+%    \begin{macrocode}
+\ekvd at def@type at fwd{initial}{\ekvd at type@initial\@firstofone}
+\ekvd at def@type at fwd{oinitial}{\ekvd at type@initial\ekv at exparg}
+\ekvd at def@type at fwd{einitial}{\ekvd at type@initial\ekv at expandedarg}
+\ekvd at def@type at fwd{finitial}{\ekvd at type@initial\ekv at fexparg}
+\long\def\ekvd at type@initial#1#2#3%
+  {%
+    \ekvd at assert@not at new
+    \ekvd at assert@not at also
+    \ekvd at assert@not at long
+    \ekvd at assert@not at protected
+    \ekvd at ifnoarg
+      {%
+        \ekvifdefinedNoVal\ekvd at set{#2}%
+          {\csname\ekv at name\ekvd at set{#2}N\endcsname}%
+          {\ekvd at err@undefined at noval{#2}}%
+      }%
+      {%
+        \ekvifdefined\ekvd at set{#2}%
+          {#1{\csname\ekv at name\ekvd at set{#2}\endcsname}{#3}}%
+          {\ekvd at err@undefined at key{#2}}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{bool,gbool,boolTF,gboolTF,invbool,ginvbool,invboolTF,ginvboolTF}
+% \begin{macro}[internal]{\ekvd at type@bool}
+% The boolean types are a quicker version of a |choice| that accept |true| and
+% |false|, and set up the |NoVal| action to be identical to \texttt{\key=true}.
+% The |true| and |false| actions are always just |\let|ting the macro in |#7| to
+% some other macro (\emph{e.g.}, \cs[no-index]{iftrue}).
+%    \begin{macrocode}
+\ekvd at def@type at fwd{bool}{\ekvd at type@bool{}\iftrue\iffalse}
+\ekvd at def@type at fwd{gbool}{\ekvd at type@bool\global\iftrue\iffalse}
+\ekvd at def@type at fwd{boolTF}{\ekvd at type@bool{}\@firstoftwo\@secondoftwo}
+\ekvd at def@type at fwd{gboolTF}{\ekvd at type@bool\global\@firstoftwo\@secondoftwo}
+\ekvd at def@type at fwd{invbool}{\ekvd at type@bool{}\iffalse\iftrue}
+\ekvd at def@type at fwd{ginvbool}{\ekvd at type@bool\global\iffalse\iftrue}
+\ekvd at def@type at fwd{invboolTF}{\ekvd at type@bool{}\@secondoftwo\@firstoftwo}
+\ekvd at def@type at fwd{ginvboolTF}{\ekvd at type@bool\global\@secondoftwo\@firstoftwo}
+\protected\def\ekvd at type@bool#1#2#3#4#5%
+  {%
+    \ekvd at do@new{}{#4}%
+    \ekvd at do@new{NoVal}{#4}%
+    \ekvd at assert@filledarg{#5}%
+    \ekvd at newlet#5#3%
+    \ekvd at type@choice{#4}%
+    \protected\ekvdefNoVal\ekvd at set{#4}{#1\let#5#2}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{true}\endcsname
+      {#1\let#5#2}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{false}\endcsname
+      {#1\let#5#3}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{boolpair,gboolpair,boolpairTF,gboolpairTF}
+% \begin{macro}[internal]{\ekvd at type@boolpair}
+% The boolean pair types are essentially the same as the boolean types, but set
+% two macros instead of one.
+%    \begin{macrocode}
+\ekvd at def@type{boolpair}
+  {\ekvd at assert@twoargs{#3}\ekvd at type@boolpair{}\iftrue\iffalse{#1}#3}
+\ekvd at def@type{gboolpair}
+  {\ekvd at assert@twoargs{#3}\ekvd at type@boolpair\global\iftrue\iffalse{#1}#3}
+\ekvd at def@type{boolpairTF}
+  {\ekvd at assert@twoargs{#3}\ekvd at type@boolpair{}\@firstoftwo\@secondoftwo{#1}#3}
+\ekvd at def@type{gboolpairTF}
+  {%
+    \ekvd at assert@twoargs{#3}%
+    \ekvd at type@boolpair\global\@firstoftwo\@secondoftwo{#1}#3%
+  }
+\protected\def\ekvd at type@boolpair#1#2#3#4#5#6%
+  {%
+    \ekvd at do@new{}{#4}%
+    \ekvd at do@new{NoVal}{#4}%
+    \ekvd at newlet#5#3%
+    \ekvd at newlet#6#2%
+    \ekvd at type@choice{#4}%
+    \protected\ekvdefNoVal\ekvd at set{#4}{#1\let#5#2#1\let#6#3}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{true}\endcsname
+      {#1\let#5#2#1\let#6#3}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{false}\endcsname
+      {#1\let#5#3#1\let#6#2}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{data,gdata,dataT,gdataT}
+% \begin{macro}[internal]{\ekvd at type@data}
+%    \begin{macrocode}
+\ekvd at def@type at fwd{data}
+  {\ekvd at type@data\@secondoftwo\edef{####2}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{edata}
+  {%
+    \ekvd at type@data\@secondoftwo\edef
+      {####2}{\ekv at unexpanded\ekv at expanded{{##1}}}%
+  }
+\ekvd at def@type at fwd{gdata}
+  {\ekvd at type@data\@secondoftwo\xdef{####2}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{xdata}
+  {%
+    \ekvd at type@data\@secondoftwo\xdef
+      {####2}{\ekv at unexpanded\ekv at expanded{{##1}}}%
+  }
+\ekvd at def@type at fwd{dataT}{\ekvd at type@data\@gobble\edef{}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{edataT}
+  {\ekvd at type@data\@gobble\edef{}{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\ekvd at def@type at fwd{gdataT}{\ekvd at type@data\@gobble\xdef{}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{xdataT}
+  {\ekvd at type@data\@gobble\xdef{}{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\protected\def\ekvd at type@data#1#2#3#4#5#6%
+  {%
+    \ekvd at do@new{}{#5}%
+    \ekvd at assert@filledarg{#6}%
+    \ekvd at newlet#6#1%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#5}{\long#2#6####1#3{####1{#4}}}{}%
+      }%
+      {%
+        \protected\ekvd at long\ekvdef\ekvd at set{#5}%
+          {\long#2#6####1#3{####1{#4}}}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{box,gbox}
+% \begin{macro}[internal]{\ekvd at type@box}
+% Set up our boxes. Though we're a generic package we want to be colour safe, so
+% we put an additional grouping level inside the box contents, for the case that
+% someone uses \pkg{color}. |\ekvd at newreg| is a small wrapper which tests
+% whether the first argument is defined and if not does
+% |\csname new#2\endcsname#1|.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{box}{\ekvd at type@box{}}
+\ekvd at def@type at fwd{gbox}{\ekvd at type@box\global}
+\protected\def\ekvd at type@box#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@filledarg{#3}%
+    \ekvd at newreg#3{box}%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#2}{#1\setbox#3=\hbox{\begingroup##1\endgroup}}{}%
+      }%
+      {%
+        \protected\ekvd at long\ekvdef\ekvd at set{#2}%
+          {#1\setbox#3=\hbox{\begingroup##1\endgroup}}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{toks,gtoks}
+% \begin{macro}[internal]{\ekvd at type@toks}
+% Similar to |box|, but set the |toks|.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{toks}{\ekvd at type@toks{}}
+\ekvd at def@type at fwd{gtoks}{\ekvd at type@toks\global}
+\protected\def\ekvd at type@toks#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@filledarg{#3}%
+    \ekvd at newreg#3{toks}%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#2}{#1#3={##1}}{}%
+      }%
+      {\protected\ekvd at long\ekvdef\ekvd at set{#2}{#1#3={##1}}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd at type@preapptoks,\ekvd at t@apptoks,\ekvd at t@gapptoks}
+% Just like |toks|, but expand the current contents of the |toks| register to
+% append the new contents.
+%    \begin{macrocode}
+\ekvd at ifprimitive\toksapp
+  {%
+    \ekvd at def@type at fwd{apptoks}{\ekvd at type@preapptoks\toksapp}
+    \ekvd at def@type at fwd{gapptoks}{\ekvd at type@preapptoks\gtoksapp}
+    \ekvd at def@type at fwd{pretoks}{\ekvd at type@preapptoks\tokspre}
+    \ekvd at def@type at fwd{gpretoks}{\ekvd at type@preapptoks\gtokspre}
+    \protected\def\ekvd at type@preapptoks#1#2#3%
+      {%
+        \ekvd at do@new{}{#2}%
+        \ekvd at assert@filledarg{#3}%
+        \ekvd at newreg#3{toks}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#2}{#1#3{##1}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#2}{#1#3{##1}}}%
+      }
+  }
+  {%
+    \ekvd at def@type at fwd{apptoks}{\ekvd at type@apptoks{}}
+    \ekvd at def@type at fwd{gapptoks}{\ekvd at type@apptoks\global}
+    \protected\def\ekvd at type@apptoks#1#2#3%
+      {%
+        \ekvd at do@new{}{#2}%
+        \ekvd at assert@filledarg{#3}%
+        \ekvd at newreg#3{toks}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#2}{#1#3=\expandafter{\the#3##1}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#2}%
+              {#1#3=\expandafter{\the#3##1}}%
+          }%
+      }
+    \ekvd at def@type at fwd{pretoks}{\ekvd at type@pretoks{}}
+    \ekvd at def@type at fwd{gpretoks}{\ekvd at type@pretoks\global}
+    \newtoks\ekvd at toks
+    \protected\def\ekvd at type@pretoks#1#2#3%
+      {%
+        \ekvd at do@new{}{#2}%
+        \ekvd at assert@filledarg{#3}%
+        \ekvd at newreg#3{toks}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#2}%
+              {#1#3=\ekv at expanded{{\ekv at unexpanded{##1}\the#3}}}%
+              {}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#2}%
+              {#1#3=\ekv at expanded{{\ekv at unexpanded{##1}\the#3}}}%
+          }%
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {int,eint,gint,xint,dimen,edimen,gdimen,xdimen,skip,eskip,gskip,xskip}
+% \begin{macro}[internal]{\ekvd at type@register}
+% The |\ekvd at type@register| can handle all the types for which the assignment will
+% just be \texttt{\meta{register}=\meta{value}}.
+%    \begin{macrocode}
+\ekvd at def@type at fwd {int}{\ekvd at type@register{count}{}{}}
+\ekvd at def@type at fwd{eint}{\ekvd at type@register{count}{}\numexpr}
+\ekvd at def@type at fwd{gint}{\ekvd at type@register{count}\global{}}
+\ekvd at def@type at fwd{xint}{\ekvd at type@register{count}\global\numexpr}
+\ekvd at def@type at fwd {dimen}{\ekvd at type@register{dimen}{}{}}
+\ekvd at def@type at fwd{edimen}{\ekvd at type@register{dimen}{}\dimexpr}
+\ekvd at def@type at fwd{gdimen}{\ekvd at type@register{dimen}\global{}}
+\ekvd at def@type at fwd{xdimen}{\ekvd at type@register{dimen}\global\dimexpr}
+\ekvd at def@type at fwd {skip}{\ekvd at type@register{skip}{}{}}
+\ekvd at def@type at fwd{eskip}{\ekvd at type@register{skip}{}\glueexpr}
+\ekvd at def@type at fwd{gskip}{\ekvd at type@register{skip}\global{}}
+\ekvd at def@type at fwd{xskip}{\ekvd at type@register{skip}\global\glueexpr}
+\protected\def\ekvd at type@register#1#2#3#4#5%
+  {%
+    \ekvd at do@new{}{#4}%
+    \ekvd at assert@filledarg{#5}%
+    \ekvd at newreg#5{#1}%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#4}{#2#5=#3##1\relax}{}%
+      }%
+      {\protected\ekvd at long\ekvdef\ekvd at set{#4}{#2#5=#3##1\relax}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{store,gstore,estore,xstore}
+% \begin{macro}[internal]{\ekvd at type@store}
+% The none-expanding |store| types use an |\edef| or |\xdef| and |\unexpanded|
+% to be able to also store |#| easily.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{store}{\ekvd at type@store\edef{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{gstore}{\ekvd at type@store\xdef{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{estore}
+  {\ekvd at type@store\edef{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\ekvd at def@type at fwd{xstore}
+  {\ekvd at type@store\xdef{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\protected\def\ekvd at type@store#1#2#3#4%
+  {%
+    \ekvd at do@new{}{#3}%
+    \ekvd at assert@filledarg{#4}%
+    \ekvd at newlet#4\ekv at empty
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#3}{#1#4{#2}}{}%
+      }%
+      {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#1#4{#2}}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{meta,nmeta}
+% \begin{macro}[internal]{\ekvd at type@meta}
+% |meta| sets up things such that another instance of |\ekvset| will be run on
+% the argument, with the same \set.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{meta}
+  {\ekvd at type@meta{}{##1}\ekvd at add@val{{##1}}{}\ekv at exparg}
+\ekvd at def@type at fwd{nmeta}
+  {%
+    \ekvd at assert@not at long
+    \ekvd at type@meta
+      {NoVal}{}\ekvd at add@noval{}\ekvd at assert@not at long@also\ekv at expargtwice
+  }
+\protected\long\def\ekvd at type@meta#1#2#3#4#5#6#7#8%
+  {%
+    \ekvd at do@new{#1}{#7}%
+    \ekvd at assert@filledarg{#8}%
+    #6{\ekvd at prot\ekvd at long\def\ekvd at tmp#2}{\ekvmorekv{#8}}%
+    \ekvd at ifalso
+      {\ekv at exparg{#3{#7}}{\ekvd at tmp#4}{#5}}%
+      {\csname ekvlet#1\endcsname\ekvd at set{#7}\ekvd at tmp}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{smeta,snmeta}
+% \begin{macro}[internal]
+%   {\ekvd at type@smeta,\ekvd at type@smeta@}
+% |smeta| is pretty similar to |meta|, but needs two arguments inside of \val,
+% such that the first is the \set\ for which the sub-|\ekvset| and the second is
+% the \kv\ list.
+%    \begin{macrocode}
+\ekvd at def@type at fwd{smeta}{\ekvd at type@smeta{}{##1}\ekvd at add@val{{##1}}{}}
+\ekvd at def@type at fwd{snmeta}
+  {%
+    \ekvd at assert@not at long
+    \ekvd at type@smeta{NoVal}{}\ekvd at add@noval{}\ekvd at assert@not at long@also
+  }
+\protected\long\def\ekvd at type@smeta#1#2#3#4#5#6#7%
+  {%
+    \ekvd at do@new{#1}{#6}%
+    \ekvd at assert@twoargs{#7}%
+    \ekvd at type@smeta@#7{#2}%
+    \ekvd at ifalso
+      {\ekv at exparg{#3{#6}}{\ekvd at tmp#4}{#5}}%
+      {\csname ekvlet#1\endcsname\ekvd at set{#6}\ekvd at tmp}%
+  }
+\protected\long\def\ekvd at type@smeta@#1#2#3%
+  {\ekvd at prot\ekvd at long\ekv at expargtwice{\def\ekvd at tmp#3}{\ekvset{#1}{#2}}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{choice}
+% \begin{macro}[internal]{\ekvd at type@choice,\ekvd at populate@choice}
+%   The real key definition of a |choice| type is pretty simple, the heavy
+%   lifting is done by a helper macro at run time. Though setting up the choices
+%   needs a bit of work. First the key macro definition.
+%    \begin{macrocode}
+\protected\def\ekvd at type@choice#1%
+  {%
+    \ekvd at assert@not at long
+    \ekv at expargtwice{\ekvd at prot\def\ekvd at tmp##1}%
+      {%
+        \expandafter\expandafter\expandafter
+        \ekvd at h@choice
+        \expandafter\expandafter\expandafter
+          {\expandafter\ekvd at choice@name\expandafter{\ekvd at set}{#1}{##1}}%
+      }%
+    \ekvd at ifalso
+      {%
+        \ekvd at assert@val{#1}%
+        \ekvd at if@not at already@choice{#1}%
+          {%
+            \ekv at exparg
+              {%
+                \expandafter\ekvd at add@aux
+                  \csname\ekv at name\ekvd at set{#1}\endcsname{{##1}}{#1}%
+              }%
+              {\ekvd at tmp{##1}}%
+              {\ekvd at long\ekvdef}\ekvd at assert@not at long@also
+          }%
+      }%
+      {\ekvlet\ekvd at set{#1}\ekvd at tmp}%
+  }
+%    \end{macrocode}
+%   The set up of different choices is done through another parser, that one
+%   needs relatively few types though.
+%    \begin{macrocode}
+\ekvpNewParser{ekvd at populate@choice}
+\ekvpValueAlwaysRequired{ekvd at populate@choice}
+\ekvpDefType{ekvd at populate@choice}{protect}
+  {\ekvd at populate@choice\protected{#1}{#3}}
+\ekvpDefType{ekvd at populate@choice}{unprotect}{\ekvd at populate@choice{}{#1}{#3}}
+\ekvpDefNoType{ekvd at populate@choice}         {\ekvd at populate@choice{}{#1}{#3}}
+\ekvpLet{ekvd at populate@choice}{type}{protected}{protect}
+\ekvpLet{ekvd at populate@choice}{type}{unprotected}{unprotect}
+%    \end{macrocode}
+%   The choice definition is done by the following little helper:
+%    \begin{macrocode}
+\protected\long\def\ekvd at populate@choice#1#2#3%
+  {%
+    #1\expandafter\edef
+        \csname\ekvd at choice@name\ekvd at set\ekvd at set@choice{#2}\endcsname
+      {\ekv at unexpanded{#3}}%
+  }
+%    \end{macrocode}
+%   And we define the real type:
+%    \begin{macrocode}
+\ekvd at def@type{choice}
+  {%
+    \ekvd at do@new{}{#1}%
+    \ekvd at assert@arg
+    \ekvd at type@choice{#1}%
+    \def\ekvd at set@choice{#1}%
+    \ekvpParse at unsafe\ekvp@@p at ekvd@populate at choice{#3}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% 
+% \begin{macro}{choice-store,choice-enum}
+%   These two types define a special kind of |choice| key and are quite similar,
+%   the only difference is what the different choices do (hence they use a
+%   shared initialisation which differs in the chosen |populate| step).
+%    \begin{macrocode}
+\ekvd at def@type at fwd{choice-store}
+  {\ekvd at type@choicespecial\ekvd at populate@choicestore}
+\ekvd at def@type at fwd{choice-enum}
+  {\ekvd at type@choicespecial\ekvd at populate@choiceenum}
+%    \end{macrocode}
+% \begin{macro}[internal]{\ekvd at type@choicespecial}
+%   Initialise similar to a |choice| key. The difference is that we require two
+%   arguments (which we assert), a macro to store things in, and a |csv|-list
+%   containing the allowed values. |#1| is the |populate| macro according to the
+%   type used.
+%    \begin{macrocode}
+\protected\long\def\ekvd at type@choicespecial#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@twoargs{#3}%
+    \ekvd at type@choice{#2}%
+    \def\ekvd at set@choice{#2}%
+    #1#3%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {\ekvd at populate@choicestore,\ekvd at populate@choicestore@}
+%   We initialise the storing macro if it doesn't yet exist, and then we loop
+%   over the value list. The |\edef|s with |\unexpanded| are both necessary to
+%   be able to store macro parameter tokens (the outer protects at define time,
+%   the inner at use time).
+%    \begin{macrocode}
+\protected\long\def\ekvd at populate@choicestore#1%
+  {%
+    \ekvd at newlet#1\ekv at empty
+    \ekvparse{\ekvd at populate@choicestore at k#1}{\ekvd at populate@choicestore at kv#1}%
+  }
+\protected\long\def\ekvd at populate@choicestore at kv#1#2#3%
+  {%
+    \protected\expandafter\edef
+      \csname\ekvd at choice@name\ekvd at set\ekvd at set@choice{#2}\endcsname
+      {\ekv at unexpanded{\edef#1{\ekv at unexpanded{#3}}}}%
+  }
+\ekv at exparg{\protected\long\def\ekvd at populate@choicestore at k#1#2}%
+  {\ekvd at populate@choicestore at kv{#1}{#2}{#2}}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {\ekvd at populate@choiceenum,\ekvd at populate@choiceenum@}
+%   This is similar to the population of a |choice-store| type, but instead of
+%   storing the values in a macro this initialises a count and stores the
+%   position of the value in the list inside that count (zero-indexed). The
+%   space is necessary to terminate the number scanning, which is the reason we
+%   use |\@firstofone| (so that the space after the macro name isn't gobbled by
+%   \TeX).
+%    \begin{macrocode}
+\protected\long\def\ekvd at populate@choiceenum#1%
+  {%
+    \ekvd at newreg#1{count}%
+    \def\ekvd at tmp{0}%
+    \ekvcsvloop{\ekvd at populate@choiceenum@#1}%
+  }
+\protected\long\def\ekvd at populate@choiceenum@#1#2%
+  {%
+    \protected\expandafter\edef
+      \csname\ekvd at choice@name\ekvd at set\ekvd at set@choice{#2}\endcsname
+      {#1=\@firstofone{\ekvd at tmp} }%
+    \edef\ekvd at tmp{\the\numexpr\ekvd at tmp+1\relax}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{unknown-choice}
+%    \begin{macrocode}
+\ekvd at def@type{unknown-choice}
+  {%
+    \ekvd at do@new at for@name{\ekvd at unknown@choice at name\ekvd at set{#1}}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at long
+    \ekvd at assert@not at also
+    \ekvd at prot\expandafter
+    \def\csname\ekvd at unknown@choice at name\ekvd at set{#1}\endcsname##1{#3}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{unknown}
+% \begin{macro}[internal]{\ekvd at type@unknown at code,\ekvd at type@unknown at noval}
+%   The |unknown| type has different subtypes which would be the key names for
+%   other types. It is first checked whether that subtype is defined, if it
+%   isn't throw an error, else use that subtype.
+%    \begin{macrocode}
+\ekvd at def@type{unknown}
+  {%
+    \ekv at ifdefined{ekvd at type@unknown@\detokenize{#1}}%
+      {\csname ekvd at type@unknown@\detokenize{#1}\endcsname{#3}}%
+      \ekvd at err@misused at unknown
+  }
+%    \end{macrocode}
+%   The |unknown noval| type can use |\ekvdefunknownNoVal| directly (after
+%   asserting some prefixes).
+%    \begin{macrocode}
+\protected\long\def\ekvd at type@unknown at noval#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}uN}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \ekvd at prot\ekvd at long\ekvdefunknownNoVal\ekvd at set{#1}%
+  }
+%    \end{macrocode}
+%   The |unknown code| type uses some trickery during the definition in order to
+%   swap out |#1| and |#2| in the user supplied definition. This is done via a
+%   temporary macro that stores the definition but gets the parameter numbers
+%   reversed while the real definition is done.
+%    \begin{macrocode}
+\protected\long\def\ekvd at type@unknown at code#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}u}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \begingroup
+      \def\ekvd at tmp##1##2##3{#1}%
+      \ekv at exparg
+      {%
+        \endgroup
+        \ekvd at prot\ekvd at long\ekvdefunknown\ekvd at set
+      }%
+      {\ekvd at tmp{##2}{##1}{##3}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at type@unknown at redirect,
+%     \ekvd at type@unknown at redirect-code,
+%     \ekvd at type@unknown at redirect-noval
+%   }
+%   The |unknown redirect| types also just forward to |\ekvredirectunknown|
+%   after asserting some prefixes.
+%    \begin{macrocode}
+\protected\edef\ekvd at type@unknown at redirect#1%
+  {%
+    \expandafter\noexpand\csname ekvd at type@unknown at redirect-code\endcsname{#1}%
+    \expandafter\noexpand\csname ekvd at type@unknown at redirect-noval\endcsname{#1}%
+  }
+\protected\expandafter\def\csname ekvd at type@unknown at redirect-code\endcsname#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}u}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \ekvd at assert@not at protected
+    \expandafter\ekvredirectunknown\expandafter{\ekvd at set}{#1}%
+  }
+\protected\expandafter\def\csname ekvd at type@unknown at redirect-noval\endcsname#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}uN}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \ekvd at assert@not at protected
+    \expandafter\ekvredirectunknownNoVal\expandafter{\ekvd at set}{#1}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Key Type Helpers}
+% There are some keys that might need helpers during their execution (not during
+% their definition, which are gathered as |@type@| macros). These helpers are
+% named |@h@|.
+%
+% \begin{macro}[internal]{\ekvd at h@choice,\ekvd at h@choice@}
+% The |choice| helper will just test whether the given choice was defined, if
+% not throw an error expandably, else call the macro which stores the code for
+% this choice.
+%    \begin{macrocode}
+\def\ekvd at h@choice#1%
+  {%
+    \expandafter\ekvd at h@choice@
+      \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
+      {#1}%
+  }
+\def\ekvd at h@choice@#1#2%
+  {%
+    \ifx#1\relax
+      \ekvd at err@choice at invalid{#2}%
+      \expandafter\@gobble
+    \fi
+    #1%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Handling \texttt{also}}
+%
+% \begin{macro}[internal]
+%   {\ekvd at add@val,\ekvd at add@noval,\ekvd at add@aux,\ekvd at add@aux@}
+%    \begin{macrocode}
+\protected\long\def\ekvd at add@val#1#2#3%
+  {%
+    \ekvd at assert@val{#1}%
+    \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}\endcsname{{##1}}%
+      {#1}{#2}{\ekvd at long\ekvdef}{#3}%
+  }
+\protected\long\def\ekvd at add@noval#1#2#3%
+  {%
+    \ekvd at assert@noval{#1}%
+    \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}N\endcsname{}%
+      {#1}{#2}\ekvdefNoVal{#3}%
+  }
+\protected\long\def\ekvd at add@aux#1#2%
+  {%
+    \ekvd at extract@prefixes#1%
+    \expandafter\ekvd at add@aux@\expandafter{#1#2}%
+  }
+%    \end{macrocode}
+%   Once we're done with adding something to the definition of a key we need to
+%   clear the prefixes. Maybe it would be better to only restore them if they
+%   were changed by the |\ekvd at extract@prefixes| mechanism, but I think this is
+%   fine with just resetting all (there should be no code dependent on any of
+%   the prefix storing macros after this was run).
+%    \begin{macrocode}
+\protected\long\def\ekvd at add@aux@#1#2#3#4#5%
+  {%
+    #5%
+    \ekvd at prot#4\ekvd at set{#2}{#1#3}%
+    \ekvd at clear@prefixes
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at extract@prefixes,\ekvd at extract@prefixes@,
+%     \ekvd at extract@prefixes at long,\ekvd at extract@prefixes at prot
+%   }
+% This macro checks which prefixes were used for the definition of a macro and
+% sets |\ekvd at long| and |\ekvd at prot| accordingly.
+%    \begin{macrocode}
+\protected\def\ekvd at extract@prefixes#1%
+  {%
+    \expandafter\ekvd at extract@prefixes@\meaning#1\ekvd at stop
+  }
+%    \end{macrocode}
+% In the following definition |#1| will get replaced by |macro:|, |#2| by
+% |\long| and |#3| by |\protected| (in each, all tokens will have category
+% other). This allows us to parse the |\meaning| of a macro for those strings.
+%    \begin{macrocode}
+\protected\def\ekvd at extract@prefixes@#1#2#3%
+  {%
+    \protected\def\ekvd at extract@prefixes@##1#1##2\ekvd at stop
+      {%
+        \ekvd at extract@prefixes at long
+          ##1\ekvd at mark\@firstofone#2\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at long\long}%
+        \ekvd at extract@prefixes at prot
+          ##1\ekvd at mark\@firstofone#3\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at prot\protected}%
+      }%
+    \protected\def\ekvd at extract@prefixes at long##1#2##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+    \protected\def\ekvd at extract@prefixes at prot##1#3##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+  }
+%    \end{macrocode}
+% We use a temporary macro to expand the three arguments of
+% |\ekvd at extract@prefixes@|, which will set up the real meaning of itself and
+% the parsing for |\long| and |\protected|.
+%    \begin{macrocode}
+\begingroup
+\edef\ekvd at tmp
+  {%
+    \endgroup
+    \ekvd at extract@prefixes@
+      {\detokenize{macro:}}%
+      {\string\long}%
+      {\string\protected}%
+  }
+\ekvd at tmp
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Tests}
+%
+% \begin{macro}[internal]{\ekvd at newlet,\ekvd at newreg}
+% These macros test whether a control sequence is defined, if it isn't they
+% define it, either via |\let| or via the correct \cs[no-index]{new\meta{reg}}.
+%    \begin{macrocode}
+\protected\def\ekvd at newlet#1#2%
+  {%
+    \ifdefined#1%
+      \ifx#1\relax\ekv at fi@gobble\fi\@firstofone
+      \ekv at fi@gobble
+    \fi
+    \@firstofone{\let#1#2}%
+  }
+\protected\def\ekvd at newreg#1#2%
+  {%
+    \ifdefined#1%
+      \ifx#1\relax\ekv at fi@gobble\fi\@firstofone
+      \ekv at fi@gobble
+    \fi
+    \@firstofone{\csname new#2\endcsname#1}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekvd at assert@twoargs,\ekvd at ifnottwoargs,\ekvd at ifempty@gtwo}
+% A test for exactly two tokens can be reduced for an empty-test after gobbling
+% two tokens, in the case that there are fewer tokens than two in the argument,
+% only macros will be gobbled that are needed for the true branch, which doesn't
+% hurt, and if there are more this will not be empty.
+%    \begin{macrocode}
+\long\def\ekvd at assert@twoargs#1%
+  {\ekvd at ifnottwoargs{#1}{\ekvd at err@missing at definition\ekvpGobbleT}{}}
+\long\def\ekvd at ifnottwoargs#1%
+  {%
+    \ekvd at ifempty@gtwo#1\ekv at ifempty@B
+      \ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+  }
+\long\def\ekvd at ifempty@gtwo#1#2{\ekv at ifempty@\ekv at ifempty@A}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at assert@val,\ekvd at assert@val@,\ekvd at assert@noval,\ekvd at assert@noval@,
+%     \ekvd at extract@args,\ekvd at extracted@args,\ekvd at one@arg at string
+%   }
+% Assert that a given key is defined as a value taking key or a |NoVal| key with
+% the correct argument structure, respectively.
+%    \begin{macrocode}
+\protected\def\ekvd at assert@val#1%
+  {%
+    \ekvifdefined\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@val@\csname\ekv at name\ekvd at set{#1}\endcsname}%
+      {%
+        \ekvifdefinedNoVal\ekvd at set{#1}%
+          \ekvd at err@add at val@on at noval
+          {\ekvd at err@undefined at key{#1}}%
+        \ekvpGobbleT
+      }%
+  }
+\protected\def\ekvd at assert@val@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekvd at one@arg at string
+      \ekvd at err@unsupported at arg
+      \expandafter\ekvpGobbleT
+    \fi
+  }%
+\protected\def\ekvd at assert@noval#1%
+  {%
+    \ekvifdefinedNoVal\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@noval@\csname\ekv at name\ekvd at set{#1}N\endcsname}%
+      {%
+        \ekvifdefined\ekvd at set{#1}%
+          \ekvd at err@add at noval@on at val
+          {\ekvd at err@undefined at key{#1}}%
+        \ekvpGobbleT
+      }%
+  }
+\protected\def\ekvd at assert@noval@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekv at empty
+      \ekvd at err@unsupported at arg
+      \expandafter\ekvpGobbleT
+    \fi
+  }
+\protected\def\ekvd at extract@args#1%
+  {%
+    \protected\def\ekvd at extract@args##1#1##2->##3\ekvd at stop
+      {\def\ekvd at extracted@args{##2}}%
+  }
+\expandafter\ekvd at extract@args\expandafter{\detokenize{macro:}}
+\edef\ekvd at one@arg at string{\string#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd at assert@arg,\ekvd at ifnoarg}
+% The |\ekvd at ifnoarg| macro is initialised as |\@secondoftwo|. Each time a key
+% without an argument is encountered it will be set to |\@firstoftwo| for the
+% scope of that key's parsing.
+%    \begin{macrocode}
+\def\ekvd at assert@arg{\ekvd at ifnoarg{\ekvd at err@missing at definition\ekvpGobbleT}{}}
+\let\ekvd at ifnoarg\@secondoftwo
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd at assert@filledarg,\ekvd at ifnoarg@or at empty}
+%    \begin{macrocode}
+\long\def\ekvd at assert@filledarg#1%
+  {\ekvd at ifnoarg@or at empty{#1}{\ekvd at err@missing at definition\ekvpGobbleT}{}}
+\long\def\ekvd at ifnoarg@or at empty#1%
+  {%
+    \ekvd at ifnoarg
+      \@firstoftwo
+      {\ekv at ifempty{#1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at assert@not at long,\ekvd at assert@not at protected,\ekvd at assert@not at also,
+%     \ekvd at assert@not at long@also,\ekvd at assert@not at protected@also,
+%     \ekvd at assert@new,\ekvd at assert@not at new
+%   }
+% Some key-types don't want to be |also|, |\long| or |\protected|, so we provide
+% macros to test this and throw an error, this could be silently ignored but now
+% users will learn to not use unnecessary stuff which slows the compilation
+% down.
+%    \begin{macrocode}
+\def\ekvd at assert@not at long{\ifx\ekvd at long\long\ekvd at err@no at prefix{long}\fi}
+\def\ekvd at assert@not at protected
+  {\ifx\ekvd at prot\protected\ekvd at err@no at prefix{protected}\fi}
+\def\ekvd at assert@not at also{\ekvd at ifalso{\ekvd at err@no at prefix{also}}{}}
+\def\ekvd at assert@not at long@also
+  {\ifx\ekvd at long\long\ekvd at err@no at prefix@also{long}\fi}
+\def\ekvd at assert@not at protected@also
+  {\ifx\ekvd at prot\protected\ekvd at err@no at prefix@also{protected}\fi}
+\def\ekvd at assert@new#1#2%
+  {%
+    \csname ekvifdefined#1\endcsname\ekvd at set{#2}%
+      {\ekvd at err@not at new\ekvpGobbleT}%
+      {}%
+  }
+\def\ekvd at assert@not at new
+  {\ifx\ekvd at do@new\ekvd at assert@new\ekvd at err@no at prefix{new}\fi}
+\def\ekvd at do@new at for@name#1%
+  {%
+    \ifx\ekvd at do@new\ekvd at assert@new
+      \ekv at fi@firstofone
+    \fi
+    \@gobble{\ekv at ifdefined{#1}{\ekvd at err@not at new\ekvpGobbleT}{}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at if@not at already@choice, \ekvd at if@not at already@choice at a,
+%     \ekvd at if@not at already@choice at b
+%   }
+% It is bad to use |also| on a key that already contains a |choice|, as both
+% choices would share the same valid values and thus lead to each callback being
+% used twice. The following is a rudimentary test against this.
+%    \begin{macrocode}
+\protected\def\ekvd at if@not at already@choice#1%
+  {%
+    \expandafter\ekvd at if@not at already@choice at a
+      \csname\ekv at name\ekvd at set{#1}\endcsname
+      {}\ekvd at h@choice\ekvd at stop
+  }
+\protected\def\ekvd at if@not at already@choice at a
+  {%
+    \expandafter\ekvd at if@not at already@choice at b
+  }
+\long\protected\def\ekvd at if@not at already@choice at b#1\ekvd at h@choice#2\ekvd at stop
+  {%
+    \ekv at ifempty{#2}\@firstofone\@gobble
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd at ifspace,\ekvd at ifspace@}
+% Yet another test which can be reduced to an if-empty, this time by gobbling
+% everything up to the first space.
+%    \begin{macrocode}
+\long\def\ekvd at ifspace#1%
+  {%
+    \ekvd at ifspace@#1 \ekv at ifempty@B
+      \ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+  }
+\long\def\ekvd at ifspace@#1 % keep this space
+  {%
+    \ekv at ifempty@\ekv at ifempty@A
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Messages}
+%
+% Most messages of \expkvd\ are not expandable, since they only appear during
+% key-definition, which is not expandable anyway.
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at errm,\ekvd at err@missing at definition,
+%     \ekvd at err@missing at type,\ekvd at err@undefined at prefix,\ekvd at err@undefined at key,
+%     \ekvd at err@no at prefix,\ekvd at err@no at prefix@also,
+%     \ekvd at err@add at val@on at noval,\ekvd at err@add at noval@on at val,
+%     \ekvd at err@unsupported at arg,\ekvd at err@not at new
+%   }
+% The non-expandable error messages are boring, so here they are:
+%    \begin{macrocode}
+\protected\long\def\ekvd at errm#1{\errmessage{expkv-def Error: #1}}
+\protected\def\ekvd at err@missing at definition
+  {\ekvd at errm{Missing definition for key `\ekvd at cur'}}
+\protected\def\ekvd at err@missing at type
+  {\ekvd at errm{Missing type prefix for key `\ekvd at cur'}}
+\protected\def\ekvd at err@undefined at prefix#1%
+  {%
+    \ekvd at errm
+      {%
+        Undefined prefix `\ekv at unexpanded{#1}' found while processing
+        `\ekvd at cur'%
+      }%
+  }
+\protected\def\ekvd at err@undefined at key#1%
+  {%
+    \ekvd at errm
+      {Undefined key `\ekv at unexpanded{#1}' found while processing `\ekvd at cur'}%
+  }
+\protected\def\ekvd at err@undefined at noval#1%
+  {%
+    \ekvd at errm
+      {%
+        Undefined noval key `\ekv at unexpanded{#1}' found while processing
+        `\ekvd at cur'%
+      }%
+  }
+\protected\def\ekvd at err@no at prefix#1%
+  {\ekvd at errm{prefix `#1' not accepted in `\ekvd at cur'}}
+\protected\def\ekvd at err@no at prefix@also#1%
+  {\ekvd at errm{`\ekvd at cur' not allowed with a `#1' key}}
+\protected\def\ekvd at err@add at val@on at noval
+  {\ekvd at errm{`\ekvd at cur' not allowed with a NoVal key}}
+\protected\def\ekvd at err@add at noval@on at val
+  {\ekvd at errm{`\ekvd at cur' not allowed with a value taking key}}
+\protected\def\ekvd at err@unsupported at arg
+  {%
+    \ekvd at errm
+      {%
+        Existing key-macro has the unsupported argument string
+        `\ekvd at extracted@args' for key `\ekvd at cur'%
+      }%
+  }
+\protected\def\ekvd at err@not at new
+  {\ekvd at errm{The key for `\ekvd at cur' is already defined}}
+\protected\long\def\ekvd at err@misused at unknown
+  {\ekvd at errm{Misuse of the unknown type found while processing `\ekvd at cur'}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at err@choice at invalid,\ekvd at err@choice at invalid@,\ekvd at choice@name,
+%     \ekvd at unknown@choice at name
+%   }
+% |\ekvd at err@choice at invalid| will have to use this mechanism to throw its
+% message. Also we have to retrieve the name parts of the choice in an easy way,
+% so we use parentheses of catcode 8 here, which should suffice in most cases to
+% allow for a correct separation.
+%    \begin{macrocode}
+\def\ekvd at err@choice at invalid#1%
+  {%
+    \ekvd at err@choice at invalid@#1%
+  }
+\begingroup
+\catcode40=8
+\catcode41=8
+\@firstofone{\endgroup
+\def\ekvd at choice@name#1#2#3%
+  {%
+    ekvd#1(#2)\detokenize{#3}%
+  }
+\def\ekvd at unknown@choice at name#1#2%
+  {%
+    ekvd:u:#1(#2)%
+  }
+\def\ekvd at err@choice at invalid@ ekvd#1(#2)\detokenize#3%
+  {%
+    \ekv at ifdefined{\ekvd at unknown@choice at name{#1}{#2}}%
+      {\csname\ekvd at unknown@choice at name{#1}{#2}\endcsname{#3}}%
+      {\ekvd at err{invalid choice `#3' for `#2' in set `#1'}}%
+  }
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd at err}
+% The expandable error messages use |\ekvd at err|, which is just like |\ekv at err|
+% from \expkv. It uses a runaway argument to start the error message.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekvd at err#1}{\ekverr{expkv-def}{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% Now everything that's left is to reset the category code of |@|.
+%    \begin{macrocode}
+\catcode`\@=\ekvd at tmp
+%    \end{macrocode}
+%
+% \gobbledocstriptag
+%</tex>
+%^^A=<<


Property changes on: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-def.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt-2020-10-10.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt-2020-10-10.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt-2020-10-10.dtx	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,940 @@
+% \iffalse meta-comment
+%
+% File: expkv-opt.dtx Copyright (C) 2020-2023 Jonathan P. Spratte
+%
+% This work  may be  distributed and/or  modified under  the conditions  of the
+% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+% (at your option) any later version.  The latest version of this license is in
+% the file:
+%
+%   http://www.latex-project.org/lppl.txt
+%
+% ------------------------------------------------------------------------------
+%
+%<*driver>^^A>>=
+\def\nameofplainTeX{plain}
+\ifx\fmtname\nameofplainTeX\else
+  \expandafter\begingroup
+\fi
+\input l3docstrip.tex
+\askforoverwritefalse
+\preamble
+
+--------------------------------------------------------------
+expkv-opt -- parse class and package options with expkv
+E-mail: jspratte at yahoo.de
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+--------------------------------------------------------------
+
+Copyright (C) 2020-2023 Jonathan P. Spratte
+
+This  work may be  distributed and/or  modified under  the conditions  of the
+LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+(at your option) any later version.  The latest version of this license is in
+the file:
+
+  http://www.latex-project.org/lppl.txt
+
+This work is "maintained" (as per LPPL maintenance status) by
+  Jonathan P. Spratte.
+
+This work consists of the file  expkv-opt.dtx
+and the derived files           expkv-opt.pdf
+                                expkv-opt.sty
+and the file                    expkv-opt-2020-10-10.dtx
+and the derived file            expkv-opt-2020-10-10.sty
+
+\endpreamble
+% stop docstrip adding \endinput
+\postamble
+\endpostamble
+\generate{\file{expkv-opt-2020-10-10.sty}{\from{expkv-opt-2020-10-10.dtx}{pkg}}}
+\ifx\fmtname\nameofplainTeX
+  \expandafter\endbatchfile
+\else
+  \expandafter\endgroup\expandafter\stop
+\fi
+%
+\IfFileExists{expkv-opt.sty}{\RequirePackage{expkv-opt}}{}
+\ProvidesFile{expkv-opt.dtx}
+  [\csname ekvoDate\endcsname\ parse class and package options with expkv]
+\PassOptionsToPackage{full}{textcomp}
+\documentclass{l3doc}
+\RequirePackage[oldstylenums,nott]{kpfonts}
+\input{glyphtounicode}
+\pdfgentounicode=1
+\RequirePackage{listings}
+\RequirePackage{booktabs}
+\RequirePackage{array}
+\RequirePackage{collcell}
+\RequirePackage{siunitx}
+\RequirePackage{xcolor}
+\RequirePackage{caption}
+\RequirePackage{microtype}
+\RequirePackage{accsupp}
+\lstset
+  {
+    ,flexiblecolumns=false
+    ,basewidth=.53em
+    ,gobble=2
+    ,basicstyle=\fontfamily{jkp}\itshape
+    ,morekeywords=^^A
+      {^^A
+        \ekvoProcessLocalOptions,
+        \ekvoProcessGlobalOptions,
+        \ekvoProcessUnusedGlobalOptions,
+        \ekvoProcessOptionsList,
+        \ekvoUseUnknownHandlers
+      }
+    ,morecomment=[l]\%
+    ,commentstyle=\color[gray]{0.4}
+    ,literate={\{}{{\CodeSymbol\{}}{1}
+              {\}}{{\CodeSymbol\}}}{1}
+    ^^A,literate=*{<key>}{\key}{4}{<set>}{\set}{4}
+  }
+\newcommand*\CodeSymbol[1]{\textbf{#1}}
+\RequirePackage{randtext}
+\let\metaORIG\meta
+\protected\def\meta #1{\texttt{\metaORIG{#1}}}
+\renewcommand*\thefootnote{\fnsymbol{footnote}}
+\definecolor{expkvred}{HTML}{9F393D}
+\colorlet{expkvgrey}{black!75}
+\makeatletter
+\newcommand*\expkv
+  {^^A
+    \texorpdfstring
+      {^^A
+        \mbox
+          {^^A
+            \BeginAccSupp{ActualText=expkv}^^A
+            \href{https://github.com/Skillmon/tex_expkv}
+              {^^A
+                \rmfamily
+                \bfseries
+                {\color{expkvgrey}e\kern-.05em x\kern-.05em}^^A
+                \lower.493ex
+                  \hbox{{\color{expkvgrey}P}\kern-.1em{\color{expkvred}k}}^^A
+                \kern-.18em{\color{expkvred}v}^^A
+              }^^A
+            \EndAccSupp{}^^A
+          }^^A
+      }
+      {expkv}^^A
+  }
+\newcommand*\expkvpkg[1]
+  {^^A
+    \texorpdfstring
+      {^^A
+        \mbox
+          {^^A
+            \BeginAccSupp{ActualText=expkv-#1}^^A
+            \href{https://github.com/Skillmon/tex_expkv-#1}
+              {^^A
+                \rmfamily
+                \bfseries
+                {\color{expkvgrey}e\kern-.05em x\kern-.05em}^^A
+                \lower.493ex
+                  \hbox{{\color{expkvgrey}P}\kern-.1em{\color{expkvred}k}}^^A
+                \kern-.18em{\color{expkvred}v}^^A
+                {\color{expkvgrey}^^A
+                  \kern.05em\rule[-.1ex]{.08em}{1.2ex}\kern.05em\textsc{#1}^^A
+                }^^A
+              }^^A
+            \EndAccSupp{}^^A
+          }^^A
+      }
+      {expkv-#1}^^A
+  }
+\newcommand*\expkvd{\expkvpkg{def}}
+\newcommand*\expkvc{\expkvpkg{cs}}
+\newcommand*\expkvo{\expkvpkg{opt}}
+\newcommand\kv{\meta{key}=\meta{value}}
+\newcommand\key{\meta{key}}
+\newcommand\val{\meta{value}}
+\newcommand\set{\meta{set}}
+\newcommand\enfprot{\textcolor{black}{protected}}
+\newcommand\allprot{\textcolor{gray}{protected}}
+\newcommand\notprot{\textcolor{red!80!black}{protected}}
+\newcommand\enflong{\textcolor{black}{long}}
+\newcommand\alllong{\textcolor{gray}{long}}
+\newcommand\notlong{\textcolor{red!80!black}{long}}
+\newcommand\prefixes[2]
+  {^^A
+    \hfill
+    \ifcase\numexpr#1\relax\or
+      \enfprot\or
+      \allprot\or
+      \notprot\fi\space
+    \ifcase\numexpr#2\relax\or
+      \enflong\or
+      \alllong\or
+      \notlong\fi
+  }
+\hypersetup{linkcolor=red!80!black,urlcolor=purple!80!black}
+\DoNotIndex{\def,\edef,\,,\=,\begingroup,\catcode,\chardef,\csname,\endcsname}
+\DoNotIndex{\endgroup,\endinput,\errmessage,\expandafter,\input,\let,\long}
+\DoNotIndex{\protected,\ProvidesFile,\ProvidesPackage,\relax,\space}
+\DoNotIndex{\@,\unexpanded,\string,\expanded,\dimexpr,\global,\glueexpr,\hbox}
+\DoNotIndex{\numexpr,\RequirePackage,\setbox,\the,\unless,\xdef,\@firstofone}
+\DoNotIndex{\@firstoftwo,\@gobble,\@secondoftwo,\AtEndOfPackage,\newcommand}
+\DoNotIndex{\PackageError,\@classoptionslist,\@clsextension,\@currext}
+\DoNotIndex{\@currname,\@empty,\@gobbletwo,\@onlypreamble,\@unprocessedoptions}
+\DoNotIndex{\@unusedoptionlist}
+\DoNotIndex{\ifcsname}
+\DoNotIndex{\ifx}
+\DoNotIndex{\ifdefined}
+\DoNotIndex{\iffalse}
+\DoNotIndex{\iftrue}
+\DoNotIndex{\else}
+\DoNotIndex{\fi}
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@ifdefinable\gobbledocstriptag{\def\gobbledocstriptag#1>{}}
+\makeatother
+\begin{document}
+  \title
+    {^^A
+      \texorpdfstring
+        {^^A
+          \huge\expkvo
+          \\[\medskipamount]
+          \Large parse class and package options with \expkv
+        }{expkv-opt - parse class and package options with expkv}^^A
+    }
+  \date{\ekvoDate\space v\ekvoVersion}
+  \author{Jonathan P. Spratte\thanks{\protect\randomize{jspratte at yahoo.de}}}
+  \DocInput{expkv-opt.dtx}
+\end{document}
+%</driver>^^A=<<
+% \fi
+%
+% \maketitle
+% \renewcommand*\thefootnote{\arabic{footnote}}
+%
+% \begin{abstract}
+% \noindent\parfillskip=0pt
+% \expkvo\ provides option parsing for classes and packages in \LaTeXe\ based on
+% \expkv. Global and local options are parsed individually by different
+% commands. The stylised name is \expkvo\ but the files use \file{expkv-opt},
+% this is due to CTAN-rules which don't allow \string| in package names since
+% that is the pipe symbol in *nix shells.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \begin{documentation}^^A>>=
+%
+% \section{Documentation}
+%
+% The \expkv\ family provides at its core a \kv\ parser and additionally
+% packages, one to conveniently define new keys (\expkvd) and another to build
+% expandable \kv\ taking control sequences (\expkvc). Still missing from the mix
+% was a solution to parse \LaTeXe\ class and package options, a gap that's
+% hereby filled with \expkvo.
+%
+% \expkvo\ shouldn't place any restrictions on the keys, but note that parts of
+% \LaTeXe\ can break if the \kv\ list contains braces. This includes the global
+% options list depending on which class you're using. Also keep in mind that
+% every value provided should be save from an |\edef| expansion, as the space
+% stripping code of \LaTeXe\ options (which is applied before \expkvo\ takes
+% control) uses such an expansion.
+%
+% The package can be loaded with
+% \begin{lstlisting}
+% \usepackage{expkv-opt}
+% \end{lstlisting}
+% Unlike the other packages in the \expkv\ family, \expkvo\ is only provided as
+% a \LaTeX\ package.
+%
+% Before reading this documentation you should read \expkv's documentation and
+% might want to also read the documentation of \expkvd.
+%
+%
+% \subsection{Macros}
+%
+% \expkvo's behaviour if it encounters a defined or an undefined \key\ depends
+% on which list is being parsed and whether the current file is a class or not.
+% Of course in every case a defined \key's callback will be invoked but an
+% additional action might be executed. For this reason the rule set of every
+% macro will be given below the short description which list it will parse. 
+%
+% During each of the processing macros the current list element (not separated
+% in \key\ and \val\ but as a whole) is stored within the macro
+% \cs{CurrentOption}.
+%
+% \begin{function}{\ekvoProcessLocalOptions}
+%   \begin{syntax}
+%     \cs{ekvoProcessLocalOptions}\marg{set}
+%   \end{syntax}
+%   This parses the options which are directly passed to the current class or
+%   package for an \expkv\ \set.
+% \end{function}
+% \begin{description}
+%   \item[Class:]
+%     \begin{description}
+%       \item[defined] \emph{nothing}
+%       \item[undefined]
+%         add the key to the list of unused global options (if the local option
+%         list matches the option list of the main class)
+%     \end{description}
+%   \item[Package:]
+%     \begin{description}
+%       \item[defined] \emph{nothing}
+%       \item[undefined] throw an error
+%     \end{description}
+% \end{description}
+%
+% \begin{function}{\ekvoProcessGlobalOptions}
+%   \begin{syntax}
+%     \cs{ekvoProcessGlobalOptions}\marg{set}
+%   \end{syntax}
+%   In \LaTeXe\ the options given to |\documentclass| are global options. This
+%   macro processes the global options for an \expkv\ \set.
+% \end{function}
+% \begin{description}
+%   \item[Class:]
+%     \begin{description}
+%       \item[defined] remove the option from the list of unused global options
+%       \item[undefined] \emph{nothing}
+%     \end{description}
+%   \item[Package:]
+%     \begin{description}
+%       \item[defined] remove the option from the list of unused global options
+%       \item[undefined] \emph{nothing}
+%     \end{description}
+% \end{description}
+%
+% \begin{function}{\ekvoProcessUnusedGlobalOptions}
+%   \begin{syntax}
+%     \cs{ekvoProcessUnusedGlobalOptions}\marg{set}
+%   \end{syntax}
+%   If you want to, instead of parsing all global options, you can parse only
+%   those global options which weren't yet used by another package or class.
+% \end{function}
+% \begin{description}
+%   \item[Class:]
+%     \begin{description}
+%       \item[defined] remove the option from the list of unused global options
+%       \item[undefined] \emph{nothing}
+%     \end{description}
+%   \item[Package:]
+%     \begin{description}
+%       \item[defined] remove the option from the list of unused global options
+%       \item[undefined] \emph{nothing}
+%     \end{description}
+% \end{description}
+%
+% \begin{function}{\ekvoProcessOptionsList}
+%   \begin{syntax}
+%     \cs{ekvoProcessOptionsList}\meta{list}\marg{set}
+%   \end{syntax}
+%   Process the \kv\ list stored in the macro \meta{list}.
+% \end{function}
+% \begin{description}
+%   \item[Class:]
+%     \begin{description}
+%       \item[defined] \emph{nothing}
+%       \item[undefined] \emph{nothing}
+%     \end{description}
+%   \item[Package:]
+%     \begin{description}
+%       \item[defined] \emph{nothing}
+%       \item[undefined] \emph{nothing}
+%     \end{description}
+% \end{description}
+%
+% \begin{function}{\ekvoUseUnknownHandlers}
+%   \begin{syntax}
+%     \cs{ekvoUseUnknownHandlers}\meta{cs_1}\meta{cs_2}
+%   \end{syntax}
+%   With this macro you can change the action \expkvo\ executes if it encounters
+%   an undefined \key\ for the next (and only the next) list processing macro.
+%   The macro \meta{cs_1} will be called if an undefined \key\ without a \val\
+%   is encountered and get one argument, being the \key. Analogous the macro
+%   \meta{cs_2} will be called if an undefined \key\ with a \val\ was specified.
+%   It will get two arguments, the first being the \key\ and the second the
+%   \val.
+% \end{function}
+%
+% \begin{function}{\ekvoVersion,\ekvoDate}
+%   These two macros store the version and date of the package.
+% \end{function}
+%
+%
+% \subsection{Example}
+%
+% Let's say we want to create a package that changes the way footnotes are
+% displayed in \LaTeX. For this it will essentially just redefine
+% \cs[no-index]{thefootnote} and we'll call this package \pkg{ex-footnote}.
+% First we report back which package we are:
+% \begin{lstlisting}
+% \ProvidesPackage{ex-footnote}[2020-02-02 v1 change footnotes]
+% \end{lstlisting}
+% Next we'll need to provide the options we want the package to have.
+% \begin{lstlisting}
+% \RequirePackage{color}
+% \RequirePackage{expkv-opt} % also loads expkv
+% \ekvdef{ex-footnote}{color}{\def\exfn at color{#1}}
+% \ekvdef{ex-footnote}{format}{\def\exfn at format{#1}}
+% \end{lstlisting}
+% We can provide initial values just by defining the two macros storing the
+% value.
+% \begin{lstlisting}
+% \newcommand*\exfn at color{}
+% \newcommand*\exfn at format{arabic}
+% \end{lstlisting}
+% Next we need to process the options given to the package. The package should
+% only obey options directly passed to it, so we're only using
+% |\ekvoProcessLocalOptions|:
+% \begin{lstlisting}
+% \ekvoProcessLocalOptions{ex-footnote}
+% \end{lstlisting}
+% Now everything that's still missing is actually changing the way footnotes
+% appear:
+% \begin{lstlisting}
+% \renewcommand*\thefootnote
+%   {%
+%     \ifx\exfn at color\@empty
+%       \csname\exfn at format\endcsname{footnote}%
+%     \else
+%       \textcolor{\exfn at color}{\csname\exfn at format\endcsname{footnote}}%
+%     \fi
+%   }
+% \end{lstlisting}
+% \bigskip
+%
+% \noindent
+% So the complete code of the package would look like this:
+% \begin{lstlisting}
+% \ProvidesPackage{ex-footnote}[2020-02-02 v1 change footnotes]
+%
+% \RequirePackage{color}
+% \RequirePackage{expkv-opt} % also loads expkv
+%
+% \ekvdef{ex-footnote}{color}{\def\exfn at color{#1}}
+% \ekvdef{ex-footnote}{format}{\def\exfn at format{#1}}
+% \newcommand*\exfn at color{}
+% \newcommand*\exfn at format{arabic}
+%
+% \ekvoProcessLocalOptions{ex-footnote}
+%
+% \renewcommand*\thefootnote
+%   {%
+%     \ifx\exfn at color\@empty
+%       \csname\exfn at format\endcsname{footnote}%
+%     \else
+%       \textcolor{\exfn at color}{\csname\exfn at format\endcsname{footnote}}%
+%     \fi
+%   }
+% \end{lstlisting}
+% \bigskip
+%
+% \noindent
+% And it could be used with one of the following lines:
+% \begin{lstlisting}
+% \usepackage{ex-footnote}
+% \usepackage[format=fnsymbol]{ex-footnote}
+% \usepackage[color=green]{ex-footnote}
+% \usepackage[color=red,format=roman]{ex-footnote}
+% \end{lstlisting}
+%
+%
+% \subsection{Bugs}
+%
+% If you happen to find bugs, it'd be great if you let me know. Just write me an
+% email (see the front page) or submit a bug report on GitHub:
+% \url{https://github.com/Skillmon/tex_expkv-opt}
+%
+%
+% \subsection{License}
+%
+% Copyright \textcopyright\ 2020\unless\ifnum\year=2020--\the\year\fi\
+% Jonathan P. Spratte
+%
+% \medskip\noindent
+% This work may be distributed and/or modified under the conditions of the
+% \LaTeX\ Project Public License (LPPL), either version 1.3c of this license or
+% (at your option) any later version. The latest version of this license is in
+% the file:
+%
+% \url{http://www.latex-project.org/lppl.txt}
+%
+% \noindent
+% This work is ``maintained'' (as per LPPL maintenance status) by
+%
+% \mbox{Jonathan P. Spratte}.
+%
+% \end{documentation}^^A=<<
+%
+% \begin{implementation}^^A>>=
+%
+% \clearpage
+%
+%
+% \section{Implementation}
+%
+% \gobbledocstriptag
+%<*pkg>
+% Start the package with the typical \LaTeX\ standards.
+% 
+% \begin{macro}{\ekvoVersion,\ekvoDate}
+%   Store the packages version and date in two macros.
+%    \begin{macrocode}
+\newcommand*\ekvoVersion{0.1c}
+\newcommand*\ekvoDate{2020-10-10}
+%    \end{macrocode}
+% \end{macro}
+% And we report who we are and what we need.
+%    \begin{macrocode}
+\ProvidesPackage{expkv-opt}
+  [%
+    \ekvoDate\space v\ekvoVersion\space
+    parse class and package options with expkv%
+  ]
+\RequirePackage{expkv}
+%    \end{macrocode}
+%
+%
+% \subsection{Loop}
+%
+% \begin{macro}[internal]
+%   {\ekvo at CurrentOption@loop,\ekvo at CurrentOption@loop@,\ekvo at end@loop}
+%   We'll need some loop which can iterate over a comma separated list. The loop
+%   is very basic and only works for commas of category~12. First we insert the
+%   delimiters for the actual loop. The |\ekv at set@other| is necessary to get a
+%   functional |\ekvmorekv| in this loop.
+%    \begin{macrocode}
+\protected\long\def\ekvo at CurrentOption@loop#1#2%
+  {%
+    \ekvo at CurrentOption@loop@#2\ekv at set@other\ekv at mark#1,\ekv at stop,\ekvo at tail
+  }
+%    \end{macrocode}
+%   The actual loop checks whether the final element has been read and if so
+%   ends the loop. Else blank elements are ignored, |\CurrentOption| is set and
+%   the macro which parses the list elements called. Then call the next
+%   iteration.
+%    \begin{macrocode}
+\long\def\ekvo at CurrentOption@loop@#1\ekv at set@other#2,%
+  {%
+    \ekv at gobble@from at mark@to at stop#2\ekvo at end@loop\ekv at stop
+    \ekv at ifblank{#2}%
+      {}%
+      {%
+        \edef\CurrentOption{\unexpanded\expandafter{\ekv at gobble@mark#2}}%
+        #1{#2}%
+      }%
+    \ekvo at CurrentOption@loop@#1\ekv at set@other\ekv at mark
+  }
+\long\def\ekvo at end@loop#1\ekvo at tail{}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Tests}
+%
+% \begin{macro}[internal]{\ekvo at ifx@TF,\ekvo at ifx@F}
+%   We'll need branching |\ifx| tests so that user input containing unbalanced
+%   \TeX\ ifs doesn't break (at least not because of us, everything else is the
+%   fault of \LaTeXe).
+%    \begin{macrocode}
+\def\ekvo at ifx@TF#1#2{\ifx#1#2\ekv at fi@firstoftwo\fi\@secondoftwo}
+\def\ekvo at ifx@F#1#2{\ifx#1#2\ekv at fi@gobble\fi\@firstofone}
+%    \end{macrocode}
+% \end{macro}
+% 
+% \begin{macro}[internal]{\ekvo at do@with at set,\ekvo at name,\ekvo at setname}
+%   This test checks whether the \set\ is defined.  If it is we store it in
+%   |\ekvo at setname| and set |\ekvo at name| to a short cut to get the \key's
+%   callback name. Next we execute the code in |#2|, if the \set\ isn't defined
+%   |#2| is gobbled.
+%    \begin{macrocode}
+\protected\def\ekvo at do@with at set#1#2%
+  {%
+    \ekvifdefinedset{#1}%
+      {%
+        \expandafter
+        \let\expandafter\ekvo at name\csname\ekv at undefined@set{#1}\endcsname
+        \def\ekvo at setname{#1}%
+        #2%
+      }%
+      {\ekvo at err@undefined at set{#1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Key handlers}
+%
+% \expkvo\ uses handlers specifying what happens if a parsed \key\ is defined or
+% undefined.
+%
+% \begin{macro}[internal]
+%   {\ekvo at handle@undefined at k@pkg,\ekvo at handle@undefined at kv@pkg}
+%   The case for undefined keys in a local list of a package is easy, just throw
+%   appropriate errors.
+%    \begin{macrocode}
+\protected\long\def\ekvo at handle@undefined at k@pkg#1%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {\ekvo at err@value at required{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+\def\ekvo at handle@undefined at kv@pkg#1#2%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {\ekvo at err@value at forbidden{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvo at addto@unused at one,\ekvo at addto@unused at two,
+%     \ekvo at rmfrom@unused at one,\ekvo at rmfrom@unused at two
+%   }
+%   These macros will add or remove the |\CurrentOption| to or from the list of
+%   unused global options.
+%    \begin{macrocode}
+\long\def\ekvo at addto@unused at one#1{\ekvo at addto@list\@unusedoptionlist}
+\long\def\ekvo at addto@unused at two#1#2{\ekvo at addto@list\@unusedoptionlist}
+\long\def\ekvo at rmfrom@unused at one#1{\ekvo at rmfrom@list\@unusedoptionlist}
+\long\def\ekvo at rmfrom@unused at two#1#2{\ekvo at rmfrom@list\@unusedoptionlist}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {
+%     \ekvo at set@handlers at local,\ekvo at set@handlers at global,
+%     \ekvo at set@handlers at unusedglobal,\ekvo at set@handlers at list
+%   }
+%   These macros are boring. They just set up the handlers to respect the rules
+%   documented earlier.
+%    \begin{macrocode}
+\protected\def\ekvo at set@handlers at local
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \ifx\@currext\@clsextension
+          \ifx\@classoptionslist\relax
+            \let\ekvo at handle@undefined at k\@gobble
+            \let\ekvo at handle@undefined at kv\@gobbletwo
+          \else
+            \expandafter
+            \ifx\csname opt@\@currname.\@currext\endcsname\@classoptionslist
+              \let\ekvo at handle@undefined at k\ekvo at addto@unused at one
+              \let\ekvo at handle@undefined at kv\ekvo at addto@unused at two
+            \else
+              \let\ekvo at handle@undefined at k\@gobble
+              \let\ekvo at handle@undefined at kv\@gobbletwo
+            \fi
+          \fi
+        \else
+          \let\ekvo at handle@undefined at k\ekvo at handle@undefined at k@pkg
+          \let\ekvo at handle@undefined at kv\ekvo at handle@undefined at kv@pkg
+        \fi
+      }%
+  }
+\protected\def\ekvo at set@handlers at global
+  {%
+    \unless\ifx\@unusedoptionlist\@empty
+      \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+      \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+    \fi
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+\protected\def\ekvo at set@handlers at unusedglobal
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\ekvo at addto@unused at one
+        \let\ekvo at handle@undefined at kv\ekvo at addto@unused at two
+        \let\@unusedoptionlist\@empty
+        \@gobbletwo
+      }%
+    \@firstofone
+      {%
+        \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+        \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+      }%
+  }
+\protected\def\ekvo at set@handlers at list
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at if@need at handlers,\ekvo at dont@need at handlers}
+%   If the user specifies handlers this macro will be let to
+%   |\ekvo at dont@need at handlers|, which will act like |\@gobble| and also let it
+%   to |\@firstofone| afterwards.
+%    \begin{macrocode}
+\let\ekvo at if@need at handlers\@firstofone
+\protected\long\def\ekvo at dont@need at handlers#1%
+  {%
+    \let\ekvo at if@need at handlers\@firstofone
+  }%
+%    \end{macrocode}
+% \end{macro}
+%
+% We have to set the default for the handlers of defined keys, because they
+% don't necessarily get defined before a list is parsed.
+%    \begin{macrocode}
+\let\ekvo at handle@defined at k\@gobble
+\let\ekvo at handle@defined at kv\@gobbletwo
+%    \end{macrocode}
+%
+%
+% \subsection{Processing list elements}
+%
+% \begin{macro}[internal]{\ekvo at process@common}
+%   All the key processing frontend macros use the same basic structure. |#1|
+%   will be a simple test, deciding whether the list will really be parsed or
+%   not, |#3| will be the \set, and |#2| will be the individual code of the
+%   frontend macro which should be executed if both the test in |#1| is true and
+%   the \set\ is defined.
+%    \begin{macrocode}
+\protected\def\ekvo at process@common#1#2#3%
+  {%
+    #1{\ekvo at do@with at set{#3}{#2}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at process@list}
+%   This macro only expands the list holding macro and forwards it to the
+%   loop macro.
+%    \begin{macrocode}
+\protected\def\ekvo at process@list#1%
+  {%
+    \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at parse
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at parse}
+%   This macro calls internals of |\ekvparse| such that the code splitting at
+%   commas isn't executed, else this is equivalent to
+%   |\ekvparse\ekvo at set@k\ekvo at set@kv{#1}|.
+%    \begin{macrocode}
+\protected\long\def\ekvo at parse#1%
+  {%
+    \ekv at expanded
+      {\ekv at unexpanded{\ekvparse\ekvo at set@k\ekvo at set@kv}\expandafter}%
+      \expandafter{\ekv at gobble@mark#1}\ekvo at tail
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at set@k,\ekvo at set@kv}
+%   These two macros check whether the key is defined and if so call the handler
+%   for defined keys and execute the key, else the handler for undefined keys is
+%   called. They have to clean up a bit of code which is left by |\ekvo at parse|.
+%    \begin{macrocode}
+\protected\def\ekvo at set@k#1#2\ekvo at tail
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {%
+        \ekvo at handle@defined at k{#1}%
+        \csname\ekvo at name{#1}N\endcsname
+      }%
+      {\ekvo at handle@undefined at k{#1}}%
+  }
+\protected\def\ekvo at set@kv#1#2#3\ekvo at tail
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {%
+        \ekvo at handle@defined at kv{#1}{#2}%
+        \csname\ekvo at name{#1}\endcsname{#2}%
+      }%
+      {\ekvo at handle@undefined at kv{#1}{#2}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{List variable helpers}
+%
+% \begin{macro}[internal]{\ekvo at addto@list}
+%   This macro is rather simple. If the list to which the |\CurrentOption|
+%   should be added is empty we can just let the list to the |\CurrentOption|.
+%   Else we have to expand the list once and the |\CurrentOption| once.
+%    \begin{macrocode}
+\protected\def\ekvo at addto@list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      {\let#1\CurrentOption}%
+      {%
+        \edef#1%
+          {%
+            \unexpanded\expandafter{#1},%
+            \unexpanded\expandafter{\CurrentOption}%
+          }%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at rmfrom@list,\ekvo at rmfrom@list@}
+%   This works by looping over every list item and comparing it to
+%   |\ekvo at curropt| which stores the real |\CurrentOption|. This is
+%   comparatively slow, but works for items containing braces unlike what
+%   \LaTeXe\ does. We could be faster for items not containing braces, though.
+%    \begin{macrocode}
+\protected\def\ekvo at rmfrom@list#1%
+  {%
+    \ekvo at ifx@F#1\@empty
+      {%
+        \let\ekvo at tmp@list\@empty
+        \let\ekvo at curropt\CurrentOption
+        \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at rmfrom@list@
+        \let\CurrentOption\ekvo at curropt
+        \let#1\ekvo at tmp@list
+      }%
+  }
+\protected\long\def\ekvo at rmfrom@list@#1%
+  {%
+    \ekvo at ifx@F\CurrentOption\ekvo at curropt
+      {\ekvo at addto@list\ekvo at tmp@list}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Errors}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvo at err@undefined at key,\ekvo at err@value at required,
+%     \ekvo at err@value at forbidden,\ekvo at err@undefined at set
+%   }
+%   Just some macros to throw errors in the few cases an error has to be thrown.
+%    \begin{macrocode}
+\protected\def\ekvo at err@undefined at key#1%
+  {%
+    \PackageError{expkv-opt}{Undefined key `#1' in set `\ekvo at setname'}{}%
+  }
+\protected\def\ekvo at err@value at required#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Value required for key `#1' in set `\ekvo at setname'}%
+      {}%
+  }
+\protected\def\ekvo at err@value at forbidden#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Value forbidden for key `#1' in set `\ekvo at setname'}%
+      {}%
+  }
+\protected\def\ekvo at err@undefined at set#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Undefined set `#1'}%
+      {The set for which you try to parse options isn't defined in expkv.}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{User Interface}
+%
+% The user interface macros just put together the bits and pieces.
+% \begin{macro}{\ekvoProcessLocalOptions}
+%    \begin{macrocode}
+\protected\def\ekvoProcessLocalOptions
+  {%
+    \ekvo at process@common
+      {\ekv at ifdefined{opt@\@currname.\@currext}\@firstofone\@gobble}%
+      {%
+        \ekvo at set@handlers at local
+        \expandafter
+        \ekvo at process@list\csname opt@\@currname.\@currext\endcsname
+        \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\ekvoProcessGlobalOptions}
+%    \begin{macrocode}
+\protected\def\ekvoProcessGlobalOptions
+  {%
+    \ekvo at process@common{\ekvo at ifx@F\@classoptionslist\relax}%
+      {%
+        \ekvo at set@handlers at global
+        \ekvo at process@list\@classoptionslist
+        \let\ekvo at handle@defined at k\@gobble
+        \let\ekvo at handle@defined at kv\@gobbletwo
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\ekvoProcessUnusedGlobalOptions}
+%    \begin{macrocode}
+\protected\def\ekvoProcessUnusedGlobalOptions
+  {%
+    \ekvo at process@common{\ekvo at ifx@F\@unusedoptionlist\@empty}%
+      {%
+        \let\ekvo at tmp@list\@unusedoptionlist
+        \ekvo at set@handlers at unusedglobal
+        \ekvo at process@list\ekvo at tmp@list
+        \let\ekvo at handle@defined at k\@gobble
+        \let\ekvo at handle@defined at kv\@gobbletwo
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\ekvoProcessOptionsList}
+%    \begin{macrocode}
+\protected\def\ekvoProcessOptionsList#1%
+  {%
+    \ekvo at process@common{\ekvo at ifx@F#1\@empty}%
+      {%
+        \ekvo at set@handlers at list
+        \ekvo at process@list#1%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\ekvoUseUnknownHandlers}
+%    \begin{macrocode}
+\protected\def\ekvoUseUnknownHandlers#1#2%
+  {%
+    \let\ekvo at handle@undefined at k#1\relax
+    \let\ekvo at handle@undefined at kv#2\relax
+    \let\ekvo at if@need at handlers\ekvo at dont@need at handlers
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% All user interface macros should be only used in the preamble.
+%    \begin{macrocode}
+\@onlypreamble\ekvoProcessLocalOptions
+\@onlypreamble\ekvoProcessGlobalOptions
+\@onlypreamble\ekvoProcessUnusedGlobalOptions
+\@onlypreamble\ekvoProcessOptionsList
+\@onlypreamble\ekvoUseUnknownHandlers
+%    \end{macrocode}
+% 
+% \gobbledocstriptag
+%</pkg>
+%
+% \end{implementation}^^A=<<
+%
+% \clearpage
+% \PrintIndex
+%
+% \Finale
+\endinput
+%
+^^A vim: ft=tex fdm=marker fmr=>>=,=<<


Property changes on: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt-2020-10-10.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt.dtx	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,796 @@
+% \iffalse meta-comment
+%
+% File: expkv-opt.dtx Copyright (C) 2020-2023 Jonathan P. Spratte
+%
+% This work  may be  distributed and/or  modified under  the conditions  of the
+% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+% (at your option) any later version.  The latest version of this license is in
+% the file:
+%
+%   http://www.latex-project.org/lppl.txt
+%
+% ------------------------------------------------------------------------------
+%
+%<*driver>^^A>>=
+\def\expkvDocNoGenerate{}
+\input expkv-bundle.ins
+\generate{\file{expkv-opt.sty}{\from{expkv-opt.dtx}{pkg}}}
+\endbatchfile
+%</driver>^^A=<<
+% \fi
+%
+% \section{\expkvo}
+%
+% \gobbledocstriptag
+%<*pkg>
+%
+% First we check whether the \LaTeXe\ kernel supports raw options. If it doesn't
+% we check whether a specific version was requested, and if that's not the case
+% we manually run |\pkgcls at parse@date at arg| with the last version that supported
+% non-raw options.
+%    \begin{macrocode}
+\IfFormatAtLeastTF{2021/05/01}
+  {}
+  {%
+    \ifx\pkgcls at targetlabel\@empty
+      \ifnum\requestedLaTeXdate=\pkgcls at targetdate
+        \pkgcls at parse@date at arg{=v0.1}%
+      \fi
+    \fi
+  }
+%    \end{macrocode}
+% Then we tell \LaTeXe\ where to find which release so that the package rollback
+% code of \LaTeXe\ can do its thing.
+%    \begin{macrocode}
+\DeclareRelease{v0.1}{2020/10/10}{expkv-opt-2020-10-10.sty}
+\DeclareCurrentRelease{v0.2}{2021/04/04}
+%    \end{macrocode}
+% 
+% Start the package with the typical \LaTeX\ standards.
+% 
+% \begin{macro}{\ekvoVersion,\ekvoDate}
+%   Store the package's version and date in two macros.
+%    \begin{macrocode}
+\newcommand*\ekvoVersion{1.0}
+\newcommand*\ekvoDate{2023-01-23}
+%    \end{macrocode}
+% \end{macro}
+% And we report who we are and what we need.
+%    \begin{macrocode}
+\ProvidesPackage{expkv-opt}
+  [%
+    \ekvoDate\space v\ekvoVersion\space
+    parse class and package options with expkv%
+  ]
+\RequirePackage{expkv}
+%    \end{macrocode}
+%
+%
+% \subsection{Loop}
+%
+% \begin{macro}[internal]
+%   {\ekvo at CurrentOption@loop,\ekvo at CurrentOption@loop@,\ekvo at end@loop}
+%   We'll need some loop which can iterate over a comma separated list. The loop
+%   is very basic and only works for commas of category~12. First we insert the
+%   delimiters for the actual loop. The |\ekv at set@other| is necessary to get a
+%   functional |\ekvmorekv| in this loop.
+%    \begin{macrocode}
+\protected\long\def\ekvo at CurrentOption@loop#1#2%
+  {%
+    \ekvo at CurrentOption@loop@#2\ekv at set@other\ekv at mark#1,\ekv at stop,\ekvo at tail
+  }
+%    \end{macrocode}
+%   The actual loop checks whether the final element has been read and if so
+%   ends the loop. Else blank elements are ignored, |\CurrentOption| is set and
+%   the macro which parses the list elements called. Then call the next
+%   iteration.
+%    \begin{macrocode}
+\long\def\ekvo at CurrentOption@loop@#1\ekv at set@other#2,%
+  {%
+    \ekv at gobble@from at mark@to at stop#2\ekvo at end@loop\ekv at stop
+    \ekv at ifblank{#2}%
+      {}%
+      {%
+        \edef\CurrentOption{\unexpanded\expandafter{\ekv at gobble@mark#2}}%
+        #1{#2}%
+      }%
+    \ekvo at CurrentOption@loop@#1\ekv at set@other\ekv at mark
+  }
+\long\def\ekvo at end@loop#1\ekvo at tail{}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Tests}
+%
+% \begin{macro}[internal]{\ekvo at ifx@TF,\ekvo at ifx@T,\ekvo at ifx@F}
+%   We'll need branching |\ifx| tests so that user input containing unbalanced
+%   \TeX\ ifs doesn't break (at least not because of us, everything else is the
+%   fault of \LaTeXe).
+%    \begin{macrocode}
+\def\ekvo at ifx@TF#1#2{\ifx#1#2\ekv at fi@firstoftwo\fi\@secondoftwo}
+\def\ekvo at ifx@T#1#2{\ifx#1#2\ekv at fi@firstofone\fi\@gobble}
+\def\ekvo at ifx@F#1#2{\ifx#1#2\ekv at fi@gobble\fi\@firstofone}
+%    \end{macrocode}
+% \end{macro}
+% 
+% \begin{macro}[internal]{\ekvo at do@with at set,\ekvo at name,\ekvo at setname}
+%   This test checks whether the \set\ is defined.  If it is we store it in
+%   |\ekvo at setname| and set |\ekvo at name| to a short cut to get the \key's
+%   callback name. Next we execute the code in |#2|, if the \set\ isn't defined
+%   |#2| is gobbled.
+%    \begin{macrocode}
+\protected\def\ekvo at do@with at set#1#2%
+  {%
+    \ekvifdefinedset{#1}%
+      {%
+        \expandafter
+        \let\expandafter\ekvo at name\csname\ekv at undefined@set{#1}\endcsname
+        \def\ekvo at setname{#1}%
+        #2%
+      }%
+      {\ekvo at err@undefined at set{#1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Key handlers}
+%
+% \expkvo\ uses handlers specifying what happens if a parsed \key\ is defined or
+% undefined.
+%
+% \begin{macro}[internal]
+%   {\ekvo at handle@undefined at k@pkg,\ekvo at handle@undefined at kv@pkg}
+%   The case for undefined keys in a local list of a package is easy, just throw
+%   appropriate errors.
+%    \begin{macrocode}
+\protected\long\def\ekvo at handle@undefined at k@pkg#1%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {\ekvo at err@value at required{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+\def\ekvo at handle@undefined at kv@pkg#1#2%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {\ekvo at err@value at forbidden{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvo at addto@unused at one,\ekvo at addto@unused at two,
+%     \ekvo at rmfrom@unused at one,\ekvo at rmfrom@unused at two
+%   }
+%   These macros will add or remove the |\CurrentOption| to or from the list of
+%   unused global options. Since |\ekvo at do@unusedoptionlist| will have some
+%   overhead before calling the list changing macro in filtering the current
+%   option, we use an optimization here in that we check whether the list is
+%   empty before calling the |rmfrom| function.
+%    \begin{macrocode}
+\long\def\ekvo at addto@unused at one#1{\ekvo at do@unusedoptionlist\ekvo at addnewto@list}
+\long\def\ekvo at addto@unused at two#1#2{\ekvo at do@unusedoptionlist\ekvo at addnewto@list}
+\long\def\ekvo at rmfrom@unused at one#1%
+  {%
+    \ekvo at ifx@F\@unusedoptionlist\@empty
+      {\ekvo at do@unusedoptionlist\ekvo at rmfrom@list}%
+  }
+\long\def\ekvo at rmfrom@unused at two#1#2%
+  {%
+    \ekvo at ifx@F\@unusedoptionlist\@empty
+      {\ekvo at do@unusedoptionlist\ekvo at rmfrom@list}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvo at do@unusedoptionlist,
+%     \ekvo at prepare@unusedoption,
+%     \ekvo at prepare@unusedoption at a,
+%     \ekvo at prepare@unusedoption at b,
+%     \ekvo at prepare@unusedoption at c
+%   }
+%   The way the new \LaTeXe\ kernel handles the unused option list changed. Now
+%   not the entire |\CurrentOption| is listed, but just everything up to the
+%   first equals sign, and spaces got zapped, doesn't matter whether the raw
+%   option list gets used or not. So we have to zap spaces and remove everything
+%   from the first equals sign onwards. The code used here will fail if the
+%   current option contains an |\ekv at mark| or |\ekv at stop| before the first
+%   equals sign (this seems rather unlikely).
+%    \begin{macrocode}
+\protected\def\ekvo at do@unusedoptionlist#1%
+  {%
+    \let\ekvo at unpreparedCurrentOption\CurrentOption
+    \edef\CurrentOption
+      {\expandafter\ekvo at prepare@unusedoption\CurrentOption=\ekv at mark}%
+    #1\@unusedoptionlist
+    \let\CurrentOption\ekvo at unpreparedCurrentOption
+  }
+\def\ekvo at prepare@unusedoption{\ekvo at prepare@unusedoption at a\@empty}
+\def\ekvo at prepare@unusedoption at a#1%
+  {%
+    \long\def\ekvo at prepare@unusedoption at a##1=##2\ekv at mark
+      {%
+        \ekvo at prepare@unusedoption at b##1\ekv at stop
+          \ekv at mark\ekvo at prepare@unusedoption at b
+          #1\ekv at mark\ekvo at prepare@unusedoption at c
+      }%
+  }
+\ekvo at prepare@unusedoption at a{ }
+\long\def\ekvo at prepare@unusedoption at b#1 #2\ekv at mark#3{#3#1#2\ekv at mark#3}
+\long\def\ekvo at prepare@unusedoption at c
+    #1\ekv at stop
+    \ekv at mark\ekvo at prepare@unusedoption at b\ekv at mark\ekvo at prepare@unusedoption at c
+  {\unexpanded\expandafter{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvo at set@handlers at local,\ekvo at set@handlers at global,
+%     \ekvo at set@handlers at list
+%   }
+%   These macros are boring. They just set up the handlers to respect the rules
+%   documented earlier.
+%    \begin{macrocode}
+\protected\def\ekvo at set@handlers at local
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \ifx\@currext\@clsextension
+          \ifx\@classoptionslist\relax
+            \let\ekvo at handle@undefined at k\@gobble
+            \let\ekvo at handle@undefined at kv\@gobbletwo
+          \else
+            \expandafter
+            \ifx
+                \csname @raw at opt@\@currname.\@currext\endcsname
+                \@raw at classoptionslist
+              \let\ekvo at handle@undefined at k\ekvo at addto@unused at one
+              \let\ekvo at handle@undefined at kv\ekvo at addto@unused at two
+              \unless\ifx\@unusedoptionlist\@empty
+                \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+                \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+              \fi
+            \else
+              \let\ekvo at handle@undefined at k\@gobble
+              \let\ekvo at handle@undefined at kv\@gobbletwo
+            \fi
+          \fi
+        \else
+          \let\ekvo at handle@undefined at k\ekvo at handle@undefined at k@pkg
+          \let\ekvo at handle@undefined at kv\ekvo at handle@undefined at kv@pkg
+        \fi
+      }%
+  }
+\protected\def\ekvo at set@handlers at global
+  {%
+    \unless\ifx\@unusedoptionlist\@empty
+      \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+      \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+    \fi
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+\protected\def\ekvo at set@handlers at list
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at if@need at handlers,\ekvo at dont@need at handlers}
+%   If the user specifies handlers this macro will be let to
+%   |\ekvo at dont@need at handlers|, which will act like |\@gobble| and also let it
+%   to |\@firstofone| afterwards.
+%    \begin{macrocode}
+\let\ekvo at if@need at handlers\@firstofone
+\protected\long\def\ekvo at dont@need at handlers#1%
+  {%
+    \let\ekvo at if@need at handlers\@firstofone
+  }%
+%    \end{macrocode}
+% \end{macro}
+%
+% We have to set the default for the handlers of defined keys, because they
+% don't necessarily get defined before a list is parsed.
+%    \begin{macrocode}
+\let\ekvo at handle@defined at k\@gobble
+\let\ekvo at handle@defined at kv\@gobbletwo
+%    \end{macrocode}
+%
+%
+% \subsection{Processing list elements}
+%
+% \begin{macro}[internal]{\ekvo at process@common}
+%   All the key processing frontend macros use the same basic structure. |#1|
+%   will be a simple test, deciding whether the list will really be parsed or
+%   not, |#3| will be the \set, and |#2| will be the individual code of the
+%   frontend macro which should be executed if both the test in |#1| is true and
+%   the \set\ is defined.
+%    \begin{macrocode}
+\protected\def\ekvo at process@common#1#2#3%
+  {%
+    #1{\ekvo at do@with at set{#3}{#2}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at process@list}
+%   This macro only expands the list holding macro and forwards it to the
+%   loop macro.
+%    \begin{macrocode}
+\protected\def\ekvo at process@list#1%
+  {%
+    \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at parse
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvo at parse,
+%     \ekvo at parse@kv,\ekvo at parse@kv@,\ekvo at expansion@kv,\ekvo at expansion@kv@,
+%     \ekvo at parse@k, \ekvo at parse@k@, \ekvo at expansion@k, \ekvo at expansion@k@
+%   }
+%   This macro calls internals of \expkv\ such that the input is split at an
+%   equals sign of category other.
+%    \begin{macrocode}
+\long\def\ekvo at parse#1%
+  {%
+    \ekv at eq@other#1\ekv at nil\ekv at mark\ekvo at parse@kv
+      =\ekv at mark\ekvo at parse@k
+  }
+%    \end{macrocode}
+%   If there was an equals sign, this will be called and remove the remainder of
+%   the split. Afterwards the \expnotation\ is checked and possibly executed,
+%   and the \kv\ pair is set. While reinsertion works via the |Rr|
+%   \expansion-rule, it might affect the unused global option list.
+%    \begin{macrocode}
+\long\def\ekvo at parse@kv#1\ekv at stop#2\ekv at nil=\ekv at mark\ekvo at parse@k
+  {\ekv at strip{#2}{\ekv at strip{#1}\ekvo at parse@kv@}}
+\long\def\ekvo at parse@kv@#1#2%
+  {%
+    \ekv at ifexp{#1}%
+      {\ekvo at expansion@kv{#2}}%
+      {\ekvo at set@kv{#1}{#2}}%
+  }
+%    \end{macrocode}
+%   Check for \expansion-rules was true, now we need to execute them, and use
+%   the result in |\ekvo at set@kv|. Also we have to handle the key as if it was a
+%   defined key if the |\r| \expansion-rule was found (which potentially removes
+%   it from the list of global unused options).
+%    \begin{macrocode}
+\long\def\ekvo at expansion@kv#1#2#3#4%
+  {%
+    \ekv at expansion@rule@{#1}#2\ekv at mark\ekv at stop{#3}{}%
+      {\ekvo at handle@defined at kv{#3}{#1}\ekvmorekv}%
+    \ekvo at expansion@kv@
+  }
+\long\def\ekvo at expansion@kv@#1#2{\ekvo at set@kv{#1}{#2}}
+%    \end{macrocode}
+%   And basically the same two biggish steps, but for the case that no equals
+%   sign is found.
+%    \begin{macrocode}
+\long\def\ekvo at parse@k#1\ekv at nil\ekv at mark\ekvo at parse@kv\ekv at stop\ekv at mark
+  {\ekv at strip{#1}\ekvo at parse@k@}
+\long\def\ekvo at parse@k@#1%
+  {%
+    \ekv at ifexp{#1}%
+      \ekvo at expansion@k
+      {\ekvo at set@k{#1}}%
+  }
+\long\def\ekvo at expansion@k#1#2#3%
+  {%
+    \ekv at expansion@rule@{#2}#1\ekv at mark\ekv at stop{}{}%
+      {\ekvo at handle@defined at k{#2}\ekvmorekv}%
+    \ekvo at expansion@k@
+  }
+\long\def\ekvo at expansion@k@#1#2{\ekvo at set@k{#2}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at set@k,\ekvo at set@kv}
+%   These two macros check whether the key is defined and if so call the handler
+%   for defined keys and execute the key, else the handler for undefined keys is
+%   called.
+%    \begin{macrocode}
+\protected\def\ekvo at set@k#1%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {%
+        \ekvo at handle@defined at k{#1}%
+        \csname\ekvo at name{#1}N\endcsname
+      }%
+      {\ekvo at handle@undefined at k{#1}}%
+  }
+\protected\def\ekvo at set@kv#1#2%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {%
+        \ekvo at handle@defined at kv{#1}{#2}%
+        \csname\ekvo at name{#1}\endcsname{#2}%
+      }%
+      {\ekvo at handle@undefined at kv{#1}{#2}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{List variable helpers}
+%
+% \begin{macro}[internal]{\ekvo at addto@list}
+%   This macro is rather simple. If the list to which the |\CurrentOption|
+%   should be added is empty we can just let the list to the |\CurrentOption|.
+%   Else we have to expand the list once and the |\CurrentOption| once.
+%    \begin{macrocode}
+\protected\def\ekvo at addto@list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      {\let#1\CurrentOption}%
+      {%
+        \edef#1%
+          {%
+            \unexpanded\expandafter{#1},%
+            \unexpanded\expandafter{\CurrentOption}%
+          }%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at addnewto@list}
+%   This works just like |\ekvo at addto@list|, but it only adds elements which are
+%   not yet part of the list, hence we check if the option is already in the
+%   list.
+%    \begin{macrocode}
+\protected\def\ekvo at addnewto@list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      {\let#1\CurrentOption}%
+      {%
+        \ekvo at if@in at list#1%
+          {}%
+          {%
+            \edef#1%
+              {%
+                \unexpanded\expandafter{#1},%
+                \unexpanded\expandafter{\CurrentOption}%
+              }%
+          }%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekvo at if@in at list,\ekvo at if@in at list@,\ekvo at if@in at list@result}
+%   This is a slow but robust test whether some option is already contained in a
+%   list. Using argument gobbling logic would be faster, but that way wouldn't
+%   be robust for elements containing |{|, |}|, or |#|. Just loop over the code
+%   and compare each element, end early if a match is found.
+%    \begin{macrocode}
+\protected\def\ekvo at if@in at list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      \@secondoftwo
+      {%
+        \let\ekvo at curropt\CurrentOption
+        \let\ekvo at if@in at list@result\@secondoftwo
+        \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at if@in at list@
+        \let\CurrentOption\ekvo at curropt
+        \ekvo at if@in at list@result
+      }%
+  }
+\protected\long\def\ekvo at if@in at list@#1%
+  {%
+    \ekvo at ifx@T\ekvo at curropt\CurrentOption
+      {%
+        \let\ekvo at if@in at list@result\@firstoftwo
+        \ekvo at end@loop
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvo at rmfrom@list,\ekvo at rmfrom@list@}
+%   This works by looping over every list item and comparing it to
+%   |\ekvo at curropt| which stores the real |\CurrentOption|. This is
+%   comparatively slow, but works for items containing braces unlike what
+%   \LaTeXe\ does. We could be faster for items not containing braces, though.
+%    \begin{macrocode}
+\protected\def\ekvo at rmfrom@list#1%
+  {%
+    \ekvo at ifx@F#1\@empty
+      {%
+        \let\ekvo at tmp@list\@empty
+        \let\ekvo at curropt\CurrentOption
+        \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at rmfrom@list@
+        \let\CurrentOption\ekvo at curropt
+        \let#1\ekvo at tmp@list
+      }%
+  }
+\protected\long\def\ekvo at rmfrom@list@#1%
+  {%
+    \ekvo at ifx@F\CurrentOption\ekvo at curropt
+      {\ekvo at addto@list\ekvo at tmp@list}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Errors}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvo at err@undefined at key,\ekvo at err@value at required,
+%     \ekvo at err@value at forbidden,\ekvo at err@undefined at set
+%   }
+%   Just some macros to throw errors in the few cases an error has to be thrown.
+%    \begin{macrocode}
+\protected\def\ekvo at err@undefined at key#1%
+  {%
+    \ekvo at pkg@cls at error
+      {Undefined option `\detokenize{#1}'}%
+      {The used option was not defined. Perhaps you misspelled it?}%
+  }
+\protected\def\ekvo at err@value at required#1%
+  {%
+    \ekvo at pkg@cls at error
+      {Missing value for option `\detokenize{#1}'}%
+      {The used option requires a value or you misspelled its name.}%
+  }
+\protected\def\ekvo at err@value at forbidden#1%
+  {%
+    \ekvo at pkg@cls at error
+      {Unwanted value for option `\detokenize{#1}'}%
+      {The used option doesn't support a value or you misspelled its name.}%
+  }
+\protected\def\ekvo at err@undefined at set#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Undefined set `#1'}%
+      {The set for which you try to parse options isn't defined in expkv.}%
+  }
+\protected\def\ekvo at pkg@cls at error
+  {%
+    \ekvo at ifx@TF\@currext\@clsextension
+      \ClassError
+      \PackageError
+        \@currname
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{User Interface}
+%
+% The user interface macros just put together the bits and pieces.
+%
+% \begin{macro}{\ekvoProcessOptions}
+%   First we check if user-defined handlers were used. If that's the case we
+%   need to store them and restore them for each list processor. Else just call
+%   them sequentially.
+%    \begin{macrocode}
+\protected\def\ekvoProcessOptions#1%
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \ekvoProcessGlobalOptions{#1}%
+        \ekvoProcessLocalOptions {#1}%
+        \ekvoProcessFutureOptions{#1}%
+        \@gobbletwo
+      }%
+    \@firstofone
+      {%
+        \let\ekvo at tmpa\ekvo at handle@undefined at k
+        \let\ekvo at tmpb\ekvo at handle@undefined at kv
+        \ekvoUseUnknownHandlers\ekvo at tmpa\ekvo at tmpb
+        \ekvoProcessGlobalOptions{#1}%
+        \ekvoUseUnknownHandlers\ekvo at tmpa\ekvo at tmpb
+        \ekvoProcessLocalOptions {#1}%
+        \ekvoUseUnknownHandlers\ekvo at tmpa\ekvo at tmpb
+        \ekvoProcessFutureOptions{#1}%
+        \let\ekvo at tmpa\ekvo at undefined
+        \let\ekvo at tmpb\ekvo at undefined
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvoProcessLocalOptions}
+%    \begin{macrocode}
+\protected\def\ekvoProcessLocalOptions
+  {%
+    \ekvo at process@common
+      {\ekv at ifdefined{@raw at opt@\@currname.\@currext}\@firstofone\@gobble}%
+      {%
+        \ekvo at set@handlers at local
+        \expandafter
+        \ekvo at process@list\csname @raw at opt@\@currname.\@currext\endcsname
+        \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvoProcessGlobalOptions}
+%    \begin{macrocode}
+\protected\def\ekvoProcessGlobalOptions
+  {%
+    \ekvo at process@common{\ekvo at ifx@F\@classoptionslist\relax}%
+      {%
+        \ekvo at set@handlers at global
+        \ekvo at process@list\@raw at classoptionslist
+        \let\ekvo at handle@defined at k\@gobble
+        \let\ekvo at handle@defined at kv\@gobbletwo
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvoProcessUnusedGlobalOptions}
+%    \begin{macrocode}
+\protected\def\ekvoProcessUnusedGlobalOptions#1%
+  {%
+    \PackageError{expkv-opt}%
+      {%
+        \noexpand
+        \ekvoProcessUnusedGlobalOptions no longer works because of changes in%
+        \MessageBreak
+        the LaTeX2e kernel%
+      }%
+      {}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvoProcessFutureOptions}
+%   Parsing future options (without patching kernel internals) is only possible
+%   with kernel versions after 2022-11-01.
+%   The user macro needs to store the user-set handlers for later if
+%   |\ekvoUseUnknownHandlers| was used. Then it stores the correct code to
+%   process future options in the |opt at handler@| variable.
+%    \begin{macrocode}
+\IfFormatAtLeastTF{2022/11/01}
+  {%
+    \protected\def\ekvoProcessFutureOptions#1%
+      {%
+        \ekvo at if@need at handlers\@gobbletwo
+        \@firstofone
+          {%
+            \expandafter\let
+              \csname ekvo at future@undefined at k@\@currname.\@currext\endcsname
+              \ekvo at handle@undefined at k
+            \expandafter\let
+              \csname ekvo at future@undefined at kv@\@currname.\@currext\endcsname
+              \ekvo at handle@undefined at kv
+          }%
+        \protected\expandafter
+        \xdef\csname opt at handler@\@currname.\@currext\endcsname
+          {\ekv at unexpanded{\ekvo at future{#1}}}%
+      }
+%    \end{macrocode}
+% \begin{macro}[internal]{\ekvo at future,\ekvo at set@handlers at future}
+%   Key parsing is pretty similar to |\ekvoProcessLocalOptions|, only the
+%   handlers are defined differently, namely it is checked whether they are
+%   user-specified, if not we reuse the undefined handlers for packages (which
+%   will throw an error if an unknown key is found).
+%    \begin{macrocode}
+    \protected\def\ekvo at future
+      {%
+        \ekvo at process@common
+          {\ekv at ifdefined{@raw at opt@\@currname.\@currext}\@firstofone\@gobble}%
+          {%
+            \ekvo at set@handlers at future
+            \expandafter\ekvo at process@list
+              \csname @raw at opt@\@currname.\@currext\endcsname
+            \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+          }%
+      }
+    \protected\def\ekvo at set@handlers at future
+      {%
+        \expandafter\let\expandafter
+          \ekvo at handle@undefined at k
+          \csname
+            \ekv at ifdefined{ekvo at future@undefined at k@\@currname.\@currext}%
+              {ekvo at future@undefined at k@\@currname.\@currext}%
+              {ekvo at handle@undefined at k@pkg}%
+          \endcsname
+        \expandafter\let\expandafter
+          \ekvo at handle@undefined at kv
+          \csname
+            \ekv at ifdefined{ekvo at future@undefined at kv@\@currname.\@currext}%
+              {ekvo at future@undefined at kv@\@currname.\@currext}%
+              {ekvo at handle@undefined at kv@pkg}%
+          \endcsname
+      }
+%    \end{macrocode}
+% \end{macro}
+%    \begin{macrocode}
+  }
+  {%
+    \protected\def\ekvoProcessFutureOptions#1%
+      {%
+        \PackageWarning{expkv-opt}%
+          {LaTeX-kernel is too old to process future options.\@gobbletwo}%
+        \protected\gdef\ekvoProcessFutureOptions##1{}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvoProcessOptionsList}
+%    \begin{macrocode}
+\protected\def\ekvoProcessOptionsList#1%
+  {%
+    \ekvo at process@common{\ekvo at ifx@F#1\@empty}%
+      {%
+        \ekvo at set@handlers at list
+        \ekvo at process@list#1%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvoUseUnknownHandlers}
+% \begin{macro}[internal]{\ekvoUseUnknownHandlers at n,\ekvoUseUnknownHandlers at s}
+%    \begin{macrocode}
+\protected\def\ekvoUseUnknownHandlers
+  {%
+    \let\ekvo at if@need at handlers\ekvo at dont@need at handlers
+    \@ifstar\ekvoUseUnknownHandlers at s\ekvoUseUnknownHandlers at n
+  }
+\protected\def\ekvoUseUnknownHandlers at s
+  {%
+    \long\def\ekvo at handle@undefined at k##1%
+      {%
+        \ekv at ifdefined{\ekvo at name{}uN}%
+          {%
+            \csname\ekvo at name{}uN\expandafter\endcsname\expandafter
+              {\detokenize{##1}}{##1}%
+          }%
+          {\@gobble}%
+      }%
+    \long\def\ekvo at handle@undefined at kv##1##2%
+      {%
+        \ekv at ifdefined{\ekvo at name{}u}%
+          {%
+            \csname\ekvo at name{}u\ekv at expanded{\endcsname
+              {\ekv at unexpanded{##2}}{\detokenize{##1}}}{##1}%
+          }%
+          {}%
+      }%
+  }
+\protected\def\ekvoUseUnknownHandlers at n#1#2%
+  {%
+    \let\ekvo at handle@undefined at k#1\relax
+    \let\ekvo at handle@undefined at kv#2\relax
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% All user interface macros should be only used in the preamble.
+%    \begin{macrocode}
+\@onlypreamble\ekvoProcessOptions
+\@onlypreamble\ekvoProcessLocalOptions
+\@onlypreamble\ekvoProcessGlobalOptions
+\@onlypreamble\ekvoProcessFutureOptions
+\@onlypreamble\ekvoProcessOptionsList
+\@onlypreamble\ekvoUseUnknownHandlers
+%    \end{macrocode}
+% 
+% \gobbledocstriptag
+%</pkg>


Property changes on: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-opt.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-pop.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-pop.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-pop.dtx	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,700 @@
+% \iffalse meta-comment
+%
+% File: expkv-pop.dtx Copyright (C) 2020-2023 Jonathan P. Spratte
+%
+% This work  may be  distributed and/or  modified under  the conditions  of the
+% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+% (at your option) any later version.  The latest version of this license is in
+% the file:
+%
+%   http://www.latex-project.org/lppl.txt
+%
+% ------------------------------------------------------------------------------
+%
+%<*driver>^^A>>=
+\def\expkvDocNoGenerate{}
+\input expkv-bundle.ins
+\generate{\file{expkv-pop.sty}{\from{expkv-pop.dtx}{pkg}}}
+\generate{\file{expkv-pop.tex}{\from{expkv-pop.dtx}{tex}}}
+\generate{\file{t-expkv-pop.tex}{\from{expkv-pop.dtx}{ctx}}}
+\endbatchfile
+%</driver>^^A=<<
+% \fi
+%
+% \section{\expkvp}
+%^^A the LaTeX package >>=
+% \subsection{The \LaTeX\ Package}
+% Set up the \LaTeX\ package.
+% \gobbledocstriptag
+%<*pkg>
+%    \begin{macrocode}
+\RequirePackage{expkv}
+\def\ekvp at tmp
+  {%
+    \ProvidesFile{expkv-pop.tex}%
+      [\ekvpDate\space v\ekvpVersion\space a prefix oriented parser]%
+  }
+\input{expkv-pop.tex}
+\ProvidesPackage{expkv-pop}%
+  [\ekvpDate\space v\ekvpVersion\space a prefix oriented parser]
+%    \end{macrocode}
+% \gobbledocstriptag
+%</pkg>
+%^^A=<<
+%^^A the ConTeXt module >>=
+% \subsection{The \ConTeXt\ module}
+% Set up the \ConTeXt\ module.
+% \gobbledocstriptag
+%<*ctx>
+%    \begin{macrocode}
+\writestatus{loading}{ConTeXt User Module / expkv-pop}
+\usemodule[expkv]
+\unprotect
+\input expkv-pop.tex
+\writestatus{loading}
+  {ConTeXt User Module / expkv-pop / Version \ekvpVersion\space loaded}
+\protect\endinput
+%    \end{macrocode}
+% \gobbledocstriptag
+%</ctx>
+%^^A=<<
+%^^A main file >>=
+% \subsection{The Generic Code}
+% And another generic code package we need to set up.
+% \gobbledocstriptag
+%<*tex>
+%
+% Loading the generic \expkv\ package if it wasn't already loaded, utilizing
+% that \expkv\ prevents itself from loading multiple times.
+%    \begin{macrocode}
+\input expkv
+%    \end{macrocode}
+%
+% Introduce an own guard against being loaded multiple times:
+%    \begin{macrocode}
+\expandafter\ifx\csname ekvpVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+%    \end{macrocode}
+%
+% \begin{macro}{\ekvpVersion,\ekvpDate}
+%   Specify the own version and date
+%    \begin{macrocode}
+\def\ekvpVersion{1.0}
+\def\ekvpDate{2023-01-23}
+%    \end{macrocode}
+% \end{macro}
+%
+% Reporting back who we are for \LaTeX\ (the package will have set up things for
+% us).
+%    \begin{macrocode}
+\csname ekvp at tmp\endcsname
+%    \end{macrocode}
+%
+% Package internal category code setup (stored to restore it at the end -- we
+% have to be careful to not lose this definition of |\ekvp at tmp| inside the
+% package).
+%    \begin{macrocode}
+\expandafter\chardef\csname ekvp at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+%    \end{macrocode}
+%
+% \subsubsection{Parsing}^^A>>=
+%
+% \begin{macro}{\ekvpParse}
+% \begin{macro}[internal]
+%   {
+%     \ekvpParse at a,\ekvpParse at b,\ekvpParse at c,
+%     \ekvpParse at unsafe,\ekvpParse at unsafe@auto
+%   }
+%   Parsing should be done in two steps of expansion, hence we put
+%   |\unexpanded\expanded| around it. Next we check whether the parser is
+%   defined, and afterwards run |\ekvparse|. For that we expand it once and
+%   remove the |\unexpanded| which it uses itself.
+%    \begin{macrocode}
+\long\def\ekvpParse#1#2%
+  {%
+    \ekv at unexpanded\ekv at expanded
+      {{\expandafter\ekvpParse at a\detokenize{#1}\ekv at mark{#2}}}%
+  }
+\def\ekvpParse at a#1\ekv at mark
+  {%
+    \ekv at ifdefined{ekvp@@p@#1}%
+      {\expandafter\ekvpParse at b\csname ekvp@@p@#1\endcsname}%
+      {\ekvp at err@unknownparser{#1}\@gobble}%
+  }
+\def\ekvpParse at b#1%
+  {%
+    \ekv at ifdefined{#1{ppa}}%
+      {%
+        \expandafter\ekvpParse at c\expandafter
+          {\expandafter#1\csname#1{ppa}\endcsname}%
+      }%
+      {\ekvpParse at c{#1{}}}%
+  }
+\def\ekvpParse at c#1#2#3{#2#3}
+\ekv at expargtwice{\long\def\ekvpParse at c#1#2}%
+  {\expandafter\ekvpParse at c\ekvparse{\ekvp at k#1}{\ekvp at p#1}{#2}}
+\long\def\ekvpParse at unsafe#1#2#3{\ekv at unexpanded\ekv at expanded{{#2#3}}}
+\ekv at expargtwice{\long\def\ekvpParse at unsafe@auto#1#2#3}
+  {\expandafter\ekvpParse at unsafe\ekvparse{\ekvp at k#1#2}{\ekvp at p#1#2}{#3}}
+\ekv at expargtwice{\long\def\ekvpParse at unsafe#1#2}%
+  {\expandafter\ekvpParse at unsafe\ekvparse{\ekvp at k#1{}}{\ekvp at p#1{}}{#2}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvp at k}
+%   For |NoVal| we use the parser specific rule.
+%    \begin{macrocode}
+\def\ekvp at k#1{\csname #1k\endcsname#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvp at ifspace,\ekvp at ifspace@}
+%   This checks whether a space is inside its argument (gobbling up to the first
+%   space and checking for an empty remainder).
+%    \begin{macrocode}
+\long\def\ekvp at ifspace#1%
+  {%
+    \ekvp at ifspace@#1 \ekv at ifempty@B\ekv at ifempty@false
+      \ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+  }
+\long\def\ekvp at ifspace@#1 % keep this space
+  {\ekv at ifempty@\ekv at ifempty@A}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvp at p}
+% \begin{macro}[internal]{\ekvp at prefix}
+% \begin{macro}[internal]{\ekvp at prefix@a,\ekvp at prefix@b}
+%   If there should be a prefix there needs to be a space, so we check for one.
+%   Then we split the first prefix of the rest.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekvp at prefix#1}%
+  {%
+    \ekvp at ifspace{#1}%
+      {\ekvp at prefix@a#1\ekv at stop}%
+      {\ekvp at noprefix{#1}}%
+  }
+%    \end{macrocode}
+%   A prefix is parsed with a few additional logical groups. The input |#1| is
+%   the parser's name macro, |#2| is the full item which should be parsed. And
+%   we place an additional group in which the prefix macros will be collected.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekvp at p#1#2#3}{\ekvp at prefix{#3}#1{#2}{#3}}
+%    \end{macrocode}
+%   The prefix is |\detokenize|d and forwarded. Then we check whether it's a
+%   defined type or prefix.
+%    \begin{macrocode}
+\long\def\ekvp at prefix@a#1 % keep this space
+  {\expandafter\ekvp at prefix@b\detokenize{#1}\ekv at mark{#1}}
+\ekv at exparg{\long\def\ekvp at prefix@b#1\ekv at mark#2#3\ekv at stop#4}%
+  {%
+    \ekv at ifdefined{#4{pt}@#1}
+      {\expandafter\ekvp at prefix@pt\csname #4{pt}@#1\endcsname{#1}}%
+      {%
+        \ekv at ifdefined{#4{pp}@#1}%
+          {\expandafter\ekvp at prefix@pp\csname #4{pp}@#1\endcsname}%
+          {\@firstoftwo{\ekvp at noprefix{#2 #3}}}%
+      }%
+      {#3}#4%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvp at prefix@pt,\ekvp at prefix@pt@}
+%   A type ends the prefix parsing (every item can only have one type). The
+%   argument |#1| is that type macro, and in |#2| is the types name. |#3| then
+%   contains the name of the element, |#4| is the parser's name macro (which is
+%   no longer needed here), |#5| is the list of prefix macros, |#6| the entire
+%   unchanged item, and |#7| is the value provided to the current item. The
+%   prefix macro list will be stepped through, each macro will get the type
+%   name, element name, and complete unprocessed item, whereas the type macro
+%   will not receive the type string (but instead the value), which is why we
+%   put a |\@firstoftwo| there to remove the type. |\ekvp at prefix@pt@| is a
+%   helper to fetch the first prefix macro (or the type should |#5| be empty).
+%    \begin{macrocode}
+\long\def\ekvp at prefix@pt#1#2#3#4#5#6#7%
+  {%
+    \ekvp at prefix@pt@{#2}{#3}{#6}#5{\@firstoftwo#1}{#7}\ekvpEOT
+    \ekv at unexpanded{\ekvpEOA{#6}}%
+  }
+\long\def\ekvp at prefix@pt@#1#2#3#4{#4{#1}{#2}{#3}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvp at prefix@pp}
+%   A prefix macro is added to the list of prefixes (argument |#4|) and the next
+%   prefix is searched.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekvp at prefix@pp#1#2#3#4}{\ekvp at prefix{#2}#3{#4#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvp at noprefix}
+%   If no prefix was found (either because there was no space, or the first
+%   space delimited thing wasn't a valid prefix) we check if there is a notype
+%   rule or throw an error.
+%    \begin{macrocode}
+\long\def\ekvp at noprefix#1#2%
+  {%
+    \ekv at ifdefined{#2{pn}}
+      {\expandafter\ekvp at prefix@pt\csname #2{pn}\endcsname{}{#1}}
+      \ekvp at err@missingtype
+      #2%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%^^A=<<
+%
+% \subsubsection{Defining Parsers}^^A>>=
+%
+% \begin{macro}{\ekvpNewParser}
+% \begin{macro}[internal]{\ekvpNewParser@}
+%   To define a new parser we need to assert that it doesn't already exists (if
+%   so we throw an error) and define the parser name. A parser name is defined
+%   as the macro \cs[no-index]{ekvp@@p@\meta{name}}, that macro will take one
+%   argument and build the name of a prefix or type. Additionally a new parser
+%   gets its |NoVal| rule set up as the default rule.
+%    \begin{macrocode}
+\protected\long\def\ekvpNewParser#1%
+  {\expandafter\ekvpNewParser@\detokenize{#1}\ekv at mark}
+\protected\def\ekvpNewParser@#1\ekv at mark
+  {%
+    \ekv at ifdefined{ekvp@@p@#1}%
+      {\ekvp at errm{Parser `#1' already defined}}%
+      {%
+        \expandafter\def\csname ekvp@@p@#1\endcsname##1{ekvp@@##1@#1}
+        \expandafter
+        \let\csname\csname ekvp@@p@#1\endcsname k\endcsname\ekvp at k@default
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpValueAlwaysRequired}
+% \begin{macro}[internal]{\ekvpValueAlwaysRequired@}
+%   This just changes the default |NoVal| rule to throw an error.
+%    \begin{macrocode}
+\protected\long\def\ekvpValueAlwaysRequired#1%
+  {\ekvp at parser@def{#1}\ekvpValueAlwaysRequired@{}}
+\protected\def\ekvpValueAlwaysRequired@#1%
+  {\expandafter\let\csname#1k\endcsname\ekvp at err@noval}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpDefNoValue}
+% \begin{macro}[internal]{\ekvpDefNoValue@}
+%    \begin{macrocode}
+\protected\long\def\ekvpDefNoValue#1%
+  {\ekvp at parser@def{#1}\ekvpDefNoValue@\@gobble}
+\protected\long\def\ekvpDefNoValue@#1#2%
+  {%
+    \def\ekvp at tmp##1{\ekv at unexpanded{#2}}%
+    \ekv at exparg{\long\expandafter\def\csname#1k\endcsname##1##2##3}%
+      {\ekvp at tmp{##3}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpUseNoValueMarker}
+% \begin{macro}[internal]{\ekvpUseNoValueMarker@}
+%
+%    \begin{macrocode}
+\protected\long\def\ekvpUseNoValueMarker#1%
+  {\ekvp at parser@def{#1}\ekvpUseNoValueMarker@\@gobble}
+\protected\long\def\ekvpUseNoValueMarker@#1#2%
+  {%
+    \long\expandafter\edef\csname#1k\endcsname##1##2##3%
+      {\ekv at unexpanded{\ekvp at p}##1{##2}{##3}{\ekv at unexpanded{#2}}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpDefNoValuePrefix}
+% \begin{macro}[internal]{\ekvpDefNoValuePrefix@,\ekvpDefNoValuePrefix@@}
+%   This might be the most complicated of the |NoVal|-behaviour changes. The
+%   first two steps should be clear.
+%    \begin{macrocode}
+\protected\long\def\ekvpDefNoValuePrefix#1%
+  {\ekvp at parser@def{#1}\ekvpDefNoValuePrefix@\@gobbletwo}
+\protected\def\ekvpDefNoValuePrefix@#1%
+  {\expandafter\ekvpDefNoValuePrefix@@\csname#1{ppn}\endcsname#1}
+%    \end{macrocode}
+%   This step is the complicated one combining the effects of \cs{ekvpDefPrefix}
+%   with the standard |NoVal|-rule (but for which the no-value marker might have
+%   been changed), so here's what happens:
+%   We set up a temporary meaning for the control sequence name
+%   forwarded as |#1| to extract the no-value marker of the current parser. Then
+%   we set up the |NoVal|-macro of the current parser to expand to the normal
+%   parsing route, there we inject |#1| as the first prefix macro in the
+%   corresponding first argument of \cs[no-index]{ekvp at p}, and we extract the
+%   no-value marker with the |\expandafter#1|-chain. This last step might
+%   actually fail badly if \cs{ekvpValueAlwaysRequired} or \cs{ekvpDefNoValue}
+%   was used.
+%    \begin{macrocode}
+\protected\long\def\ekvpDefNoValuePrefix@@#1#2%
+  {%
+    \long\def#1\ekvp at p##1##2##3%
+      {%
+        \ekv at unexpanded{\ekvp at p}%
+          ####1{####2\ekv at unexpanded{#1}}{####3}{\ekv at unexpanded{##3}}%
+      }%
+    \long\expandafter\edef\csname#2k\endcsname##1##2##3%
+      {\expandafter\expandafter\expandafter#1\csname#2k\endcsname{}{}{}}%
+    \ekvp at parser@def at prefix#1%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpDefAutoPrefix}
+% \begin{macro}[internal]{\ekvpDefAutoPrefix@}
+%    \begin{macrocode}
+\protected\long\def\ekvpDefAutoPrefix#1%
+  {\ekvp at parser@def{#1}\ekvpDefAutoPrefix@\@gobbletwo}
+\protected\long\def\ekvpDefAutoPrefix@#1%
+  {\expandafter\ekvp at parser@def at prefix\csname#1{ppa}\endcsname}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvp at parser@def,\ekvp at parser@def@}
+%   This just makes sure that the parser is defined and builds the parser name.
+%   |#1| should be the user-level parser name, |#2| the macro that gets the
+%   code-level parser forwarded, and |#3| should gobble all additional arguments
+%   needed by whichever frontend macro this is used for in case of an error.
+%    \begin{macrocode}
+\long\def\ekvp at parser@def#1%
+  {\expandafter\ekvp at parser@def@\detokenize{#1}\ekv at mark}
+\def\ekvp at parser@def@#1\ekv at mark#2#3%
+  {%
+    \ekv at ifdefined{ekvp@@p@#1}%
+      {\ekv at exparg{#2}{\csname ekvp@@p@#1\endcsname}}%
+      {\ekvp at errm{Parser `#1' not defined}#3}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvpDefPrefix}
+% \begin{macro}[internal]{\ekvpDefPrefix@,\ekvp at parser@def at prefix}
+%   A prefix is stored as a macro. At first we define a temporary meaning just
+%   to make sure that the user uses only the first three arguments.
+%   The real macro is a bit more complicated. It places the user provided before
+%   action (|#3|) where it currently is, the after action (|#4|) after
+%   |\ekvpEOT| (so after the type action). It also fetches the next prefix or
+%   the type macro and forwards the arguments to it.
+%    \begin{macrocode}
+\protected\long\def\ekvpDefPrefix#1%
+  {\ekvp at parser@def{#1}\ekvpDefPrefix@\@gobblethree}
+\protected\long\def\ekvpDefPrefix@#1#2%
+  {\expandafter\ekvp at parser@def at prefix\csname#1{pp}@\detokenize{#2}\endcsname}
+\protected\long\def\ekvp at parser@def at prefix#1#2#3%
+  {%
+    \def#1##1##2##3{#2#3}%
+    \long\def#1##1##2##3##4##5\ekvpEOT
+      {\ekv at unexpanded{#2}##4{##1}{##2}{##3}##5\ekvpEOT\ekv at unexpanded{#3}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpDefPrefixLet,\ekvpDefPrefixStore}
+%   These are just special cases of |\ekvpDefPrefix|, so nothing complicated
+%   here.
+%    \begin{macrocode}
+\ekv at exparg{\protected\long\def\ekvpDefPrefixLet#1#2#3#4#5}%
+  {\ekvpDefPrefix{#1}{#2}{\ekvpProtect{\let#3= #4}}{\ekvpProtect{\let#3= #5}}}
+\ekv at exparg{\protected\long\def\ekvpDefPrefixStore#1#2#3#4#5}%
+  {%
+    \ekvpDefPrefix{#1}{#2}%
+      {\ekvpProtect{\edef#3{\ekv at unexpanded{#4}}}}%
+      {\ekvpProtect{\edef#3{\ekv at unexpanded{#5}}}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvpDefType,\ekvpDefNoType}
+% \begin{macro}[internal]{\ekvpDefType@,\ekvpDefNoType@,\ekvpDefType at NoType}
+%   A type macro and a notype-macro are pretty similar, the whole difference is
+%   the naming scheme. The macro leaves the user definition in the input and
+%   places the |\ekvpEOP| and |\ekvpEOT| markers.
+%    \begin{macrocode}
+\protected\long\def\ekvpDefType#1{\ekvp at parser@def{#1}\ekvpDefType@\@gobbletwo}
+\protected\long\def\ekvpDefType@#1#2%
+  {\ekvpDefType at NoType{#1{pt}@\detokenize{#2}}}%
+\protected\long\def\ekvpDefNoType#1{\ekvp at parser@def{#1}\ekvpDefNoType@\@gobble}
+\protected\long\def\ekvpDefNoType@#1{\ekvpDefType at NoType{#1{pn}}}
+\protected\long\def\ekvpDefType at NoType#1#2%
+  {%
+    \long\expandafter\def\csname#1\endcsname##1##2##3\ekvpEOT
+      {\ekv at unexpanded{\ekvpEOP{##2}#2\ekvpEOT{##2}}}%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpLet}
+% \begin{macro}[internal]{\ekvpLet at a,\ekvpLet at b,\ekvpLet at c,\ekvpLet at d}
+%   Letting has an optional argument, so we can't use |\ekvp at parser@def|
+%   directly here, first we need to convert the optional argument to a normal
+%   one so that we can gobble it normally. Then we check that the two parsers
+%   are defined, and afterwards that the copy macro is. If all this is correct
+%   we do the |\let|. Since arguments are shuffled around here, I'll list them
+%   each time they get reordered (some might be curried).
+%
+%   |#1| is the parser name, |#2| the type, |#3| the new \prefix/\type\ name,
+%   |#4| the optional other parser name, |#5| the already existing
+%   \prefix/\type\ which should be copied.
+%    \begin{macrocode}
+\protected\long\def\ekvpLet#1#2#3{\ekvoptarg{\ekvpLet at a{#1}{#2}{#3}}{#1}}
+\protected\long\def\ekvpLet at a#1%
+  {\ekvp at parser@def{#1}\ekvpLet at b{\@firstoftwo\@gobblethree}}
+\protected\long\def\ekvpLet at b#1#2#3#4%
+  {\ekvp at parser@def{#4}\ekvpLet at c{\@firstoftwo\@gobblethree}#1{#2}{#3}}
+%    \end{macrocode}
+%   |#1| the other parser's macro, |#2| the parser's macro, |#3| the type, |#4|
+%   the new \prefix/\type, |#5| the already existing \prefix/\type.
+%    \begin{macrocode}
+\protected\long\def\ekvpLet at c#1#2#3%
+  {%
+    \ekv at ifdefined{ekvpLet@@\detokenize{#3}}%
+      {\expandafter\ekvpLet at d\csname ekvpLet@@\detokenize{#3}\endcsname{#1}{#2}}%
+      {\ekvp at errm{unknown type \detokenize{#3}}\@gobbletwo}%
+  }
+%    \end{macrocode}
+%   |#1| the type's macro, |#2| the other parser's macro, |#3| the parser's
+%   macro, |#4| the new \prefix/\type, |#5| the already existing \prefix/\type.
+%    \begin{macrocode}
+\protected\long\def\ekvpLet at d#1#2#3#4#5%
+  {%
+    \ekv at ifdefined{#2{#1}@\detokenize{#5}}%
+      {%
+        \expandafter\let
+          \csname#3{#1}@\detokenize{#4}\expandafter\endcsname
+          \csname#2{#1}@\detokenize{#5}\endcsname
+      }%
+      {\ekvp at errm{Undefined prefix/type \detokenize{#5} can't be copied}}%
+  }
+\def\ekvpLet@@prefix{pp}
+\def\ekvpLet@@type{pt}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%^^A=<<
+%
+% \subsubsection{\texttt{NoVal} Handling}^^A>>=
+%
+% The idea of |NoVal| handling is taken from \pkg{expl3}. We define a marker
+% (or directly use \pkg{expl3}'s). The defined test is not as robust as
+% \pkg{expl3}'s, but pretty fast (and based on |\ekv at ifempty|).
+%
+% \begin{macro}{\ekvpIfNoVal}
+% \begin{macro}[internal]{\ekvp at novalflag,\ekvp at ifnoval}
+% \begin{macro}[internal]{\ekvp at k@default}
+%    \begin{macrocode}
+\ekv at ifdefined{c_novalue_tl}
+  {\expandafter\let\expandafter\ekvp at novalflag\csname c_novalue_tl\endcsname}
+  {%
+    \begingroup
+    \lccode`\Z=`\-
+    \lccode`\:=`\-
+    \lccode`\N=\z@
+    \lccode`\V=\z@
+    \lowercase{\endgroup\def\ekvp at novalflag{ZNoValue:}}%
+  }
+\def\ekvpIfNoVal#1%
+  {%
+    \long\def\ekvpIfNoVal##1%
+      {%
+        \ekvp at ifnoval{}##1{}?!#1??!\ekv at ifempty@B\ekv at ifempty@true
+          \ekv at ifempty@A\ekv at ifempty@B\@secondoftwo
+      }%
+    \long\def\ekvp at ifnoval##1#1##2?##3?!{\ekv at ifempty@\ekv at ifempty@A##1##2}%
+    \long\def\ekvp at k@default##1##2##3{\ekvp at p##1{##2}{##3}{#1}}%
+  }
+\expandafter\ekvpIfNoVal\expandafter{\ekvp at novalflag}
+\let\ekvp at novalflag\ekvp at undefined
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%^^A=<<
+%
+% \subsubsection{Assertions}^^A>>=
+%
+% Assertions are just wrappers around user provided code to throw errors. Each
+% of them
+%
+% \begin{macro}{\ekvpAssertIf,\ekvpAssertIfNot}
+% \begin{macro}[internal]{\ekvpAssertIf@,\ekvpAssertIf at good,\ekvpAssert at notgood}
+%    \begin{macrocode}
+\def\ekvpAssertIf{\romannumeral\ekv at alignsafe\ekvoptarg{\ekvpAssertIf@{}}{EOT}}
+\def\ekvpAssertIfNot
+  {\romannumeral\ekv at alignsafe\ekvoptarg{\ekvpAssertIf@\else}{EOT}}
+\long\def\ekvpAssertIf@#1#2#3%
+  {%
+    #3#1\ekvpAssertIf at good\fi
+    \ekvpAssert at notgood{#2}%
+  }
+\long\def\ekvpAssertIf at good\fi\ekvpAssert at notgood#1#2%
+  {\fi\ekv at endalignsafe\ekv at zero}
+\long\def\ekvpAssert at notgood#1%
+  {%
+    \ekv at ifdefined{ekvpAssert@@#1}%
+      {\csname ekvpAssert@@#1\endcsname}%
+      {\ekvp at err@unknownmarker{#1}\ekvpAssert@@EOA}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvpAssertTF,\ekvpAssertTFNot}
+% \begin{macro}[internal]{\ekvpAssertTF@}
+%    \begin{macrocode}
+\def\ekvpAssertTF{\ekvoptarg{\ekvpAssertTF@{}}{EOT}}
+\def\ekvpAssertTFNot{\ekvoptarg{\ekvpAssertTF@{\@secondoftwo\@firstoftwo}}{EOT}}
+\long\def\ekvpAssertTF@#1#2#3%
+  {%
+    \ekv at alignsafe
+    #3#1%
+      {\ekv at endalignsafe\@gobble}%
+      {\romannumeral\ekvpAssert at notgood{#2}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \ekvpAssertValue,\ekvpAssertNoValue,\ekvpAssertOneValue,
+%     \ekvpAssertTwoValues
+%   }
+% \begin{macro}[internal]{\ekvpAssert at further}
+% \begin{macro}[internal]{\ekvp at assert@num at args}
+%   These here are special cases of assertions. First we define a helper, the
+%   following might look like a recursive call, but we'll redefine the helper
+%   later and need this definition only temporary.
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvpAssert at further#1#2#3}%
+  {\ekvoptarg{\ekvpAssert at further{#1}{#2}{#3}}{EOT}}
+%    \end{macrocode}
+%   Now the definitions, we just need to set up the tests and corresponding
+%   error messages. All this passes through the \cs{ekvpAssertTF} check (which
+%   we shortcut to its internal auxiliary function here).
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvpAssertValue}%
+  {\ekvpAssert at further{\@secondoftwo\@firstoftwo}{\ekvpIfNoVal}{missing value}}
+\ekv at exparg{\def\ekvpAssertNoValue}%
+  {\ekvpAssert at further{}{\ekvpIfNoVal}{superfluous value}}
+\ekv at exparg{\def\ekvpAssertOneValue}%
+  {\ekvpAssert at further{}{\ekvp at assert@num at args\@gobble}{argument count != 1}}
+\ekv at exparg{\def\ekvpAssertTwoValues}%
+  {\ekvpAssert at further{}{\ekvp at assert@num at args\@gobbletwo}{argument count != 2}}
+\long\def\ekvp at assert@num at args#1#2%
+  {%
+    \expandafter\ekv at ifempty@\expandafter\ekv at ifempty@A#1#2\ekv at ifempty@B
+      \ekv at ifempty@true\ekv at ifempty@A\ekv at ifempty@B\@secondoftwo
+  }
+%    \end{macrocode}
+%   And finally redefine our auxiliary that just does a bit of argument
+%   reordering for us.
+%    \begin{macrocode}
+\long\def\ekvpAssert at further#1#2#3#4#5{\ekvpAssertTF@{#1}{#4}{#2{#5}}{#3}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvpAssert@@EOP,\ekvpAssert@@EOT,\ekvpAssert@@EOA}
+%    \begin{macrocode}
+\def\ekvpAssert@@EOA#1#2%
+  {\long\def#1##1##2#2##3{\ekvp at err{##1 at `##3'}\ekv at endalignsafe\ekv at zero}}
+\ekvpAssert@@EOA\ekvpAssert@@EOP\ekvpEOP
+\ekvpAssert@@EOA\ekvpAssert@@EOT\ekvpEOT
+\ekvpAssert@@EOA\ekvpAssert@@EOA\ekvpEOA
+%    \end{macrocode}
+% \end{macro}
+%
+%^^A=<<
+%
+% \subsubsection{Markers}^^A>>=
+%
+% \begin{macro}
+%   {\ekvpGobbleP,\ekvpGobbleT,\ekvpGobbleA,\ekvpEOP,\ekvpEOT,\ekvpEOA}
+%   Since after the |\ekvpEOT|, \emph{etc.} markers the full element is placed,
+%   they are defined as |\@gobble|, and the functions gobbling up to them gobble
+%   that argument as well.
+%    \begin{macrocode}
+\long\def\ekvpGobbleP#1\ekvpEOP#2{}
+\long\def\ekvpGobbleT#1\ekvpEOT#2{}
+\long\def\ekvpGobbleA#1\ekvpEOA#2{}
+\let\ekvpEOP\@gobble
+\let\ekvpEOT\@gobble
+\let\ekvpEOA\@gobble
+%    \end{macrocode}
+% \end{macro}
+%
+%^^A=<<
+%
+% \subsubsection{Miscellaneous Auxiliaries}^^A>>=
+%
+% \begin{macro}{\ekvpProtect}
+% \begin{macro}[internal]{\ekvpProtect@,\ekvpProtect@@}
+%   The idea of this macro is pretty simple. In contexts in which a |\protected|
+%   macro isn't expanded the |\ekvpProtect@@| expansion will just expand to
+%   itself and in the process protect the argument using |\unexpanded|. If a
+%   |\protected| macro would be expanded the |\ekvpProtect@| will remove
+%   |\ekvpProtect@@| and unpack the argument.
+%    \begin{macrocode}
+\def\ekvpProtect{\ekvpProtect@\ekvpProtect@@}
+\protected\long\def\ekvpProtect@\ekvpProtect@@#1{#1}
+\long\def\ekvpProtect@@#1{\ekv at unexpanded{\ekvpProtect@@{#1}}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%^^A=<<
+%
+% \subsubsection{Error messages}^^A>>=
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvp at err,\ekvp at err@unknownparser,\ekvp at err@noval,\ekvp at err@missingtype,
+%     \ekvp at errm
+%   }
+%   These should be pretty straight forward. We use |\ekverr| to throw
+%   expandable errors.
+%    \begin{macrocode}
+\protected\long\def\ekvp at errm#1{\errmessage{expkv-pop Error: #1}}
+\ekv at exparg{\long\def\ekvp at err#1}{\ekverr{expkv-pop}{#1}}
+\def\ekvp at err@unknownparser#1{\ekvp at err{unknown parser `#1'}}
+\long\def\ekvp at err@noval#1#2#3{\ekvp at err{missing value for `#3'}}
+\long\def\ekvp at err@missingtype#1#2#3#4{\ekvp at err{missing type in `#3'}}
+\long\def\ekvp at err@unknownmarker#1{\ekvp at err{unknown marker `#1'}}
+%    \end{macrocode}
+% \end{macro}
+%
+%^^A=<<
+%
+% Undefine the no longer needed |\ekvp at prefix| and restore the category code of
+% |@|:
+%    \begin{macrocode}
+\let\ekvp at prefix\ekvp at undefined
+\catcode`\@=\ekvp at tmp
+%    \end{macrocode}
+%
+% \gobbledocstriptag
+%</tex>
+%^^A=<<


Property changes on: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv-pop.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv.dtx	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,2375 @@
+% \iffalse meta-comment
+%
+% File: expkv.dtx Copyright (C) 2020-2023 Jonathan P. Spratte
+%
+% This work  may be  distributed and/or  modified under  the conditions  of the
+% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+% (at your option) any later version.  The latest version of this license is in
+% the file:
+%
+%   http://www.latex-project.org/lppl.txt
+%
+% ------------------------------------------------------------------------------
+%
+%<*driver>^^A>>=
+\def\expkvDocNoGenerate{}
+\input expkv-bundle.ins
+\generate{\file{expkv.sty}{\from{expkv.dtx}{pkg}}}
+\generate{\file{expkv.tex}{\from{expkv.dtx}{tex}}}
+\generate{\file{t-expkv.tex}{\from{expkv.dtx}{ctx}}}
+\endbatchfile
+%</driver>^^A=<<
+% \fi
+%
+% \section{\expkv}
+%^^A the LaTeX package >>=
+% \subsection{The \LaTeX\ Package}
+% First we set up the \LaTeX\ package. That one doesn't really do much except
+% |\input|ting the generic code and identifying itself as a package. Additional
+% an |all| option is declared to load all the sub modules in one go.
+% \gobbledocstriptag
+%<*pkg>
+%    \begin{macrocode}
+\def\ekv at tmp
+  {%
+    \ProvidesFile{expkv.tex}%
+      [\ekvDate\space v\ekvVersion\space an expandable key=val implementation]%
+  }
+\input{expkv.tex}
+\ProvidesPackage{expkv}%
+  [\ekvDate\space v\ekvVersion\space an expandable key=val implementation]
+\let\ekv at tmp\@empty
+\DeclareOption{all}
+  {%
+    \def\ekv at tmp
+      {\RequirePackage{expkv-pop,expkv-cs,expkv-def,expkv-opt}}%
+  }
+\ProcessOptions\relax
+\ekv at tmp
+%    \end{macrocode}
+% \gobbledocstriptag
+%</pkg>
+%^^A=<<
+%^^A the ConTeXt module >>=
+% \subsection{The \ConTeXt\ module}
+% This is pretty straight forward, we just have to change the error throwing
+% mechanism for \ConTeXt\ (the approach taken for plain and \LaTeX\ breaks in
+% \ConTeXt, effectively breaking \ConTeXt, dropping you in an interactive \TeX\
+% session with almost no means of escape).
+% \gobbledocstriptag
+%<*ctx>
+%    \begin{macrocode}
+\writestatus{loading}{ConTeXt User Module / expkv}
+\unprotect
+\input expkv.tex
+\long\def\ekv at err@collect#1\par#2%
+  {\directlua{tex.error[[\detokenize{#2} Error: #1]]}}
+\writestatus{loading}
+  {ConTeXt User Module / expkv / Version \ekvVersion\space loaded}
+\protect\endinput
+%    \end{macrocode}
+% \gobbledocstriptag
+%</ctx>
+%^^A=<<
+%^^A main file >>=
+% \subsection{The Generic Code}
+% The rest of this implementation will be the generic code.
+% \gobbledocstriptag
+%<*tex>
+%
+% We make sure that it's only input once:
+%    \begin{macrocode}
+\expandafter\ifx\csname ekvVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+%    \end{macrocode}
+%
+% Check whether \eTeX\ and |\expanded| are available -- \expkv\ requires \eTeX.
+%    \begin{macrocode}
+\begingroup
+  \edef\ekvtmpa{\string\expanded}
+  \edef\ekvtmpb{\meaning\expanded}
+  \expandafter
+\endgroup
+\ifx\ekvtmpa\ekvtmpb
+  \expandafter\let\csname ekv at expanded\endcsname\expanded
+  \expandafter\let\csname ekv at unexpanded\endcsname\unexpanded
+\else
+  \begingroup
+    \edef\ekvtmpa{\string\expanded}
+    \edef\ekvtmpb{\meaning\normalexpanded}
+    \expandafter
+  \endgroup
+  \ifx\ekvtmpa\ekvtmpb
+    \expandafter\let\csname ekv at expanded\endcsname\normalexpanded
+    \expandafter\let\csname ekv at unexpanded\endcsname\normalunexpanded
+  \else
+    \errmessage
+      {expkv Error: e-TeX and the \noexpand\expanded primitive required}%
+    \expandafter\endinput
+  \fi
+\fi
+%    \end{macrocode}
+%
+% \begin{macro}{\ekvVersion,\ekvDate}
+% We're on our first input, so lets store the version and date in a macro.
+%    \begin{macrocode}
+\def\ekvVersion{2.0}
+\def\ekvDate{2023-01-23}
+%    \end{macrocode}
+% \end{macro}
+%
+% If the \LaTeX\ format is loaded we want to be a good file and report back who
+% we are, for this the package will have defined |\ekv at tmp| to use
+% |\ProvidesFile|, else this will expand to a |\relax| and do no harm.
+%    \begin{macrocode}
+\csname ekv at tmp\endcsname
+%    \end{macrocode}
+%
+% Store the category code of |@| to later be able to reset it and change it to
+% 11 for now.
+%    \begin{macrocode}
+\expandafter\chardef\csname ekv at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+%    \end{macrocode}
+% |\ekv at tmp| might later be reused to gobble any prefixes which might be
+% provided to |\ekvdef| and similar in case the names are invalid, we just
+% temporarily use it here as means to store the current category code of |@| to
+% restore it at the end of the file, we never care for the actual definition of
+% it.
+%
+% \begin{macro}[internal]{\ekv at if@lastnamedcs}
+% If the primitive |\lastnamedcs| is available, we can be a bit faster than
+% without it. So we test for this and save the test's result in this macro.
+%    \begin{macrocode}
+\begingroup
+  \edef\ekv at tmpa{\string \lastnamedcs}
+  \edef\ekv at tmpb{\meaning\lastnamedcs}
+  \ifx\ekv at tmpa\ekv at tmpb
+    \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##1}}
+  \else
+    \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##2}}
+  \fi
+  \expandafter
+\endgroup
+\ekv at if@lastnamedcs
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at empty}
+% Sometimes we have to introduce a token to prevent accidental brace stripping.
+% This token would then need to be removed by |\@gobble| or similar. Instead we
+% can use |\ekv at empty| which will just expand to nothing, that is faster than
+% gobbling an argument.
+%    \begin{macrocode}
+\def\ekv at empty{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \@gobble,\@gobbletwo,\@gobblethree,
+%     \@firstofone,\@firstoftwo,\@secondoftwo,
+%     \ekv at fi@gobble,\ekv at fi@firstofone,\ekv at fi@firstoftwo,\ekv at fi@secondoftwo,
+%     \ekv at gobble@mark,\ekv at gobbleto@stop,\ekv at gobble@from at mark@to at stop
+%   }
+% Since branching tests are often more versatile than |\if...\else...\fi|
+% constructs, we define helpers that are branching pretty fast. Also here are
+% some other utility functions that just grab some tokens. The ones that are
+% also contained in \LaTeX\ don't use the |ekv| prefix. Not all of the ones
+% defined here are really needed by \expkv\ but are provided because packages
+% like \expkvd\ or \expkvo\ need them (and I don't want to define them in each
+% package which might need them).
+%    \begin{macrocode}
+\long\def\@gobble#1{}
+\long\def\@gobbletwo#1#2{}
+\long\def\@gobblethree#1#2#3{}
+\long\def\@firstofone#1{#1}
+\long\def\@firstoftwo#1#2{#1}
+\long\def\@secondoftwo#1#2{#2}
+\long\def\ekv at fi@gobble\fi\@firstofone#1{\fi}
+\long\def\ekv at fi@firstofone\fi\@gobble#1{\fi#1}
+\long\def\ekv at fi@firstoftwo\fi\@secondoftwo#1#2{\fi#1}
+\long\def\ekv at fi@secondoftwo\fi\@firstoftwo#1#2{\fi#2}
+\def\ekv at gobble@mark\ekv at mark{}
+\long\def\ekv at gobbleto@stop#1\ekv at stop{}
+\long\def\ekv at gobble@from at mark@to at stop\ekv at mark#1\ekv at stop{}
+%    \end{macrocode}
+% \end{macro}
+% As you can see |\ekv at gobbleto@stop| uses a special marker |\ekv at stop|. The
+% package will use three such markers, the one you've seen already, |\ekv at mark|
+% and |\ekv at nil|. Contrarily to how for instance \pkg{expl3} does things, we
+% don't define them, as we don't need them to have an actual meaning. This has
+% the advantage that if they somehow get expanded -- which should never happen
+% if things work out -- they'll throw an error directly.
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at ifempty,\ekv at ifempty@,\ekv at ifempty@true,\ekv at ifempty@false,
+%     \ekv at ifempty@true at F,\ekv at ifempty@true at F@gobble,
+%     \ekv at ifempty@true at F@gobbletwo
+%   }
+% We can test for a lot of things building on an if-empty test, so lets define a
+% really fast one. Since some tests might have reversed logic (true if something
+% is not empty) we also set up macros for the reversed branches.
+%    \begin{macrocode}
+\long\def\ekv at ifempty#1%
+  {%
+    \ekv at ifempty@\ekv at ifempty@A#1\ekv at ifempty@B\ekv at ifempty@true
+      \ekv at ifempty@A\ekv at ifempty@B\@secondoftwo
+  }
+\long\def\ekv at ifempty@#1\ekv at ifempty@A\ekv at ifempty@B{}
+\long\def\ekv at ifempty@true\ekv at ifempty@A\ekv at ifempty@B\@secondoftwo#1#2{#1}
+\long\def\ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo#1#2{#2}
+\long\def\ekv at ifempty@true at F\ekv at ifempty@A\ekv at ifempty@B\@firstofone#1{}
+\long\def\ekv at ifempty@true at F@gobble\ekv at ifempty@A\ekv at ifempty@B\@firstofone#1#2%
+  {}
+\long\def\ekv at ifempty@true at F@gobbletwo
+    \ekv at ifempty@A\ekv at ifempty@B\@firstofone#1#2#3%
+  {}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekv at ifblank,\ekv at ifblank@,\ekv at ifblank@false,\ekv at ifblank@gobbletrue}
+% The obvious test that can be based on an if-empty is if-blank, meaning a test
+% checking whether the argument is empty or consists only of spaces. But instead
+% of building atop |\ekv at ifempty| our version will utilise the fact that the
+% argument in none of our usages can contain |\ekv at stop| (due to the way we
+% check for end-of-list), and hence we can use an even faster check. This here
+% works due to the fact that \TeX\ will read at least one token (or a group) for
+% an undelimited parameter which might be the end marker of the delimited next
+% parameter. So if |#1| to |\ekv at ifblank| is indeed blank, |#1| of
+% |\ekv at ifblank@| will be the placed |\ekv at stop| and |#2| will be anything until
+% the next |\ekv at stop|. The wrapper |\ekv at ifblank| will not be used by \expkv\
+% for speed reasons but \expkvo\ uses it. Also, not only a |TF| variant is
+% provided but also a rather strange one that assumes that only the |F| branch
+% is provided and that this branch consists only of a single token.
+%    \begin{macrocode}
+\long\def\ekv at ifblank#1%
+  {\ekv at ifblank@#1\ekv at stop\ekv at ifblank@false\ekv at stop\@firstoftwo}
+\long\def\ekv at ifblank@\ekv at mark#1#2\ekv at stop{}
+\long\def\ekv at ifblank@false\ekv at stop\@firstoftwo#1#2{#2}
+\def\ekv at ifblank@gobbletrue\ekv at stop#1{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at ifdefined}
+% We'll need to check whether something is defined quite frequently, so why not
+% define a macro that does this. The following test is expandable and pretty
+% fast. The version with |\lastnamedcs| is the fastest version to test for an
+% undefined macro I know of (that considers both undefined macros and those with
+% the meaning |\relax|).
+%    \begin{macrocode}
+\ekv at if@lastnamedcs
+  {%
+    \long\def\ekv at ifdefined#1{\ifcsname#1\endcsname\ekv at ifdef@\fi\@secondoftwo}
+    \def\ekv at ifdef@\fi\@secondoftwo
+      {%
+        \fi
+        \expandafter\ifx\lastnamedcs\relax
+          \ekv at fi@secondoftwo
+        \fi
+        \@firstoftwo
+      }
+  }
+  {%
+    \long\def\ekv at ifdefined#1%
+      {%
+        \ifcsname#1\endcsname\ekv at ifdef@\fi\ekv at ifdef@false#1\endcsname\relax
+          \ekv at fi@secondoftwo
+        \fi
+        \@firstoftwo
+      }
+    \def\ekv at ifdef@\fi\ekv at ifdef@false{\fi\expandafter\ifx\csname}
+    \long\def\ekv at ifdef@false
+        #1\endcsname\relax\ekv at fi@secondoftwo\fi\@firstoftwo#2#3%
+      {#3}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at strip,\ekv at strip@a,\ekv at strip@b,\ekv at strip@c}
+% We borrow some ideas of \pkg{expl3}'s \pkg{l3tl} to strip spaces
+% from keys and values. This |\ekv at strip| also strips one level of outer braces
+% \emph{after} stripping spaces, so an input of | {abc} | becomes |abc| after
+% stripping. It should be used with |#1| prefixed by |\ekv at mark|. Also this
+% implementation at most strips \emph{one} space from both sides (which should
+% be fine most of the time, since \TeX\ reads consecutive spaces as a single one
+% during tokenisation).
+%    \begin{macrocode}
+\def\ekv at strip#1%
+  {%
+    \long\def\ekv at strip##1%
+      {%
+        \ekv at strip@a
+          ##1\ekv at nil
+          \ekv at mark#1%
+          #1\ekv at nil
+      }%
+    \long\def\ekv at strip@a##1\ekv at mark#1{\ekv at strip@b##1\ekv at mark}%
+  }
+\ekv at strip{ }
+\long\def\ekv at strip@b#1 \ekv at nil{\ekv at strip@c#1\ekv at nil}
+\long\def\ekv at strip@c\ekv at mark#1\ekv at nil\ekv at mark#2\ekv at nil#3{#3{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekv at strip@key,\ekv at strip@key at a,\ekv at strip@key at b,\ekv at strip@key at c}
+%   Same idea and code as |\ekv at strip|, but the second argument to
+%   |\ekv at strip@key| must be a single token and the result of the stripping will
+%   be |\detokenize|d.
+%    \begin{macrocode}
+\def\ekv at strip@key#1%
+  {%
+    \long\def\ekv at strip@key##1{\ekv at strip@key at a##1\ekv at nil\ekv at mark#1#1\ekv at nil}
+    \long\def\ekv at strip@key at a##1\ekv at mark#1{\ekv at strip@key at b##1\ekv at mark}
+  }
+\ekv at strip@key{ }
+\long\def\ekv at strip@key at b#1 \ekv at nil{\ekv at strip@key at c#1\ekv at nil}
+\long\def\ekv at strip@key at c\ekv at mark#1\ekv at nil\ekv at mark#2\ekv at nil#3%
+  {\expandafter#3\detokenize{#1}\ekv at mark{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at exparg,\ekv at exparg@,
+%     \ekv at expandedarg,\ekv at fexparg,\ekv at expandafter
+%     \ekv at expargtwice,\ekv at expargtwice@,\ekv at zero
+%   }
+% To reduce some code doublets while gaining some speed (and also as convenience
+% for other packages in the family), it is often useful to expand the first
+% token in a definition once. Let's define a wrapper for this. And while we're
+% at it, also define a helper for |f|-~and |e|-expansion as well.
+%
+% Also, to end a |\romannumeral| expansion, we want to use |\z@|, which is
+% contained in both plain \TeX\ and \LaTeX, but we use a private name for it to
+% make it easier to spot and hence easier to manage.
+%    \begin{macrocode}
+\let\ekv at zero\z@
+\long\def\ekv at exparg#1#2%
+  {\ekv at expanded{\ekv at unexpanded{#1}\expandafter}\expandafter{#2}}
+\long\def\ekv at expandafter#1{\ekv at expanded{\ekv at unexpanded{#1}\expandafter}}
+\long\def\ekv at exparg@#1#2{#2{#1}}%
+\long\def\ekv at expandedarg#1#2{\ekv at expanded{\ekv at unexpanded{#1}{#2}}}
+\long\def\ekv at fexparg#1#2%
+  {%
+    \ekv at expanded{\ekv at unexpanded{#1}\expandafter}\expandafter
+      {\romannumeral`\^^@#2}%
+  }
+\long\def\ekv at expargtwice#1#2{\expandafter\ekv at expargtwice@\expandafter{#2}{#1}}
+\def\ekv at expargtwice@{\expandafter\ekv at exparg@\expandafter}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcsvloop}
+% \begin{macro}[internal]{\ekv at csv@loop at active,\ekv at csv@loop at active@end}
+%   An |\ekvcsvloop| will just loop over a csv list in a simple manner. First we
+%   split at active commas (gives better performance this way), next we have to
+%   check whether we're at the end of the list (checking for |\ekv at stop|). If
+%   not we go on splitting at commas of category other.
+%    \begin{macrocode}
+\begingroup
+\def\ekvcsvloop#1{%
+\endgroup
+\long\def\ekvcsvloop##1##2%
+  {\ekv at csv@loop at active{##1}\ekv at mark##2#1\ekv at stop#1}
+%    \end{macrocode}
+%   This does the same as |\ekv at csv@loop| but for active commas.
+%    \begin{macrocode}
+\long\def\ekv at csv@loop at active##1##2#1%
+  {%
+    \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at active@end\ekv at stop
+    \ekv at csv@loop{##1}##2,\ekv at stop,%
+  }%
+\long\def\ekv at csv@loop at active@end
+    \ekv at stop
+    \ekv at csv@loop##1\ekv at mark\ekv at stop,\ekv at stop,%
+  {}%
+}
+%    \end{macrocode}
+%   Do the definitions with the weird catcode.
+%    \begin{macrocode}
+\catcode`\,=13
+\ekvcsvloop,
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at csv@loop,\ekv at csv@loop at do,\ekv at csv@loop at end}
+%   We use temporary macros and an |\expandafter| chain to preexpand
+%   |\ekv at strip| here. After splitting at other commas we check again for end
+%   the end of the sublist, check for blank elements which should be ignored,
+%   and else strip spaces and execute the user code (protecting it from further
+%   expanding with |\unexpanded|).
+%    \begin{macrocode}
+\def\ekv at csv@loop#1%
+  {%
+    \long\def\ekv at csv@loop##1##2,%
+      {%
+        \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at end\ekv at stop
+        \ekv at ifblank@##2\ekv at stop\ekv at ifblank@gobbletrue
+          \ekv at stop\ekv at csv@loop at blank
+        #1\ekv at csv@loop at do{##1}%
+      }%
+  }
+\expandafter\ekv at csv@loop\expandafter{\ekv at strip{#2}}
+\long\def\ekv at csv@loop at do#1#2{\ekv at unexpanded{#2{#1}}\ekv at csv@loop{#2}\ekv at mark}
+\def\ekv at csv@loop at end#1%
+  {%
+    \long\def\ekv at csv@loop at end
+        \ekv at stop
+        \ekv at ifblank@\ekv at mark\ekv at stop\ekv at stop\ekv at ifblank@gobbletrue
+        \ekv at stop\ekv at csv@loop at blank
+        #1\ekv at csv@loop at do##1%
+      {\ekv at csv@loop at active{##1}\ekv at mark}%
+  }
+\expandafter\ekv at csv@loop at end\expandafter{\ekv at strip{\ekv at mark\ekv at stop}}
+\long\expandafter\def\expandafter\ekv at csv@loop at blank
+    \ekv at strip{\ekv at mark#1}\ekv at csv@loop at do#2%
+  {\ekv at csv@loop{#2}\ekv at mark}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekv at name,\ekv at name@set,\ekv at name@key}
+% The keys will all follow the same naming scheme, so we define it here.
+%    \begin{macrocode}
+\def\ekv at name@set#1{ekv#1(}
+\long\def\ekv at name@key#1{#1)}
+\edef\ekv at name
+  {%
+    \ekv at unexpanded\expandafter{\ekv at name@set{#1}}%
+    \ekv at unexpanded\expandafter{\ekv at name@key{\detokenize{#2}}}%
+  }
+\long\ekv at exparg{\def\ekv at name#1#2}{\ekv at name}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at undefined@set}
+% We can misuse the macro name we use to expandably store the set-name in a
+% single token -- since this increases performance drastically, especially for
+% long set-names -- to throw a more meaningful error message in case a set isn't
+% defined. The name of |\ekv at undefined@set| is a little bit misleading, as it is
+% called in either case inside of |\csname|, but the result will be a control
+% sequence with meaning |\relax| if the set is undefined, hence will break the
+% |\csname| building the key-macro which will throw the error message.
+%    \begin{macrocode}
+\def\ekv at undefined@set#1{! expkv Error: Set `#1' undefined.}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at checkvalid}
+% We place some restrictions on the allowed names, though, namely sets and
+% keys are not allowed to be empty -- blanks are fine (meaning \mbox{set-
+% or} key-names consisting of spaces). The |\def\ekv at tmp| gobbles any \TeX\
+% prefixes which would otherwise throw errors. This will, however, break the
+% package if an |\outer| has been gobbled this way. I consider that good,
+% because keys shouldn't be defined |\outer| anyways.
+%    \begin{macrocode}
+\edef\ekv at checkvalid
+  {%
+    \ekv at unexpanded\expandafter{\ekv at ifempty{#1}}%
+    \ekv at unexpanded
+      {{%
+        \def\ekv at tmp{}%
+        \ekv at errm{empty set name not allowed}%
+      }}%
+      {%
+        \ekv at unexpanded\expandafter{\ekv at ifempty{#2}}%
+        \ekv at unexpanded
+          {%
+            {%
+              \def\ekv at tmp{}%
+              \ekv at errm{empty key name not allowed}%
+            }%
+            \@secondoftwo
+          }%
+      }%
+    \ekv at unexpanded{\@gobble}%
+  }
+\ekv at exparg{\protected\def\ekv at checkvalid#1#2}{\ekv at checkvalid}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvifdefined,\ekvifdefinedNoVal}
+% And provide user-level macros to test whether a key is defined.
+%    \begin{macrocode}
+\ekv at expargtwice{\long\def\ekvifdefined#1#2}%
+  {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}}}
+\ekv at expargtwice{\long\def\ekvifdefinedNoVal#1#2}%
+  {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}N}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \ekvdef,\ekvdefNoVal,\ekvlet,\ekvletNoVal,\ekvletkv,\ekvletkvNoVal,
+%     \ekvdefunknown,\ekvdefunknownNoVal,\ekvletunknown,\ekvletunknownNoVal
+%   }
+% Set up the key defining macros |\ekvdef| etc. We use temporary macros to set
+% these up with a few expansions already done.
+%    \begin{macrocode}
+\def\ekvdef#1#2#3#4#5#6%
+  {%
+    \protected\long\def\ekvdef##1##2##3%
+      {#1{\expandafter\def\csname#2\endcsname####1{##3}#4}}%
+    \protected\long\def\ekvdefNoVal##1##2##3%
+      {#1{\expandafter\def\csname#2N\endcsname{##3}#4}}%
+    \protected\long\def\ekvlet##1##2##3%
+      {#1{\expandafter\let\csname#2\endcsname##3#4}}%
+    \protected\long\def\ekvletNoVal##1##2##3%
+      {#1{\expandafter\let\csname#2N\endcsname##3#4}}%
+    \ekv at expargtwice{\protected\long\def\ekv at defunknown##1##2##3##4}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\ekv at zero\ekv at checkvalid{##3}.}%
+          {%
+            \expandafter\expandafter\expandafter
+            \def\expandafter\csname\ekv at name{##3}{}u##1\endcsname##2{##4}%
+            #6%
+          }%
+      }%
+    \ekv at expargtwice{\protected\long\def\ekv at letunknown##1##2##3}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\ekv at zero\ekv at checkvalid{##2}.}%
+          {%
+            \expandafter\expandafter\expandafter
+            \let\expandafter\csname\ekv at name{##2}{}u##1\endcsname##3%
+            #5%
+          }%
+      }%
+    \protected\long\def\ekvletkv##1##2##3##4%
+      {%
+        #1%
+          {%
+            \expandafter\let\csname#2\expandafter\endcsname
+            \csname#3\endcsname
+            #4%
+          }%
+      }%
+    \protected\long\def\ekvletkvNoVal##1##2##3##4%
+      {%
+        #1%
+          {%
+            \expandafter\let\csname#2N\expandafter\endcsname
+            \csname#3N\endcsname
+            #4%
+          }%
+      }%
+  }
+\edef\ekvdefNoVal
+  {%
+    {\ekv at unexpanded\expandafter{\ekv at checkvalid{#1}{#2}}}%
+    {\ekv at unexpanded\expandafter{\ekv at name{#1}{#2}}}%
+    {\ekv at unexpanded\expandafter{\ekv at name{#3}{#4}}}%
+    {%
+      \ekv at unexpanded{\expandafter\ekv at defsetmacro\csname}%
+      \ekv at unexpanded\expandafter{\ekv at undefined@set{#1}\endcsname{#1}}%
+    }%
+    {%
+      \ekv at unexpanded{\expandafter\ekv at defsetmacro\csname}%
+      \ekv at unexpanded\expandafter{\ekv at undefined@set{#2}\endcsname{#2}}%
+    }%
+    {%
+      \ekv at unexpanded{\expandafter\ekv at defsetmacro\csname}%
+      \ekv at unexpanded\expandafter{\ekv at undefined@set{#3}\endcsname{#3}}%
+    }%
+  }
+\expandafter\ekvdef\ekvdefNoVal
+\ekv at exparg{\protected\long\def\ekvdefunknown#1#2}%
+  {\ekv at defunknown{}{##1##2##3}{#1}{#2}}
+\ekv at exparg{\protected\long\def\ekvdefunknownNoVal#1#2}%
+  {\ekv at defunknown{N}{##1##2}{#1}{#2}}
+\ekv at exparg{\protected\long\def\ekvletunknown#1#2}%
+  {\ekv at letunknown{}{#1}{#2}}
+\ekv at exparg{\protected\long\def\ekvletunknownNoVal#1#2}%
+  {\ekv at letunknown{N}{#1}{#2}}
+\let\ekv at defunknown\ekv at undefined
+\let\ekv at letunknown\ekv at undefined
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvredirectunknown,\ekvredirectunknownNoVal}
+% \begin{macro}[internal]
+%   {
+%     \ekv at defredirectunknown,\ekv at redirectunknown@aux,
+%     \ekv at redirectunknownNoVal@aux
+%   }
+%   The redirection macros prepare the unknown function by looping over the
+%   provided list of sets and leaving a |\ekv at redirect@kv| or |\ekv at redirect@k|
+%   for each set. Only the first of these internals will receive the \key\ and
+%   \val\ as arguments.
+%    \begin{macrocode}
+\protected\def\ekv at defredirectunknown#1#2#3#4#5#6%
+  {%
+    \begingroup
+    \edef\ekv at tmp
+      {%
+        \ekvcsvloop#1{#6}%
+        \ekv at unexpanded{#2}%
+        {\ekvcsvloop{}{#5,#6}}%
+      }%
+    \ekv at expargtwice
+      {\endgroup\long#3{#5}}%
+      {\expandafter#4\ekv at tmp\ekv at stop}%
+  }
+\ekv at exparg{\protected\def\ekvredirectunknown#1#2}%
+  {%
+    \ekv at defredirectunknown
+      \ekv at redirect@kv
+      \ekv at err@redirect at kv@notfound
+      \ekvdefunknown
+      \ekv at redirectunknown@aux
+      {#1}{#2}%
+  }
+\ekv at exparg{\protected\def\ekvredirectunknownNoVal#1#2}%
+  {%
+    \ekv at defredirectunknown
+      \ekv at redirect@k
+      \ekv at err@redirect at k@notfound
+      \ekvdefunknownNoVal
+      \ekv at redirectunknownNoVal@aux
+      {#1}{#2}%
+  }
+\def\ekv at redirectunknown@aux#1{#1{##1}{##2}}
+\def\ekv at redirectunknownNoVal@aux#1{#1{##1}}
+\let\ekv at defredirectunknown\ekv at undefined
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at redirect@k,\ekv at redirect@k at a,\ekv at redirect@k at a@,
+%     \ekv at redirect@k at b,\ekv at redirect@k at c,\ekv at redirect@k at d,
+%     \ekv at redirect@kv,\ekv at redirect@kv at a,\ekv at redirect@kv at a@,
+%     \ekv at redirect@kv at b,\ekv at redirect@kv at c,\ekv at redirect@kv at d
+%   }
+%   The redirect code works by some simple loop over all the sets, which we
+%   already preprocessed in |\ekv at defredirectunknown|. For some optimisation we
+%   blow this up a bit code wise, essentially, all this does is |\ekvifdefined|
+%   or |\ekvifdefinedNoVal| in each set, if there is a match gobble the
+%   remainder of the specified sets and execute the key macro, else go on with
+%   the next set (to which the \key\ and \val\ are forwarded).
+%
+%   First we set up some code which is different depending on |\lastnamedcs|
+%   being available or not. All this is stored in a temporary macro to have
+%   pre-expanded |\ekv at name| constellations ready.
+%    \begin{macrocode}
+\def\ekv at redirect@k#1#2#3#4%
+  {%
+    \ekv at if@lastnamedcs
+      {%
+        \def\ekv at redirect@k##1##2##3%
+          {%
+            \ifcsname#1\endcsname\ekv at redirect@k at a\fi
+            ##3{##1}%
+          }%
+        \def\ekv at redirect@k at a\fi{\fi\expandafter\ekv at redirect@k at b\lastnamedcs}%
+        \long\def\ekv at redirect@kv##1##2##3##4%
+          {%
+            \ifcsname#2\endcsname\ekv at redirect@kv at a\fi\@gobble{##1}%
+            ##4{##1}{##2}%
+          }%
+        \def\ekv at redirect@kv at a\fi\@gobble
+          {\fi\expandafter\ekv at redirect@kv at b\lastnamedcs}%
+      }
+      {%
+        \def\ekv at redirect@k##1##2##3%
+          {%
+            \ifcsname#1\endcsname\ekv at redirect@k at a\fi\ekv at redirect@k at a@
+              #1\endcsname
+            ##3{##1}%
+          }%
+        \def\ekv at redirect@k at a@#3\endcsname{}%
+        \def\ekv at redirect@k at a\fi\ekv at redirect@k at a@
+          {\fi\expandafter\ekv at redirect@k at b\csname}%
+        \long\def\ekv at redirect@kv##1##2##3##4%
+          {%
+            \ifcsname#2\endcsname\ekv at redirect@kv at a\fi\ekv at redirect@kv at a@
+              #2\endcsname{##1}%
+            ##4{##1}{##2}%
+          }%
+        \long\def\ekv at redirect@kv at a@#4\endcsname##3{}%
+        \def\ekv at redirect@kv at a\fi\ekv at redirect@kv at a@
+          {\fi\expandafter\ekv at redirect@kv at b\csname}%
+      }%
+  }
+%    \end{macrocode}
+%   The key name given to this loop will already be |\detokenize|d by |\ekvset|,
+%   so we can safely remove the |\detokenize| here for some performance gain.
+%    \begin{macrocode}
+\def\ekv at redirect@kv#1\detokenize#2#3\ekv at stop{\ekv at unexpanded{#1#2#3}}
+\edef\ekv at redirect@kv
+  {%
+    {\expandafter\ekv at redirect@kv\ekv at name{#2}{#1}N\ekv at stop}%
+    {\expandafter\ekv at redirect@kv\ekv at name{#3}{#2}\ekv at stop}%
+    {\expandafter\ekv at redirect@kv\ekv at name{#1}{#2}N\ekv at stop}%
+    {\expandafter\ekv at redirect@kv\ekv at name{#1}{#2}\ekv at stop}%
+  }
+%    \end{macrocode}
+%   Everything is ready to make the real definitions.
+%    \begin{macrocode}
+\expandafter\ekv at redirect@k\ekv at redirect@kv
+%    \end{macrocode}
+%   The remaining macros here are independent on |\lastnamedcs|, starting from
+%   the |@b| we know that there is a hash table entry, and get the macro as a
+%   parameter. We still have to test whether the macro is |\relax|, depending on
+%   the result of that test we have to either remove the remainder of the
+%   current test, or the remainder of the set list and invoke the macro.
+%    \begin{macrocode}
+\def\ekv at redirect@k at b#1%
+  {\ifx\relax#1\ekv at redirect@k at c\fi\ekv at redirect@k at d#1}
+\def\ekv at redirect@k at c\fi\ekv at redirect@k at d#1{\fi}
+\def\ekv at redirect@k at d#1#2\ekv at stop{#1}
+\def\ekv at redirect@kv at b#1%
+  {\ifx\relax#1\ekv at redirect@kv at c\fi\ekv at redirect@kv at d#1}
+\long\def\ekv at redirect@kv at c\fi\ekv at redirect@kv at d#1#2{\fi}
+\long\def\ekv at redirect@kv at d#1#2#3\ekv at stop{#1{#2}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at defsetmacro}
+%   In order to enhance the speed the set name given to |\ekvset| will be turned
+%   into a control sequence pretty early, so we have to define that control
+%   sequence.
+%    \begin{macrocode}
+\edef\ekv at defsetmacro
+  {%
+    \ekv at unexpanded{\ifx#1\relax\edef#1##1}%
+      {%
+        \ekv at unexpanded\expandafter{\ekv at name@set{#2}}%
+        \ekv at unexpanded\expandafter{\ekv at name@key{##1}}%
+      }%
+    \ekv at unexpanded{\fi}%
+  }
+\ekv at exparg{\protected\def\ekv at defsetmacro#1#2}{\ekv at defsetmacro}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvifdefinedset}
+%    \begin{macrocode}
+\ekv at expargtwice{\def\ekvifdefinedset#1}%
+  {\expandafter\ekv at ifdefined\expandafter{\ekv at undefined@set{#1}}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at ifexp}
+%   We want to be able to include expansion control. This is started by a
+%   specific structure, namely if the stuff to the left of the equals sign
+%   contains a colon followed by a space followed by at least one non-space
+%   token. There is an additional rule namely the contents in front of the
+%   \verb*|: | marker mustn't contain spaces outside of braces, but
+%   unfortunately we can test this only after we did the real split and not as
+%   part of a fast test. The temporary meaning we set up here will get
+%   \tkn{:}{13}\vissp{ } and \tkn{:}{11}\vissp{ } as |#1| and |#2|.
+%
+%   The real definition will take three arguments (two curried), namely the
+%   un-|\detokenize|d name as |#1|, what should be done if the \expnotation\
+%   should start as |#2|, and what should be done if no \expnotation\ is found
+%   as |#3|.
+%    \begin{macrocode}
+\def\ekv at ifexp#1#2%
+  {%
+%    \end{macrocode}
+%   In the following explanations I use \tkn{:}{12}, \tkn{:}{13}, and
+%   \tkn{:}{11}, but I always mean that token followed by a space.
+% \begin{macro}[internal]{\ekv at ifexp@split at o@or at other}
+%   \tkn{:}{12} splitter also used to test for \tkn{:}{13} and \tkn{:}{11}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@split at o@or at other
+        ##1: ##2\ekv at stop##3%
+        ##4#1##5\ekv at stop##6%
+        ##7#2##8\ekv at stop##9%
+      {##9##6##3##1\ekv at stop##2}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]{\ekv at ifexp@split at a@or at l}
+%   \tkn{:}{13} splitter also used to test for \tkn{:}{11}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@split at a@or at l
+        ##1#1##2\ekv at stop##3%
+        ##4#2##5\ekv at stop##6%
+      {##6##3##1\ekv at stop##2}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {\ekv at ifexp@split at a,\ekv at ifexp@split at l}
+%   \tkn{:}{13} splitter
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@split at a##1#1##2\ekv at stop##3%
+      {##3##1\ekv at stop##2}%
+%    \end{macrocode}
+%   \tkn{:}{11} splitter
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@split at l##1#2##2\ekv at stop##3%
+      {##3##1\ekv at stop##2}%
+%    \end{macrocode}
+% \end{macro}
+%   To get good performance in the most common case (standard category codes
+%   apply) we try to split on \tkn{:}{12}, due to the way this split works there
+%   are a few possible outcomes:
+%   \begin{enumerate}
+%     \item |\ekv at ifexp@none| is the first token if no colon was
+%       found at all
+%     \item |\ekv at ifexp@o| is the first token if only \tkn{:}{12}
+%       were part of \key
+%     \item |\ekv at ifexp@a| is put in front of either of the two
+%       aforementioned cases if there was at least one \tkn{:}{13} (in that case
+%       we don't yet know which was the first colon)
+%     \item |\ekv at ifexp@o| is put in front of any of the
+%       aforementioned cases if there was at least one \tkn{:}{11} (in which
+%       case we also don't know yet which was the first colon)
+%   \end{enumerate}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp##1%
+      {%
+        \ekv at ifexp@split at o@or at other
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@o
+          : \ekv at stop\ekv at ifexp@none
+          ##1\ekv at stop\ekv at ifexp@a#1\ekv at stop{}%
+          ##1\ekv at stop\ekv at ifexp@l#2\ekv at stop{}%
+      }%
+%    \end{macrocode}
+% \begin{macro}[internal]
+%   {\ekv at ifexp@o,\ekv at ifexp@none}
+%   If any of the next two are called we already know the outcome and can
+%   directly expand to it.
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@o##1\ekv at stop
+      {\ekv at ifexp@done{##1}\ekv at mark}%
+    \long\def\ekv at ifexp@none
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@o\ekv at stop
+        ##2##3%
+      {##3}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {\ekv at ifexp@a,\ekv at ifexp@a at i,\ekv at ifexp@a at ii}
+%   If this is called we know that there was no \tkn{:}{13}, if the first token
+%   now is |\ekv at ifexp@none| there was no \tkn{:}{12} as well
+%    \begin{macrocode}
+    \def\ekv at ifexp@a##1%
+      {%
+        \ekv at ifexp@a at i
+          ##1\ekv at ifexp@a at ii
+          \ekv at ifexp@none\ekv at ifexp@a at or@o
+      }%
+    \def\ekv at ifexp@a at i##1\ekv at ifexp@none{}%
+%    \end{macrocode}
+%   Easy route, no \tkn{:}{12}, simply grab and pack
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@a at ii
+        \ekv at ifexp@none\ekv at ifexp@a at or@o
+        ##1#1##2\ekv at stop\ekv at ifexp@o\ekv at stop
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {
+%     \ekv at ifexp@a at or@o,
+%     \ekv at ifexp@a at not@o,\ekv at ifexp@a at not@o@,
+%     \ekv at ifexp@o at not@a
+%   }
+%   other route, there is a \tkn{:}{12}, re-split at \tkn{:}{13}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@a at or@o##1\ekv at stop
+      {%
+        \ekv at ifexp@split at a
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@o
+          #1\ekv at stop\ekv at ifexp@o at not@a
+      }%
+%    \end{macrocode}
+%   \tkn{:}{13} came earlier than \tkn{:}{12}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@a at not@o##1\ekv at stop
+      {\ekv at ifexp@a at not@o@{##1}\ekv at mark}
+    \long\def\ekv at ifexp@a at not@o@
+        ##1##2\ekv at nil#1\ekv at stop\ekv at ifexp@o at not@a
+      {\ekv at ifexp@done{##1}##2: }%
+%    \end{macrocode}
+%   \tkn{:}{12} came earlier than \tkn{:}{13}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@o at not@a
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@o\ekv at stop
+      {\ekv at ifexp@done{##1}\ekv at mark}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]{\ekv at ifexp@l,\ekv at ifexp@l at i,\ekv at ifexp@l at ii}
+%   Now this is the most complicated case, if |\ekv at ifexp@l| is
+%   called there are a few possibilities:
+%   \begin{enumerate}
+%     \item |#1| is |\ekv at ifexp@none|: easiest route, only
+%       \tkn{:}{11} was there
+%     \item |#1| is |\ekv at ifexp@o|: complicated route, there was a
+%      \tkn{:}{11} and a \tkn{:}{12}
+%     \item |#1| is |\ekv at ifexp@a| and after that comes
+%      |\ekv at ifexp@none|: more complicated, there was a
+%      \tkn{:}{11} and a \tkn{:}{13}
+%     \item |#1| is |\ekv at ifexp@a| and after that comes
+%      |\ekv at ifexp@o|: cursed route, there were \tkn{:}{11},
+%      \tkn{:}{12}, and \tkn{:}{13}
+%   \end{enumerate}
+%    \begin{macrocode}
+    \def\ekv at ifexp@l##1%
+      {%
+        \ekv at ifexp@l at i
+          ##1\ekv at ifexp@l at ii
+          \ekv at ifexp@none{}%
+          ##1\ekv at ifexp@l at or@o
+          \ekv at ifexp@o
+        \ekv at ifexp@l at or@a
+      }%
+    \def\ekv at ifexp@l at i
+        ##1\ekv at ifexp@none##2%
+        ##3\ekv at ifexp@o
+      {##2}%
+%    \end{macrocode}
+%   easiest route, just \tkn{:}{11}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@l at ii
+        \ekv at ifexp@l at or@a##1#2##2\ekv at stop
+        \ekv at ifexp@o\ekv at stop#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {
+%     \ekv at ifexp@l at or@o,
+%     \ekv at ifexp@l at not@o,\ekv at ifexp@l at not@o@,
+%     \ekv at ifexp@o at not@l
+%   }
+%   slightly harder, \tkn{:}{11} or \tkn{:}{12}, re-split at \tkn{:}{11}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@l at or@o
+        \ekv at ifexp@o\ekv at ifexp@l at or@a
+        ##1\ekv at stop
+      {%
+        \ekv at ifexp@split at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@o
+          #2\ekv at stop\ekv at ifexp@o at not@l
+      }%
+%    \end{macrocode}
+%   \tkn{:}{11} came earlier than \tkn{:}{12}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@l at not@o##1\ekv at stop
+      {\ekv at ifexp@l at not@o@{##1}\ekv at mark}
+    \long\def\ekv at ifexp@l at not@o@
+        ##1##2\ekv at nil#2\ekv at stop\ekv at ifexp@o at not@l
+        ##3#2\ekv at stop##4%
+      {\ekv at ifexp@done{##1}##2: ##3}%
+%    \end{macrocode}
+%   \tkn{:}{12} came earlier than \tkn{:}{11}
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@o at not@l
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@o\ekv at stop
+        ##2#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {
+%     \ekv at ifexp@l at or@a,
+%     \ekv at ifexp@l at or@a at not@o,
+%     \ekv at ifexp@l at not@a,\ekv at ifexp@l at not@a@,
+%     \ekv at ifexp@a at not@l
+%   }
+%   \tkn{:}{13} was in the mix with \tkn{:}{11}, we need to see whether there
+%   was a \tkn{:}{12} as well
+%    \begin{macrocode}
+    \def\ekv at ifexp@l at or@a##1%
+      {%
+%    \end{macrocode}
+%   don't get confused by the name, this gobbles until |@none|
+%    \begin{macrocode}
+        \ekv at ifexp@a at i
+          ##1\ekv at ifexp@l at or@a at not@o
+          \ekv at ifexp@none
+        \ekv at ifexp@l at or@a at or@o
+      }%
+%    \end{macrocode}
+%   phew, no \tkn{:}{12} in the mix, we split at \tkn{:}{13} and see whether an
+%   earlier \tkn{:}{11} is found
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@l at or@a at not@o
+        \ekv at ifexp@none\ekv at ifexp@l at or@a at or@o
+        ##1#1%
+      {%
+        \ekv at ifexp@split at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@a
+          #2\ekv at stop\ekv at ifexp@a at not@l
+      }%
+    \long\def\ekv at ifexp@l at not@a##1\ekv at stop
+      {\ekv at ifexp@l at not@a@{##1}\ekv at mark}%
+    \long\def\ekv at ifexp@l at not@a@
+        ##1##2\ekv at nil#2\ekv at stop\ekv at ifexp@a at not@l
+        ##3\ekv at stop\ekv at ifexp@o\ekv at stop#2\ekv at stop##4%
+      {\ekv at ifexp@done{##1}##2#1##3}%
+    \long\def\ekv at ifexp@a at not@l
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@a\ekv at stop
+        ##2\ekv at stop\ekv at ifexp@o\ekv at stop#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {
+%     \ekv at ifexp@l at or@a at or@o,\ekv at ifexp@l at or@a at or@o at i,\ekv at ifexp@l at or@a at or@o at ii,
+%     \ekv at ifexp@l at or@a at or@o at iii,\ekv at ifexp@l at or@a at or@o at iv,
+%     \ekv at ifexp@o at not@l at or@a,
+%     \ekv at ifexp@a at not@l at or@o,\ekv at ifexp@a at not@l at or@o@
+%   }
+%   ooh no, the ugliest path, we got ourself a \tkn{:}{11}, a \tkn{:}{12}, and a
+%   \tkn{:}{13}, first grab everything left after splitting the first
+%   \tkn{:}{12} and try a \tkn{:}{13} split
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@l at or@a at or@o##1\ekv at stop
+      {%
+        \ekv at ifexp@split at a@or at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@l at or@o
+          #1\ekv at stop\ekv at ifexp@o at not@l at or@a
+          ##1\ekv at stop\ekv at ifexp@l at or@a at or@o at i#2\ekv at stop{}%
+      }%
+%    \end{macrocode}
+%   \tkn{:}{12} splitting was correct
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@o at not@l at or@a
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@l at or@o\ekv at stop
+        ##2#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+%    \end{macrocode}
+%   \tkn{:}{13} split is correct, \tkn{:}{12} has to be reverted
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@a at not@l at or@o##1\ekv at stop
+      {\ekv at ifexp@a at not@l at or@o@{##1}\ekv at mark}
+    \long\def\ekv at ifexp@a at not@l at or@o@
+        ##1##2\ekv at nil##3#2\ekv at stop##4%
+      {\ekv at ifexp@done{##1}##2: ##3}%
+%    \end{macrocode}
+%   there is still a \tkn{:}{11} left, we need to take care of \tkn{:}{13} as
+%   well, but \tkn{:}{12} was wrong
+%    \begin{macrocode}
+    \def\ekv at ifexp@l at or@a at or@o at i##1%
+      {%
+        \ekv at ifexp@l at or@a at or@o at ii
+          ##1\ekv at ifexp@l at or@a at or@o at iii
+          \ekv at ifexp@o at not@l at or@a
+        \ekv at ifexp@why
+      }%
+    \def\ekv at ifexp@l at or@a at or@o at ii
+        ##1\ekv at ifexp@o at not@l at or@a
+      {}%
+%    \end{macrocode}
+%   at least it's not absolutely the worst, \tkn{:}{11} is correct, revert the
+%   \tkn{:}{12} split
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@l at or@a at or@o at iii
+        \ekv at ifexp@o at not@l at or@a\ekv at ifexp@why
+        ##1#2%
+      {\ekv at ifexp@l at or@a at or@o at iv{##1}\ekv at mark}%
+    \long\def\ekv at ifexp@l at or@a at or@o at iv
+        ##1##2\ekv at nil\ekv at stop\ekv at ifexp@a at not@l at or@o\ekv at stop
+        #2\ekv at stop##3##4#2\ekv at stop##5%
+      {\ekv at ifexp@done{##1}##2: ##4}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {
+%     \ekv at ifexp@why,
+%     \ekv at ifexp@why at l,\ekv at ifexp@why at l@i,\ekv at ifexp@why at l@ii,
+%     \ekv at ifexp@why at a
+%   }
+%   why have you forsaken me? We know \tkn{:}{12} was wrong, but now we have
+%   something that might be correctly split at \tkn{:}{13}, but might as well be
+%   not
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@why##1\ekv at stop
+      {%
+        \ekv at ifexp@split at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@why at l
+          #2\ekv at stop\ekv at ifexp@why at a
+      }%
+%    \end{macrocode}
+%   \tkn{:}{11} is correct, rebuild stuff undoing the wrong \tkn{:}{13} split
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@why at l##1\ekv at stop
+      {\ekv at ifexp@why at l@i{##1}\ekv at mark}
+    \long\def\ekv at ifexp@why at l@i
+        ##1##2\ekv at nil#2\ekv at stop\ekv at ifexp@why at a
+      {\ekv at ifexp@why at l@ii{##1}##2#1}
+%    \end{macrocode}
+%   and undoing the wrong \tkn{:}{12} split
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@why at l@ii
+        ##1##2\ekv at nil#2\ekv at stop##3##4#2\ekv at stop##5%
+      {\ekv at ifexp@done{##1}##2: ##4}%
+%    \end{macrocode}
+%   \tkn{:}{13} is correct, we know there is a \tkn{:}{11} hiding somewhere, so
+%   we don't need to protect against brace strip using a two-step grab here,
+%   just undoing the wrong \tkn{:}{12} split is enough
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@why at a
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@why at l\ekv at stop
+        ##2\ekv at nil#2\ekv at stop##3##4#2\ekv at stop##5%
+      {\ekv at ifexp@done{##1}\ekv at mark##2: ##4}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {
+%     \ekv at ifexp@done,\ekv at ifexp@done@,
+%     \ekv at ifexp@done at test,
+%     \ekv at ifexp@panic
+%   }
+%   once the colon split is done we need to check that there are no spaces in
+%   the now split of part, if there are \emph{panic} (we did all of this for
+%   nothing), else we're finally completely done with the splitting business.
+%    \begin{macrocode}
+    \ekv at exparg{\long\def\ekv at ifexp@done##1##2\ekv at nil}%
+      {%
+        \@firstofone
+          {\ekv at ifexp@done at test##1\ekv at nil\ekv at ifexp@panic} \ekv at nil{}%
+          ##2\ekv at stop\ekv at ifexp@done@{##1}{##2}\ekv at stop\@secondoftwo
+      }
+    \long\def\ekv at ifexp@done at test##1 ##2\ekv at nil##3##4##5##6\ekv at stop{##3}
+    \ekv at exparg{\long\def\ekv at ifexp@done@##1##2\ekv at stop\@secondoftwo##3}%
+      {\ekv at strip{##2}{##3{##1}}}%
+%    \end{macrocode}
+%   Panic in this case means give up on expansion parsing, instead the normal
+%   action that would've been done if the expansion mark isn't found is
+%   executed.
+%    \begin{macrocode}
+    \long\def\ekv at ifexp@panic##1\@secondoftwo##2##3{##3}
+  }
+%    \end{macrocode}
+% \end{macro}
+%   We set up the strange category codes for colons and do the real definition
+%   after the temporary one.
+%    \begin{macrocode}
+\begingroup
+  \catcode`\~=13
+  \lccode`\~=`\:
+  \catcode`\z=11
+  \lccode`\z=`\:
+\lowercase{\endgroup
+\ekv at ifexp{~ }{z }}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvset}
+% Set up |\ekvset|, which should not be affected by active commas and equal
+% signs. The equal signs are a bit harder to cope with and we'll do that later,
+% but the active commas can be handled by just doing two comma-splitting loops
+% one at actives one at others. That's why we define |\ekvset| here with a
+% temporary meaning just to set up the things with two different category codes.
+% |#1| will be a \texttt{,\textsubscript{13}} and |#2| will be a
+% \texttt{=\textsubscript{13}}.
+%    \begin{macrocode}
+\begingroup
+\def\ekvset#1#2{%
+\endgroup
+\ekv at exparg{\long\def\ekvset##1##2}%
+  {%
+    \expandafter\expandafter\expandafter
+    \ekv at set\expandafter\csname\ekv at undefined@set{##1}\endcsname
+      \ekv at mark##2#1\ekv at stop#1{}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at set}
+% |\ekv at set| will split the \kv\ list at active commas. Then it has to check
+% whether there were unprotected other commas and resplit there.
+%    \begin{macrocode}
+\long\def\ekv at set##1##2#1%
+  {%
+%    \end{macrocode}
+% Test whether we're at the end, if so invoke |\ekv at endset|,
+%    \begin{macrocode}
+    \ekv at gobble@from at mark@to at stop##2\ekv at endset\ekv at stop
+%    \end{macrocode}
+% else go on with other commas.
+%    \begin{macrocode}
+    \ekv at set@other##1##2,\ekv at stop,%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at endset}
+% |\ekv at endset| is a hungry little macro. It will eat everything that remains
+% of |\ekv at set| and unbrace the sneaked stuff.
+%    \begin{macrocode}
+\long\def\ekv at endset\ekv at stop\ekv at set@other##1\ekv at mark\ekv at stop,\ekv at stop,##2%
+  {##2}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at eq@other at or@active,\ekv at eq@active}
+%   Splitting at equal signs will be done in a way that checks whether there is
+%   an equal sign and splits at the same time. This gets quite messy and the
+%   code might look complicated, but this is pretty fast (faster than first
+%   checking for an equal sign and splitting if one is found). The splitting
+%   code will be adapted for |\ekvset| and |\ekvparse| to get the most speed,
+%   but some of these macros don't require such adaptions.
+%   |\ekv at eq@other at or@active| and |\ekv at eq@active| will split the argument at
+%   the first equal sign. |\ekv at eq@active| will insert the macro which comes
+%   after the first following |\ekv at mark|, while |\ekv at eq@other at or@active| will
+%   also check for an active equals sign or none.
+%   Usage should look like this:
+%   \begin{syntaxexample*}
+%     |\ekv at eq@other at or@active|
+%       \indent|#1\ekv at nil\ekv at mark|\meta{code for \tkn{=}{12}}
+%       \indent\tkn{=}{12}|\ekv at mark|\meta{code for no equals sign}
+%       \indent|#1\ekv at mark|\meta{code for \tkn{=}{13} or mixed}
+%       \indent\tkn{=}{13}|\ekv at mark{}|
+%     |\ekv at eq@active|
+%       \indent|#1\ekv at nil\ekv at mark|\meta{code for \tkn{=}{13}}
+%       \indent\tkn{=}{13}|\ekv at mark|\meta{code for no \tkn{=}{13}}
+%   \end{syntaxexample*}
+%   To prevent accidental brace stripping |#1| should be handed in with a
+%   leading |\ekv at mark|, also that's what the |\ekv at nil| after the first |#1| is
+%   used for. In |\ekv at eq@other at or@active| four cases are distinguished:
+%   \begin{enumerate}
+%     \item
+%       Only equals signs of category 12 are found, then \meta{code for
+%       \tkn{=}{12}} will be inserted.
+%     \item
+%       No equals sign is found, then \meta{code for no equals sign} will be
+%       inserted.
+%     \item
+%       Only equals signs of category 13 are found, then \meta{code for
+%       \tkn{=}{13} or mixed} will be inserted, directly followed by
+%       \meta{code for no equals sign}.
+%     \item
+%       Equals signs of categories 12 and 13 are found, then \meta{code for
+%       \tkn{=}{13} or mixed} directly followed by \meta{code for \tkn{=}{12}}
+%       will be inserted.
+%   \end{enumerate}
+%   This allows for fast branching based on \TeX's argument grabbing rules and
+%   we don't have to split after the branching if the equal sign was there.
+%    \begin{macrocode}
+\long\def\ekv at eq@other at or@active
+    ##1=##2\ekv at mark##3%
+    ##4#2##5\ekv at mark##6%
+  {##6##3##1\ekv at stop\ekv at mark##2}
+\long\def\ekv at eq@other##1=##2\ekv at mark##3{##3##1\ekv at stop\ekv at mark##2}
+\long\def\ekv at eq@active##1#2##2\ekv at mark##3{##3##1\ekv at stop\ekv at mark##2}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at set@other,\ekv at set@next at other}
+%   The macro |\ekv at set@other| is guaranteed to get only single \kv\ pairs.
+%    \begin{macrocode}
+\long\def\ekv at set@other##1##2,%
+  {%
+%    \end{macrocode}
+%   First we test whether we're done.
+%    \begin{macrocode}
+    \ekv at gobble@from at mark@to at stop##2\ekv at endset@other\ekv at stop
+%    \end{macrocode}
+%   If not we split at the equal sign of category other.
+%    \begin{macrocode}
+    \ekv at eq@other at or@active
+      ##2\ekv at nil\ekv at mark\ekv at set@eq at other
+      =\ekv at mark\ekv at set@noeq
+      ##2\ekv at mark\ekv at set@eq at active
+      #2\ekv at mark{}%
+%    \end{macrocode}
+%   And put the set name after the splitting.
+%    \begin{macrocode}
+    ##1%
+    \ekv at mark
+  }
+%    \end{macrocode}
+%   The second macro is used as a shortcut to gobble two arguments and do the
+%   same as a following |\ekv at set@other|.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at set@next at other##1##2\ekv at set@other##3##4,}%
+  {\ekv at set@other{##3}{##4},}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at endset@other}
+%   Breaking the current inner loop for \tkn{,}{12} is done by gobbling all the
+%   remaining tokens and grabbing the next split at an active comma
+%   (incorporating the next |\ekv at set| call).
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at endset@other
+    \ekv at stop\ekv at eq@other at or@active
+    \ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at set@eq at other
+    =\ekv at mark\ekv at set@noeq
+    \ekv at mark\ekv at stop\ekv at mark\ekv at set@eq at active#2\ekv at mark##1%
+    ##2##3#1}%
+  {\ekv at set{##2}{##3}#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at set@eq at other}
+%   If this gets called we know that there is no \tkn{=}{13}, hence are done
+%   with the splitting business. This doesn't even need much clean up, we can
+%   just strip the \key-name and forward it to |\ekv at set@pair|.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at set@eq at other##1\ekv at stop}%
+  {\ekv at strip@key{##1}\ekv at set@pair}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at set@if at noeq}
+%   In the case that there was at least one \tkn{=}{13} we need a way to know
+%   whether there also was a \tkn{=}{12}. This here can be used to check this by
+%   only looking for |\ekv at set@noeq|.
+%    \begin{macrocode}
+\def\ekv at set@if at noeq##1\ekv at set@noeq{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at set@eq at active,\ekv at set@eq at active@}
+%   The first token after this will either be |\ekv at set@noeq| or
+%   |\ekv at set@eq at other|. We test this and branch accordingly.
+%    \begin{macrocode}
+\def\ekv at set@eq at active##1%
+  {\ekv at set@if at noeq##1\ekv at set@eq at active@\ekv at set@noeq\ekv at set@eq at mixed}
+%    \end{macrocode}
+%   Since we know that there was no \tkn{=}{12} when the next macro is called we
+%   can simply do the correct split without any checks and forward to
+%   |\ekv at set@pair|.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at set@eq at active@
+    \ekv at set@noeq\ekv at set@eq at mixed
+    ##1#2##2\ekv at mark
+    \ekv at set@eq at other\ekv at stop\ekv at mark#2\ekv at mark##3}%
+  {\ekv at strip@key{##1}\ekv at set@pair\ekv at mark##2}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekv at set@eq at mixed,\ekv at set@eq at mixed@o,\ekv at set@mixed at a}
+%   In the mixed case we grab until the first split of \tkn{=}{12} already done,
+%   and resplit at \tkn{=}{13} using the conditonal splitter described earlier.
+%    \begin{macrocode}
+\long\def\ekv at set@eq at mixed##1\ekv at stop
+  {%
+    \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at mixed@a
+      #2\ekv at mark\ekv at set@eq at mixed@o
+  }
+%    \end{macrocode}
+%   If there actually was no \tkn{=}{13} before the first \tkn{=}{12} everything
+%   was fine. We pick up our first split and remove the gibberish left by the
+%   conditional splitter.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at set@eq at mixed@o
+    ##1\ekv at nil\ekv at mark\ekv at set@eq at mixed@a\ekv at stop\ekv at mark
+    ##2\ekv at nil#2\ekv at mark##3}%
+  {\ekv at strip@key{##1}\ekv at set@pair##2\ekv at nil}
+%    \end{macrocode}
+%   |\ekv at set@eq at mixed@a| will trigger if before the first \tkn{=}{12} there was
+%   already a \tkn{=}{13}. So we use the new split and revert the erroneous
+%   split at \tkn{=}{12}.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at set@eq at mixed@a
+    ##1\ekv at stop
+    ##2\ekv at nil#2\ekv at mark\ekv at set@eq at mixed@o\ekv at mark
+    ##3#2\ekv at mark##4}%
+  {\ekv at strip@key{##1}\ekv at set@pair##2=##3}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at set@noeq,\ekv at set@was at blank}
+%   If there was no equals sign the current element might in fact be blank.
+%   Blank elements are ignored, hence we need to check for that, else we can
+%   call |\ekv at set@key|.
+%    \begin{macrocode}
+\ekv at expandedarg
+  {%
+    \long\def\ekv at set@noeq
+      ##1\ekv at nil\ekv at mark\ekv at set@eq at other\ekv at stop\ekv at mark
+  }%
+  {%
+    \ekv at unexpanded
+      {%
+        \ekv at ifblank@##1\ekv at stop\ekv at ifblank@gobbletrue
+          \ekv at stop\ekv at set@was at blank
+      }%
+    \ekv at unexpanded\expandafter{\ekv at strip@key{##1}\ekv at set@key}%
+  }
+%    \end{macrocode}
+%   If in fact the element was blank we remove the |\ekv at set@key| call and
+%   instead do the next iteration of |\ekv at set@other|.
+%    \begin{macrocode}
+\ekv at exparg{\long\expandafter\def\expandafter\ekv at set@was at blank
+    \ekv at strip@key{\ekv at mark##1}\ekv at set@key
+    ##2##3,}%
+  {\ekv at set@other{##2}{##3},}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvbreak,\ekvbreakPreSneak,\ekvbreakPostSneak}
+% Provide macros that can completely stop the parsing of |\ekvset|, who knows
+% what it'll be useful for.
+%    \begin{macrocode}
+\long\def\ekvbreak##1##2\ekv at stop#1##3{##1}
+\long\def\ekvbreakPreSneak ##1##2\ekv at stop#1##3{##1##3}
+\long\def\ekvbreakPostSneak##1##2\ekv at stop#1##3{##3##1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvsneak,\ekvsneakPre}
+% One last thing we want to do for |\ekvset| is to provide macros that just
+% smuggle stuff after |\ekvset|'s effects.
+%    \begin{macrocode}
+\long\def\ekvsneak##1##2\ekv at stop#1##3{##2\ekv at stop#1{##3##1}}
+\long\def\ekvsneakPre##1##2\ekv at stop#1##3{##2\ekv at stop#1{##1##3}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvparse}
+% Additionally to the |\ekvset| macro we also want to provide an |\ekvparse|
+% macro, that has the same scope as |\keyval_parse:NNn| from \pkg{expl3}.
+% This is pretty analogue to the |\ekvset| implementation, we just put an
+% |\unexpanded| here and there instead of other macros to stop the |\expanded|
+% on our output. The |\unexpanded\expanded{{...}}| ensures that the material
+% is in an alignment safe group at all time, and that it doesn't expand any
+% further in an |\edef| or |\expanded| context.
+%    \begin{macrocode}
+\long\def\ekvparse##1##2##3%
+  {%
+    \ekv at unexpanded\ekv at expanded
+      {{\ekv at parse{##1}{##2}\ekv at mark##3#1\ekv at stop#1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse}
+%    \begin{macrocode}
+\long\def\ekv at parse##1##2##3#1%
+  {%
+    \ekv at gobble@from at mark@to at stop##3\ekv at endparse\ekv at stop
+    \ekv at parse@other{##1}{##2}##3,\ekv at stop,%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at endparse}
+%    \begin{macrocode}
+\long\def\ekv at endparse\ekv at stop\ekv at parse@other##1\ekv at mark\ekv at stop,\ekv at stop,%
+  {}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse@other}
+%    \begin{macrocode}
+\long\def\ekv at parse@other##1##2##3,%
+  {%
+    \ekv at gobble@from at mark@to at stop##3\ekv at endparse@other\ekv at stop
+    \ekv at eq@other at or@active
+      ##3\ekv at nil\ekv at mark\ekv at parse@eq at other
+      =\ekv at mark\ekv at parse@noeq
+      ##3\ekv at mark\ekv at parse@eq at active#2\ekv at mark{}%
+    {##1}{##2}%
+    \ekv at mark
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at endparse@other}
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at endparse@other
+    \ekv at stop\ekv at eq@other at or@active
+    \ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at parse@eq at other
+    =\ekv at mark\ekv at parse@noeq
+    \ekv at mark\ekv at stop\ekv at mark\ekv at parse@eq at active#2\ekv at mark##1%
+    ##2##3##4#1}%
+  {\ekv at parse{##2}{##3}{##4}#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse@eq at other}
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at parse@eq at other##1\ekv at stop}%
+  {\ekv at strip{##1}\ekv at parse@pair}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse@if at noeq}
+%    \begin{macrocode}
+\def\ekv at parse@if at noeq##1\ekv at parse@noeq{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse@eq at active,\ekv at parse@eq at active@}
+%    \begin{macrocode}
+\def\ekv at parse@eq at active##1%
+  {%
+    \ekv at parse@if at noeq##1\ekv at parse@eq at active@\ekv at parse@noeq
+    \ekv at parse@eq at mixed
+  }
+\ekv at exparg{\long\def\ekv at parse@eq at active@
+    \ekv at parse@noeq\ekv at parse@eq at mixed
+    ##1#2##2\ekv at mark
+    \ekv at parse@eq at other\ekv at stop\ekv at mark#2\ekv at mark##3}%
+  {\ekv at strip{##1}\ekv at parse@pair\ekv at mark##2}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekv at parse@eq at mixed,\ekv at parse@eq at mixed@o,\ekv at parse@eq at mixed@a}
+%    \begin{macrocode}
+\long\def\ekv at parse@eq at mixed##1\ekv at stop
+  {%
+    \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at mixed@a
+      #2\ekv at mark\ekv at parse@eq at mixed@o
+  }
+\ekv at exparg{\long\def\ekv at parse@eq at mixed@a
+    ##1\ekv at stop
+    ##2\ekv at nil#2\ekv at mark\ekv at parse@eq at mixed@o\ekv at mark
+    ##3#2\ekv at mark##4}%
+  {\ekv at strip{##1}\ekv at parse@pair##2=##3}
+\ekv at exparg{\long\def\ekv at parse@eq at mixed@o
+    ##1\ekv at nil\ekv at mark\ekv at parse@eq at mixed@a\ekv at stop\ekv at mark
+    ##2\ekv at nil#2\ekv at mark##3}%
+  {\ekv at strip{##1}\ekv at parse@pair##2\ekv at nil}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse@noeq,\ekv at parse@was at blank}
+%    \begin{macrocode}
+\ekv at expandedarg
+  {%
+    \long\def\ekv at parse@noeq
+      ##1\ekv at nil\ekv at mark\ekv at parse@eq at other\ekv at stop\ekv at mark
+  }%
+  {%
+    \ekv at unexpanded
+      {%
+        \ekv at ifblank@##1\ekv at stop\ekv at ifblank@gobbletrue
+          \ekv at stop\ekv at parse@was at blank
+      }%
+    \ekv at unexpanded\expandafter{\ekv at strip{##1}\ekv at parse@key}%
+  }
+\ekv at exparg{\long\expandafter\def\expandafter\ekv at parse@was at blank
+    \ekv at strip{\ekv at mark##1}\ekv at parse@key
+    ##2##3##4,}%
+  {\ekv at parse@other{##2}{##3}{##4},}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse@pair,\ekv at parse@pair@}
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at parse@pair##1##2\ekv at nil}%
+  {\ekv at strip{##2}\ekv at parse@pair@{##1}}
+\ekv at exparg{\long\def\ekv at parse@pair@##1##2##3##4}%
+  {%
+    \ekv at ifexp{##2}%
+      {\ekv at expansion@parse at pair{##1}{##4}}%
+      {\ekv at unexpanded{##4{##2}{##1}}}%
+    \ekv at parse@other{##3}{##4}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at parse@key}
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at parse@key##1##2}%
+  {%
+    \ekv at ifexp{##1}%
+      {\ekv at expansion@parse at key{##2}}%
+      {\ekv at unexpanded{##2{##1}}}%
+    \ekv at parse@other{##2}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% Finally really setting things up with |\ekvset|'s temporary meaning:
+%    \begin{macrocode}
+}
+\catcode`\,=13
+\catcode`\==13
+\ekvset,=
+%    \end{macrocode}
+%
+% \begin{macro}{\ekvsetSneaked}
+% This macro can be defined just by expanding |\ekvsneak| once after expanding
+% |\ekvset|. To expand everything as much as possible early on we use a
+% temporary definition.
+%    \begin{macrocode}
+\edef\ekvsetSneaked
+  {%
+    \ekv at unexpanded{\ekvsneak{#2}}%
+    \ekv at unexpanded\expandafter{\ekvset{#1}{#3}}%
+  }
+\ekv at expargtwice{\long\def\ekvsetSneaked#1#2#3}{\ekvsetSneaked}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvchangeset}
+% Provide a macro that is able to switch out the current \set\ in |\ekvset|.
+% This operation allows something similar to \pkg{pgfkeys}'s
+% \texttt{\meta{key}/.cd} mechanism. However this operation can be more
+% expensive than |/.cd| as we can't just redefine some token to reflect this,
+% but have to switch out the set expandably, so this works similar to the
+% |\ekvsneak| macros reading and reinserting things, but it only has to read and
+% reinsert the remainder of the current key's replacement code.
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvchangeset#1}%
+  {%
+    \expandafter\expandafter\expandafter
+    \ekv at changeset\expandafter\csname\ekv at undefined@set{#1}\endcsname\ekv at empty
+  }
+%    \end{macrocode}
+% \begin{macro}[internal]{\ekv at changeset}
+% This macro does the real change-out of |\ekvchangeset|. |#2| will have a
+% leading |\ekv at empty| so that braces aren't stripped accidentally, but that
+% will not hurt and just expand to nothing in one step.
+%    \begin{macrocode}
+\long\def\ekv at changeset#1#2\ekv at set@other#3{#2\ekv at set@other#1}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvmorekv}
+%   |\ekvmorekv| injects additional keys for consideration without needing a
+%   nested |\ekvset|. The issue we're facing here is that we can only inject
+%   after the next |\ekv at set@other| to not destroy the order of things, but in
+%   theory the argument to |\ekvmorekv| could contain an active comma. Now we
+%   have two options:
+%   \begin{enumerate}
+%     \item reread all keys until the end of the current |\ekv at set@other| loop
+%       to change the commas there to an active one and insert |\ekv at set|
+%       instead
+%     \item loop over the argument of |\ekvmorekv| to remove all top-level
+%       active commas and replace them with ones of category 12.
+%   \end{enumerate}
+%   The following implements the second approach. We use a temporary definition
+%   of |\ekvmorekv| to get us |#1| for active commas. For the comma replacement
+%   we set up a small loop. The |\ekv at empty| at the end of |\ekvmorekv|'s
+%   definition protects against accidental brace loss in user code.
+%    \begin{macrocode}
+\def\ekvmorekv#1%
+  {%
+    \long\def\ekvmorekv##1%
+      {%
+        \expandafter\ekv at morekv\ekv at expanded
+          {{\ekv at morekv@loop\ekv at empty##1\ekv at stop\ekv at morekv@done#1}}%
+        \ekv at empty
+      }%
+%    \end{macrocode}
+% \begin{macro}[internal]{\ekv at parse@more,\ekv at parse@more@}
+%   For the expansion control we also need a way to support reinsertion in
+%   |\ekvparse|. Since there no user code is executed this is an internal macro.
+%   It works in the same way but the argument order exchange is different. Also,
+%   since this is only used internally, we know it is safe to omit the trailing
+%   |\ekv at empty|.
+%    \begin{macrocode}
+    \long\def\ekv at parse@more##1\@gobble##2%
+      {%
+        \expandafter\ekv at parse@more@\ekv at expanded
+          {{\ekv at morekv@loop\ekv at empty##1\ekv at stop\ekv at morekv@done#1}}%
+      }%
+    \long\def\ekv at parse@more@##1\ekv at parse@other##2##3\ekv at mark
+      {\ekv at parse@other{##2}{##3}\ekv at mark##1,}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]{\ekv at morekv}
+%   This is just a simple change of argument order, injecting the new comma
+%   separated list after the current |\ekv at set@other| call.
+%    \begin{macrocode}
+    \long\def\ekv at morekv##1##2\ekv at set@other##3\ekv at mark
+      {##2\ekv at set@other##3\ekv at mark##1,}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+%   {\ekv at morekv@loop,\ekv at morekv@done,\ekv at morekv@wrap}
+%   And here is the heavy lifting of the comma replacement. Each list element
+%   until the next active comma is read and left as an argument for
+%   |\ekv at morekv@wrap|, that will remove the leading |\ekv at empty|. The trick for
+%   a fast end of the loop is that |\ekv at morekv@wrap| will read until the next
+%   |\ekv at stop|, of which an additional one is put before |\ekv at morekv@done| so
+%   that |wrap| will wrap the real end of the list and then |done| removes the
+%   excess code.
+%    \begin{macrocode}
+    \long\def\ekv at morekv@loop##1#1%
+      {\ekv at morekv@wrap##1\ekv at stop,\ekv at morekv@loop\ekv at empty}%
+    \long\def\ekv at morekv@wrap##1\ekv at stop{\ekv at unexpanded\expandafter{##1}}%
+    \def\ekv at morekv@done\ekv at stop,\ekv at morekv@loop\ekv at empty{}%
+  }
+\begingroup\catcode`\,=13 \@firstofone{\endgroup\ekvmorekv,}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at def@expansion at rule,\ekv at def@expansion at rule@ea,
+%     \ekv at expansion@rule@,\ekv at expansion@csname
+%   }
+%   All expansion rules share the same basic structure, they do their expansion
+%   step and then call |\ekv at expansion@rule@| (this could be done faster by
+%   letting each rule build the macro for the next rule in |\csname|, but that
+%   would require a more complex argument grabbing structure of the rules, and
+%   we'd need to use |\expanded{\unexpanded{\csname ...\endcsname}\expandafter}|
+%   or similar to not do the expansion steps of the \val\ inside of |\csname|).
+%   As a result of this the \val\ needs to be grabbed twice per expansion step.
+%    \begin{macrocode}
+\protected\def\ekv at def@expansion at rule#1#2#3#4%
+  {%
+    \long\expandafter\def\csname ekv at expansion@rule@#1\endcsname##1#2%
+      {#3\ekv at expansion@rule@#4}%
+  }
+\protected\def\ekv at def@expansion at rule@ea#1#2%
+  {\ekv at def@expansion at rule{#1}{#2}\expandafter}
+%    \end{macrocode}
+%   Rules follow this naming scheme. Note that for an undefined rule an error is
+%   thrown and the result of the |\csname| is |\ekv at expansion@rule@|.
+%    \begin{macrocode}
+\long\def\ekv at expansion@csname#1\ekv at stop
+  {%
+    ekv at expansion@rule@%
+    \ifcsname ekv at expansion@rule@#1\endcsname
+      #1%
+    \else
+      \ekv at err@undefined at expansion{#1}%
+    \fi
+  }
+%    \end{macrocode}
+%   This auxiliary macro simply builds the next rule, it is used to start an
+%   expansion chain, as well as for each defined or undefined rule.
+%    \begin{macrocode}
+\long\def\ekv at expansion@rule@#1#2%
+  {\csname\expandafter\ekv at expansion@csname\string#2\ekv at stop\endcsname{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at expansion@rule@\ekv at mark}
+%   The expansion chain is ended by an internal rule that behaves very different
+%   from the others. It'll test whether the |r|-rule was used (in which case the
+%   third argument will not be empty, and also execute that reinsertion) or grab
+%   the code for the next step after the expansion.
+%    \begin{macrocode}
+\ekv at exparg
+  {%
+    \long\expandafter
+    \def\csname ekv at expansion@rule@\string\ekv at mark\endcsname
+      #1\ekv at stop#2#3#4#5%
+  }%
+  {%
+    \romannumeral\ekv at exparg{\expandafter\ekv at zero\ekv at ifempty{#3}{#5{#2}{#1}}}%
+      {\ekv at ifempty{#2}{#4{#1}}{\ekv at err@val at no@reinsert{#2}}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at expansion@rule at o,\ekv at expansion@rule at e,\ekv at expansion@rule at c,
+%     \ekv at expansion@rule at f,\ekv at expansion@rule at V,\ekv at expansion@rule at v,
+%     \ekv at expansion@rule at s,\ekv at expansion@rule at b,\ekv at expansion@rule@\r,
+%     \ekv at expansion@rule at g,\ekv at expansion@rule at p,\ekv at expansion@rule at P,
+%     \ekv at expansion@rule at r,\ekv at expansion@rule at R
+%   }
+%   All the expansion rules are executed inside a |\csname| construct, so they
+%   have to issue an |\endcsname| after the intended expansion took place. I
+%   guess the code is pretty straight forward here.
+%    \begin{macrocode}
+\ekv at def@expansion at rule@ea{o}{}{\expandafter{#1}}
+\ekv at def@expansion at rule@ea{e}{}{\ekv at expanded{{#1}}}
+\ekv at def@expansion at rule@ea{c}{}{\csname#1\endcsname}
+\ekv at def@expansion at rule@ea{f}{}{\expandafter{\romannumeral`\^^@#1}}
+\ekv at exparg{\ekv at def@expansion at rule{s}{}}{\ekv at strip{\ekv at mark#1}}{}
+\ekv at def@expansion at rule{b}{}{}{{{#1}}}
+\ekv at def@expansion at rule{\string\r}{#2\ekv at stop#3#4}{}{{#1}#2\ekv at stop{#3}{#4r}}
+\ekv at def@expansion at rule@ea{g}{}{\expandafter{\@gobble#1}}
+\ekv at def@expansion at rule{p}{#2}{}{{#2#1}}
+\ekv at def@expansion at rule{P}{#2}{}{{#1#2}}
+%    \end{macrocode}
+%   The |V| and |v| rules are a bit more complicated. They use some auxiliaries
+%   but otherwise should be more or less obvious as well. The |v| one uses some
+%   expansion to get a more meaningful error message in case the resulting
+%   control sequence would be undefined (without actually using |\csname|, to
+%   not accidentally define anything as |\relax|).
+%    \begin{macrocode}
+\long\def\ekv at expansion@rule at V#1%
+  {%
+    \ifx\relax#1\ekv at err@erroneous at variable{#1}\ekv at expansion@@clean at V\fi
+    \ekv at expansion@@V{#1}%
+  }
+\ekv at expandedarg{\long\def\ekv at expansion@rule at v#1}%
+  {%
+    \ekv at unexpanded{\ekv at ifdefined{#1}%
+      {\expandafter\ekv at expansion@@V\csname#1\endcsname}}%
+      {%
+        \ekv at unexpanded{\expandafter\ekv at err@erroneous at variable\ekv at expanded}%
+          {{\expandafter\@gobble\string\\#1}}%
+        \ekv at unexpanded{\ekv at expansion@rule@}{}%
+      }%
+  }
+\ekv at exparg{\long\def\ekv at expansion@rule at r#1#2\ekv at stop#3#4}%
+  {\ekv at expansion@rule at v{#1}#2\ekv at stop{#3}{#4r}}
+\ekv at exparg{\long\def\ekv at expansion@rule at R#1#2\ekv at stop#3#4}%
+  {\ekv at expansion@rule at V{#1}#2\ekv at stop{#3}{#4r}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at expansion@@V,\ekv at expansion@@clean at V}
+%   The actual |V| evaluation is pretty much the same as in \pkg{expl3}, but we
+%   need to put braces around the expansion result, hence branch slightly
+%   differently. In general, a macro will temporarily have the meaning of
+%   |\relax| if hit by |\noexpand| and hence the \cs[no-index]{ifx} test will
+%   result in false (as the meaning isn't the same now), so we can tell
+%   whether it would expand directly. Else we assume this is a register type and
+%   use |\the|.
+%    \begin{macrocode}
+\long\def\ekv at expansion@@V#1%
+  {%
+    \expandafter\ifx\noexpand#1#1%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+    {\expandafter\ekv at expansion@rule@\expandafter{\the#1}}%
+    {\expandafter\ekv at expansion@rule@\expandafter{#1}}%
+  }
+\long\def\ekv at expansion@@clean at V\fi\ekv at expansion@@V#1%
+  {\fi\ekv at expansion@rule@{}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {\ekv at expansion@rule@\key,\ekv at expansion@rule@\ekv at key@after}
+%   The |\key|-rule works by calling a nested expansion chain with swapped \key\
+%   and \val. Instead of |\ekv at mark| marking the end of the expansion chain
+%   we use a different final step called |\ekv at key@after|, that simply checks
+%   whether an |r|-rule was executed (\emph{error}) and ends the current
+%   expansion step in the outer chain.
+%    \begin{macrocode}
+\ekv at def@expansion at rule{\string\key}{#2#3\ekv at stop#4}%
+  {}{{#4}#2\ekv at key@after\ekv at stop{#1}{}{#3}}
+\ekv at exparg{\ekv at def@expansion at rule{\string\ekv at key@after}{\ekv at stop#2#3#4}}%
+  {\ekv at ifempty{#3}{}\ekv at err@key at no@reinsert}
+  {{#2}#4\ekv at stop{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at set@pair,\ekv at set@pair@,
+%     \ekv at set@pair at relax,\ekv at set@pair at undefined,
+%     \ekv at set@pair at u,\ekv at set@pair at u@relax,\ekv at set@pair at no@u
+%   }
+%   |\ekv at set@pair| gets invoked with the space and brace stripped key-name as
+%   its first, the value as the second (delimited by |\ekv at nil|), and the set
+%   name as the third argument. It provides tests for the key-macros and
+%   everything to be able to throw meaningful error messages if it isn't
+%   defined. We have two routes here, one if |\lastnamedcs| is defined and one
+%   if it isn't. The big difference is that if it is we can omit a |\csname| and
+%   instead just expand |\lastnamedcs| once to get the control sequence.
+%   If the macro is defined the value will be space and brace stripped and the
+%   key-macro called. Else branch into the error handling provided by
+%   |\ekv at set@pair at undefined|.
+%    \begin{macrocode}
+\ekv at if@lastnamedcs
+  {%
+    \long\def\ekv at set@pair#1\ekv at mark#2#3\ekv at nil#4%
+      {%
+        \ifcsname#4{#1}\endcsname\expandafter\ekv at set@pair@\lastnamedcs\fi
+        \ekv at set@pair at undefined{#3}{#1}{#2}%
+        \ekv at set@other#4%
+      }
+    \ekv at exparg{\long\def\ekv at set@pair at undefined#1#2#3\ekv at set@other#4}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\expandafter\ekv at zero\ekv at ifexp{#3}}%
+          {\ekv at strip{#1}\ekv at expansion@set at pair}%
+          {%
+            \ifcsname#4{}u\endcsname\expandafter\ekv at set@pair at u\lastnamedcs\fi
+            \ekv at set@pair at no@u{#1}{#2}{#3}%
+          }%
+        \ekv at set@other#4%
+      }
+  }
+  {%
+    \long\def\ekv at set@pair#1\ekv at mark#2#3\ekv at nil#4%
+      {%
+        \ifcsname#4{#1}\endcsname
+          \expandafter\ekv at set@pair@\csname#4{#1}\endcsname
+        \fi
+        \ekv at set@pair at undefined{#3}{#1}{#2}%
+        \ekv at set@other#4%
+      }
+    \ekv at exparg{\long\def\ekv at set@pair at undefined#1#2#3\ekv at set@other#4}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\expandafter\ekv at zero\ekv at ifexp{#3}}%
+          {\ekv at strip{#1}\ekv at expansion@set at pair}%
+          {%
+            \ifcsname#4{}u\endcsname
+              \expandafter\ekv at set@pair at u\csname#4{}u\endcsname
+            \fi
+            \ekv at set@pair at no@u{#1}{#2}{#3}%
+          }%
+        \ekv at set@other#4%
+      }
+  }
+\ekv at expandedarg{\long\def\ekv at set@pair@#1\fi\ekv at set@pair at undefined#2}%
+  {%
+    \ekv at unexpanded{\fi\ifx#1\relax\ekv at set@pair at relax\fi}%
+    \ekv at unexpanded\expandafter{\ekv at strip{#2}#1\ekv at set@next at other}%
+  }
+\ekv at expandafter{\long\def\ekv at set@pair at relax\fi}%
+    \ekv at strip{#1}#2\ekv at set@next at other
+  {\fi\ekv at set@pair at undefined{#1}}
+\ekv at expandedarg{\long\def\ekv at set@pair at u#1\fi\ekv at set@pair at no@u#2}%
+  {%
+    \ekv at unexpanded
+      {%
+        \fi
+        \ifx\relax#1%
+          \ekv at set@pair at u@relax
+        \fi
+      }%
+    \ekv at unexpanded\expandafter{\ekv at strip{#2}#1}%
+  }
+\ekv at expandafter{\long\def\ekv at set@pair at u@relax\fi}\ekv at strip{\ekv at mark#1}#2%
+  {\fi\ekv at set@pair at no@u.}
+\long\def\ekv at set@pair at no@u#1#2#3\ekv at set@other#4%
+  {%
+    \ekv at ifdefined{#4{#2}N}%
+      \ekv at err@noarg
+      \ekv at err@unknown
+        #4{#2}{#3}%
+    \ekv at set@other#4%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at set@key,\ekv at set@key@,
+%     \ekv at set@key at relax,\ekv at set@key at undefined,
+%     \ekv at set@key at u,\ekv at set@key at u@relax,\ekv at set@key at no@u
+%   }
+% Analogous to |\ekv at set@pair|, |\ekv at set@key| builds the \Nkey-macro and
+% provides an error-branch. It'll test whether the key-macro is defined and if
+% so call it, else there might be some \expnotation, or errors are thrown.
+%    \begin{macrocode}
+\ekv at if@lastnamedcs
+  {%
+    \long\def\ekv at set@key#1\ekv at mark#2#3%
+      {%
+        \ifcsname#3{#1}N\endcsname\expandafter\ekv at set@key@\lastnamedcs\fi
+        \ekv at set@key at undefined{#1}{#2}%
+        \ekv at set@other#3%
+      }
+    \ekv at exparg{\long\def\ekv at set@key at undefined#1#2\ekv at set@other#3}%
+      {%
+        \ekv at ifexp{#2}%
+          \ekv at expansion@set at key
+          {%
+            \ifcsname#3{}uN\endcsname\expandafter\ekv at set@key at u\lastnamedcs\fi
+            \ekv at set@key at no@u{#1}{#2}%
+          }%
+        \ekv at set@other#3%
+      }
+  }
+  {%
+    \long\def\ekv at set@key#1\ekv at mark#2#3%
+      {%
+        \ifcsname#3{#1}N\endcsname
+          \expandafter\ekv at set@key@\csname#3{#1}N\endcsname
+        \fi
+        \ekv at set@key at undefined{#1}{#2}%
+        \ekv at set@other#3%
+      }
+    \ekv at exparg{\long\def\ekv at set@key at undefined#1#2\ekv at set@other#3}%
+      {%
+        \ekv at ifexp{#2}%
+          \ekv at expansion@set at key
+          {%
+            \ifcsname#3{}uN\endcsname
+              \expandafter\ekv at set@key at u\csname#3{}uN\endcsname
+            \fi
+            \ekv at set@key at no@u{#1}{#2}%
+          }%
+        \ekv at set@other#3%
+      }
+  }
+\long\def\ekv at set@key@#1\fi\ekv at set@key at undefined
+  {\fi\ifx#1\relax\ekv at set@key at relax\fi#1\ekv at set@next at other}
+\long\def\ekv at set@key at relax\fi#1\ekv at set@next at other{\fi\ekv at set@key at undefined}
+\long\def\ekv at set@key at u#1\fi\ekv at set@key at no@u
+  {\fi\ifx\relax#1\ekv at set@key at u@relax\fi#1}
+\def\ekv at set@key at u@relax\fi#1{\fi\ekv at set@key at no@u}
+\long\def\ekv at set@key at no@u#1#2\ekv at set@other#3%
+  {%
+    \ekv at ifdefined{#3{#1}}%
+      \ekv at err@reqval
+      \ekv at err@unknown
+        #3{#1}{#2}%
+    \ekv at set@other#3%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at expansion@set at key,\ekv at expansion@set at key@,
+%     \ekv at expansion@set at pair,\ekv at expansion@set at pair@
+%   }
+%   These macros just pick up the pieces of the \expansion\ prefix as separate
+%   arguments. The \val\ for the \expansion-rules is left empty. Once expansion
+%   is done we loop back to |\ekv at set@key|, that'll pick up the processed \key\
+%   and set it if it's now defined. The same trick is used for a \kv\ pair.
+%    \begin{macrocode}
+\long\def\ekv at expansion@set at key#1#2#3%
+  {%
+    \ekv at expansion@rule@{#2}#1\ekv at mark\ekv at stop{}{}\ekvmorekv
+    \ekv at expansion@set at key@
+  }
+\long\def\ekv at expansion@set at key@#1#2\ekv at set@other#3%
+  {\expandafter\ekv at set@key\detokenize{#2}\ekv at mark{#2}#3}
+\long\def\ekv at expansion@set at pair#1#2#3#4%
+  {%
+    \ekv at expansion@rule@{#1}#2\ekv at mark\ekv at stop{#3}{}\ekvmorekv
+    \ekv at expansion@set at pair@
+  }
+\long\def\ekv at expansion@set at pair@#1#2\ekv at set@other#3%
+  {\expandafter\ekv at set@pair\detokenize{#1}\ekv at mark{#1}\ekv at mark{#2}\ekv at nil#3}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at expansion@parse at key,\ekv at expansion@parse at key@,
+%     \ekv at expansion@parse at pair,\ekv at expansion@parse at pair@
+%   }
+%   In |\ekvparse| we don't need to resort to looping back into |\ekv at parse@key|
+%   or the like, we can simply leave the result via |\ekv at unexpanded|.
+%    \begin{macrocode}
+\long\def\ekv at expansion@parse at key#1#2#3#4%
+  {%
+    \ekv at expansion@rule@{#3}#2\ekv at mark\ekv at stop{}{}\ekv at parse@more
+    \ekv at expansion@parse at key@\@gobble{#1}%
+  }
+\long\def\ekv at expansion@parse at key@#1#2\@gobble#3{\ekv at unexpanded{#3{#2}}}
+\long\def\ekv at expansion@parse at pair#1#2#3#4#5%
+  {%
+    \ekv at expansion@rule@{#1}#3\ekv at mark\ekv at stop{#4}{}\ekv at parse@more
+    \ekv at expansion@parse at pair@\@gobble{#2}%
+  }
+\long\def\ekv at expansion@parse at pair@#1#2\@gobble#3{\ekv at unexpanded{#3{#1}{#2}}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvsetdef}
+%   Provide a macro to define a shorthand to use |\ekvset| on a specified \set.
+%   To gain the maximum speed |\ekvset| is expanded twice by
+%   |\ekv at exparg| so that during runtime the macro storing the set name
+%   is already built and one |\expandafter| doesn't have to be used.
+%    \begin{macrocode}
+\ekv at expargtwice{\protected\def\ekvsetdef#1#2}%
+  {%
+    \romannumeral
+    \ekv at exparg{\ekv at zero\ekv at exparg{\def#1##1}}%
+      {\ekvset{#2}{##1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvsetSneakeddef,\ekvsetdefSneaked}
+% And do the same for |\ekvsetSneaked| in the two possible ways, with a fixed
+% sneaked argument and with a flexible one.
+%    \begin{macrocode}
+\ekv at expargtwice{\protected\def\ekvsetSneakeddef#1#2}%
+  {%
+    \romannumeral
+    \ekv at exparg{\ekv at zero\ekv at exparg{\long\def#1##1##2}}%
+      {\ekvsetSneaked{#2}{##1}{##2}}%
+  }
+\ekv at expargtwice{\protected\def\ekvsetdefSneaked#1#2#3}%
+  {%
+    \romannumeral
+    \ekv at exparg{\ekv at zero\ekv at exparg{\long\def#1##1}}%
+      {\ekvsetSneaked{#2}{#3}{##1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at alignsafe,\ekv at endalignsafe}
+%   These macros protect the usage of ampersands inside of alignment contexts.
+%    \begin{macrocode}
+\begingroup
+\catcode`\^^@=2
+\@firstofone{\endgroup
+  \def\ekv at alignsafe{\romannumeral\iffalse{\fi`^^@ }
+}
+\def\ekv at endalignsafe{\ifnum`{=\ekv at zero}\fi}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvoptarg,\ekvoptargTF}
+% Provide macros to expandably collect an optional argument in brackets. The
+% macros here are pretty simple in nature compared to \pkg{xparse}'s
+% possibilities (they don't care for nested bracket levels).
+%
+% We start with a temporary definition to pre-expand |\ekv at alignsafe| (will be
+% |#1|) and |\ekv at endalignsafe| (will be |#2|). As |\ekv at alignsafe| starts with
+% a |\romannumeral| we use that to also control the number of steps needed
+% instead of adding another |\romannumeral|. For this we have to remove the
+% space token from the end of |\ekv at alignsafe|'s definition.
+%    \begin{macrocode}
+\begingroup
+\def\ekvoptarg#1#2{%
+\endgroup
+%    \end{macrocode}
+% The real definition starts an expansion context and afterwards grabs the
+% arguments. |#1| will be the next step, |#2| the default value, and |#3| might
+% be an opening bracket, or the mandatory argument. We check for the opening
+% bracket, if it is found grab the optional argument, else leave |#1{#2}| in the
+% input stream after ending the expansion context.
+%    \begin{macrocode}
+\def\ekvoptarg{#1\ekv at optarg@a}
+\long\def\ekv at optarg@a##1##2##3%
+  {%
+    \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optarg@b\ekv at mark[\ekv at mark
+    #2%
+    \@firstofone{ ##1}{##2}{##3}%
+  }%
+%    \end{macrocode}
+% The other variant of this will do roughly the same. Here, |#1| will be the
+% next step if an optional argument is found, |#2| the next step else, and |#3|
+% might be the opening bracket or mandatory argument.
+%    \begin{macrocode}
+\def\ekvoptargTF{#1\ekv at optargTF@a}
+\long\def\ekv at optargTF@a##1##2##3%
+  {%
+    \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optargTF@b{##1}\ekv at mark[\ekv at mark
+    #2%
+    \@firstofone{ ##2}{##3}%
+  }
+%    \end{macrocode}
+% The two macros to grab the optional argument have to remove the remainder of
+% the test and the wrong next step as well as grabbing the argument.
+%    \begin{macrocode}
+\long\def\ekv at optarg@b\ekv at mark[\ekv at mark\ifnum`##1\fi\@firstofone##2##3##4##5]%
+  {#2##2{##5}}
+\long\def\ekv at optargTF@b
+    ##1\ekv at mark[\ekv at mark\ifnum`##2\fi\@firstofone##3##4##5]%
+  {#2 ##1{##5}}
+}
+%    \end{macrocode}
+% Do the definitions and add the test macro. We use |\ekv at strip| to remove the
+% trailing space from the definition of |\ekv at alignsafe|.
+%    \begin{macrocode}
+\ekv at exparg
+  {%
+    \expandafter\ekv at strip\expandafter
+      {\expandafter\ekv at mark\ekv at alignsafe}%
+      \ekvoptarg
+  }%
+  \ekv at endalignsafe
+\long\def\ekv at optarg@if#1\ekv at mark[\ekv at mark{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at ifstar}
+%   Internal helper to get an expandable |ifstar| implementation. This is pretty
+%   straight forward.
+%    \begin{macrocode}
+\long\def\ekv at ifstar#1#2#3%
+  {%
+    \if*\string#3%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+      {#1}%
+      {#2{#3}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcompile}
+%   The idea of key-compilation is to preparse some list into a form that sets
+%   that list very fast (but is frozen), in our case this means we do everything
+%   except expanding the key's code. There are two levels of expansion possible,
+%   either expand until the key-macro or expand the key-macro once as well (the
+%   latter might break if the key-macros take additional arguments). The
+%   following supports both by using a starred form.
+%    \begin{macrocode}
+\protected\long\def\ekvcompile
+  {%
+    \ekv at alignsafe
+    \ekv at ifstar{\ekv at compile{}}{\ekv at compile{\expandafter\expandafter}}%
+  }
+%    \end{macrocode}
+% \begin{macro}[internal]
+%   {\ekv at compile,\ekv at compile@,\ekv at compile@key,\ekv at compile@pair}
+%   |\ekvparse| starts with an |\unexpanded| that we don't need. Hence we use a
+%   temporary definition to remove that. Else this is pretty straight forward.
+%   There is a minor indirection (the parsing step of |\ekv at compile|) which is
+%   necessary to grab any argument specification.
+%    \begin{macrocode}
+\def\ekv at compile#1#2#3#{\ekv at compile@{#1}{#2#3}}
+\def\ekv at compile@#1#2#3{#2#3}
+\ekv at exparg{\protected\long\def\ekv at compile@#1#2#3#4}%
+  {%
+    \expandafter\ekv at expanded\expandafter
+      {%
+        \romannumeral\ekv at expargtwice{\ekv at zero\def\ekv at unexpanded{#2}}%
+          {%
+            \expandafter\ekv at compile@
+            \ekvparse
+              {\ekv at compile@key{#1}{#3}}%
+              {\ekv at compile@pair{#1}{#3}}%
+              {#4}%
+          }%
+      }%
+    \ekv at endalignsafe
+  }
+%    \end{macrocode}
+%   The compilation step just checks whether the keys are defined and leaves
+%   their code (maybe expanded once).
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at compile@key#1#2#3}%
+  {%
+    \ekvifdefinedNoVal{#2}{#3}%
+      {\ekv at unexpanded#1\expandafter{\csname\ekv at name{#2}{#3}N\endcsname}}%
+      {%
+        \ekv at ifdefined{\ekv at name{#2}{}uN}
+          {%
+            \ekv at unexpanded#1\expandafter
+              {%
+                \csname\ekv at name{#2}{}uN\expandafter\endcsname
+                  \expandafter{\detokenize{#3}}{#3}%
+              }%
+          }%
+          {%
+            \ekvifdefined{#2}{#3}%
+              {\ekv at err{missing value for `#3' in set `#2'}}%
+              {\ekv at err{unknown key `#3' in set `#2'}}%
+          }%
+      }%
+  }
+\ekv at exparg{\long\def\ekv at compile@pair#1#2#3#4}%
+  {%
+    \ekvifdefined{#2}{#3}%
+      {\ekv at unexpanded#1\expandafter{\csname\ekv at name{#2}{#3}\endcsname{#4}}}%
+      {%
+        \ekv at ifdefined{\ekv at name{#2}{}u}%
+          {%
+            \ekv at unexpanded#1\expandafter
+              {%
+                \csname\ekv at name{#2}{}u\ekv at expanded{\endcsname
+                  {\ekv at unexpanded{#4}}{\detokenize{#3}}}{#3}%
+              }%
+          }%
+          {%
+            \ekvifdefinedNoVal{#2}{#3}%
+              {\ekv at err{unwanted value for `#3' in set `#2'}}%
+              {\ekv at err{unknown key `#3' in set `#2'}}%
+          }%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekverr}
+% \begin{macro}[internal]{\ekv at err@collect,\ekv at err@cleanup}
+% Since |\ekvset| is fully expandable as long as the code of the keys is (which
+% is unlikely) we want to somehow throw expandable errors, in our case via
+% a runaway argument (to my knowledge the first version of this method was
+% implemented by Jean-François Burnol, many thanks to him). The first step is to
+% ensure that the second argument (which might contain user input) doesn't
+% contain tokens we use as delimiters (in this case |\par|), this will be done
+% by the front facing macro |\ekverr|. But first we set some other things up.
+%
+% We use a temporary definition for |\ekverr| to get multiple consecutive
+% spaces. Then we set up the macro that will collect the error and the macro
+% that will throw the error. The latter will have an unreasonable long name.
+% This way we can convey more information. Though the information in the macro
+% name is static and has to be somewhat general to fit every occurence. The
+% important bit is that the long named macro has a delimited argument and is
+% short which will throw the error at the |\par| at the end of
+% |\ekv at err@collect|. This macro has the drawback that it will only print nicely
+% if the |\newlinechar| is |^^J|.
+%    \begin{macrocode}
+\def\ekv at err@cleanup\par{}
+\def\ekv at err@collect#1%
+  {%
+    \def\ekv at err@collect##1\par##2%
+      {%
+        \expandafter
+        \ekv at err@cleanup
+        #1! ##2 Error: ##1\par
+      }%
+    \def#1##1\thanks at jfbu{}%
+  }
+\def\ekverr{ }
+\expandafter\ekv at err@collect\csname <an-expandable-macro>^^J%
+  completed due to above exception. \ekverr If the error^^J%
+  summary is \ekverr not comprehensible \ekverr see the package^^J%
+  documentation.^^J%
+  I will try to recover now. \ekverr If you're in inter-^^J%
+  active mode hit <return> \ekverr at the ? prompt and I^^J%
+  continue hoping recovery\endcsname
+%    \end{macrocode}
+%    \begin{macrocode}
+\long\def\ekverr#1#2{\expandafter\ekv at err@collect\detokenize{#2}\par{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at err,\ekv at errm}
+% We define shorthands to throw errors in \expkv.
+%    \begin{macrocode}
+\ekv at exparg{\long\def\ekv at err#1}{\ekverr{expkv}{#1}}
+\protected\long\def\ekv at errm#1{\errmessage{expkv Error: #1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekv at err@common,\ekv at err@common@,
+%     \ekv at err@unknown,\ekv at err@noarg,\ekv at err@reqval,
+%     \ekv at err@undefined at expansion
+%   }
+% Now we can use |\ekv at err| to set up some error messages so that we can later
+% use those instead of the full strings.
+%    \begin{macrocode}
+\long\def\ekv at err@common #1#2{\expandafter\ekv at err@common@\string#2{#1}}
+\ekv at exparg{\long\def\ekv at err@common@#1`#2' #3.#4#5}%
+  {\ekv at err{#4 `#5' in set `#2'}}
+\ekv at exparg{\long\def\ekv at err@unknown#1#2}{\ekv at err@common{unknown key}{#1}}
+\ekv at exparg{\long\def\ekv at err@noarg#1#2}
+  {\ekv at err@common{unwanted value for}{#1}}
+\ekv at exparg{\long\def\ekv at err@reqval#1#2}%
+  {\ekv at err@common{missing value for}{#1}}
+\ekv at exparg{\long\def\ekv at err@redirect at kv@notfound#1#2#3\ekv at stop}%
+  {\ekv at err{no key `#2' in sets #3}}
+\ekv at exparg{\def\ekv at err@redirect at k@notfound#1#2\ekv at stop}%
+  {\ekv at err{no NoVal key `#1' in sets #2}}
+\ekv at exparg{\def\ekv at err@undefined at expansion#1\fi}%
+  {\expandafter\fi\ekv at err{Undefined expansion rule `#1'}}%
+\ekv at exparg{\def\ekv at err@erroneous at variable#1}%
+  {\ekv at err{Erroneous variable `#1' used}}
+\ekv at exparg{\def\ekv at err@key at no@reinsert}%
+  {\ekv at err{Reinsertion in \key expansion forbidden}}
+\ekv at exparg{\def\ekv at err@val at no@reinsert#1}%
+  {\ekv at err{Reinsertion with key `#1' forbidden}}
+%    \end{macrocode}
+% \end{macro}
+%
+% Now everything that's left is to reset the category code of |@|.
+%    \begin{macrocode}
+\catcode`\@=\ekv at tmp
+%    \end{macrocode}
+%
+% \gobbledocstriptag
+%</tex>
+%^^A=<<


Property changes on: trunk/Master/texmf-dist/source/latex/expkv-bundle/expkv.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-cs.tex
===================================================================
--- trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-cs.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-cs.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,59 @@
+%%
+%% This is file `t-expkv-cs.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-cs.dtx  (with options: `ctx')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\writestatus{loading}{ConTeXt User Module / expkv-cs}
+\usemodule[expkv-pop]
+\unprotect
+\input expkv-cs.tex
+\writestatus{loading}
+  {ConTeXt User Module / expkv-cs / Version \ekvcVersion\space loaded}
+\protect\endinput
+%% 
+%%
+%% End of file `t-expkv-cs.tex'.


Property changes on: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-cs.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-def.tex
===================================================================
--- trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-def.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-def.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,59 @@
+%%
+%% This is file `t-expkv-def.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-def.dtx  (with options: `ctx')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\writestatus{loading}{ConTeXt User Module / expkv-def}
+\usemodule[expkv-pop]
+\unprotect
+\input expkv-def.tex
+\writestatus{loading}
+  {ConTeXt User Module / expkv-def / Version \ekvdVersion\space loaded}
+\protect\endinput
+%% 
+%%
+%% End of file `t-expkv-def.tex'.


Property changes on: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-def.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-pop.tex
===================================================================
--- trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-pop.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-pop.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,59 @@
+%%
+%% This is file `t-expkv-pop.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-pop.dtx  (with options: `ctx')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\writestatus{loading}{ConTeXt User Module / expkv-pop}
+\usemodule[expkv]
+\unprotect
+\input expkv-pop.tex
+\writestatus{loading}
+  {ConTeXt User Module / expkv-pop / Version \ekvpVersion\space loaded}
+\protect\endinput
+%% 
+%%
+%% End of file `t-expkv-pop.tex'.


Property changes on: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv-pop.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv.tex
===================================================================
--- trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,60 @@
+%%
+%% This is file `t-expkv.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv.dtx  (with options: `ctx')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\writestatus{loading}{ConTeXt User Module / expkv}
+\unprotect
+\input expkv.tex
+\long\def\ekv at err@collect#1\par#2%
+  {\directlua{tex.error[[\detokenize{#2} Error: #1]]}}
+\writestatus{loading}
+  {ConTeXt User Module / expkv / Version \ekvVersion\space loaded}
+\protect\endinput
+%% 
+%%
+%% End of file `t-expkv.tex'.


Property changes on: trunk/Master/texmf-dist/tex/context/third/expkv-bundle/t-expkv.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-cs.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-cs.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-cs.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,1013 @@
+%%
+%% This is file `expkv-cs.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-cs.dtx  (with options: `tex')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\input expkv-pop
+\expandafter\ifx\csname ekvcVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+\def\ekvcVersion{1.3}
+\def\ekvcDate{2023-01-23}
+\csname ekvc at tmp\endcsname
+\expandafter\chardef\csname ekvc at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+\edef\ekvc at tripledots{\detokenize{...}}
+\newcount\ekvc at keycount
+\let\ekvc at long\ekv at empty
+\let\ekvc at any@long\ekv at empty
+\long\def\ekvc at ifdefined#1%
+  {%
+    \ifdefined#1%
+      \ifx\relax#1%
+        \ekv at fi@gobble
+      \fi
+      \@firstofone
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+\def\ekvc at ekvset@pre at expander#1%
+  {%
+    \expandafter\ekvc at ekvset@pre at expander@a\ekvset{#1}\ekvc at stop\ekvc at stop
+  }
+\def\ekvc at ekvset@pre at expander@a
+  {%
+    \expandafter\ekvc at ekvset@pre at expander@b
+  }
+\def\ekvc at ekvset@pre at expander@b#1\ekvc at stop#2\ekvc at stop
+  {%
+    \ekv at unexpanded\expandafter{\ekv at alignsafe}%
+    \ekv at unexpanded{#1}##1\ekv at unexpanded{#2}%
+    \ekv at unexpanded\expandafter{\ekv at endalignsafe}%
+  }
+\protected\long\def\ekvcSplitAndUse#1#2%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcSplitAndUse@#1{}{#2}}%
+  }
+\protected\long\def\ekvcSplitAndUse@#1#2#3%
+  {%
+    \edef\ekvc at set{\string#1}%
+    \ekvc at SetupSplitKeys{#3}%
+    \ekvc at helpers@needed
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded\expandafter
+              {\csname ekvc at split@\the\ekvc at keycount\endcsname}%
+            \ekv at unexpanded\expandafter{\ekvc at initials{}#2}%
+          }%
+      }%
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded{#2}%
+            \ekv at unexpanded\expandafter{\ekvc at initials}%
+          }%
+      }%
+  }
+\protected\long\def\ekvcSplitAndForward#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcSplitAndUse@#1{{#2}}{#3}}%
+  }
+\protected\long\def\ekvcSplit#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@secondoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {%
+        \expandafter
+        \ekvcSplitAndUse@\expandafter#1\csname ekvc@\string#1\endcsname{#2}%
+        \ifnum\ekvc at keycount<1
+          \ekvc at any@long\expandafter\def\csname ekvc@\string#1\endcsname{#3}%
+        \else
+          \ifnum\ekvc at keycount>9
+            \ekvc at err@toomany{#1}%
+            \let#1\ekvc at undefined
+          \else
+            \ekvcSplit at build@argspec
+            \ekvc at any@long\expandafter
+            \def\csname ekvc@\string#1\expandafter\endcsname\ekvc at tmp{#3}%
+          \fi
+        \fi
+      }%
+  }
+\protected\def\ekvcSplit at build@argspec
+  {%
+    \begingroup
+      \edef\ekvc at tmp
+        {\endgroup\def\ekv at unexpanded{\ekvc at tmp}{\ekvcSplit at build@argspec@{1}}}%
+    \ekvc at tmp
+  }
+\def\ekvcSplit at build@argspec@#1%
+  {%
+    \ifnum#1>\ekvc at keycount
+      \ekv at fi@gobble
+    \fi
+    \@firstofone
+      {%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@#1\endcsname####}#1%
+        \expandafter\ekvcSplit at build@argspec@\expandafter{\the\numexpr#1+1}%
+      }%
+  }
+\protected\long\def\ekvc at SetupSplitKeys
+  {%
+    \ekvc at keycount=\ekv at zero
+    \let\ekvc at any@long\ekv at empty
+    \let\ekvc at initials\ekv at empty
+    \ekvpParse at unsafe\ekvp@@p at ekvc@setup at splitkeys
+  }
+\ekvpNewParser{ekvc at setup@splitkeys}
+\ekvpDefType{ekvc at setup@splitkeys}{short}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupSplitKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefType{ekvc at setup@splitkeys}{long}
+  {%
+    \let\ekvc at long\long
+    \let\ekvc at any@long\long
+    \expandafter\ekvc at SetupSplitKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefNoType{ekvc at setup@splitkeys}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupSplitKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefNoValue{ekvc at setup@splitkeys}
+  {%
+    \begingroup
+      \edef\ekvc at tmp{\detokenize{#1}}%
+      \expandafter
+    \endgroup
+    \ifx\ekvc at tripledots\ekvc at tmp
+      \advance\ekvc at keycount1
+      \begingroup\expandafter\endgroup
+      \expandafter\ekvc at SetupSplitKeys@unknown
+        \csname ekvc at splitmark@\the\ekvc at keycount\endcsname
+      \let\ekvc at any@long\long
+    \else
+      \ekvc at err@value at required{#1}%
+    \fi
+  }
+\protected\long\def\ekvc at SetupSplitKeys@a
+  {%
+    \advance\ekvc at keycount1
+    \begingroup\expandafter\endgroup
+    \expandafter\ekvc at SetupSplitKeys@b
+      \csname ekvc at splitmark@\the\ekvc at keycount\endcsname
+  }
+\protected\long\def\ekvc at SetupSplitKeys@b#1#2\ekv at stop#3%
+  {%
+    \long\def\ekvc at tmp##1##2#1##3{##2#1{##1}}%
+    \ifx\ekvc at long\long
+    \else
+      \expandafter\let\csname ekvc@\ekvc at set(#2)\endcsname\ekvc at tmp
+      \edef\ekvc at tmp##1%
+        {%
+          \ekv at unexpanded\expandafter{\csname ekvc@\ekvc at set(#2)\endcsname}%
+          {##1}%
+        }%
+    \fi
+    \ekvlet\ekvc at set{#2}\ekvc at tmp
+    \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{#3}}}%
+    \ekvc at helpers@needed
+      {\expandafter\ekvc at setup@splitmacro\expandafter{\the\ekvc at keycount}}%
+      {}%
+  }
+\protected\long\def\ekvc at SetupSplitKeys@unknown#1%
+  {%
+    \long\def\ekvc at tmp##1##2##3##4#1##5{##4#1{##5, {##3} = {##1} }}%
+    \ekvletunknown\ekvc at set\ekvc at tmp
+    \long\def\ekvc at tmp##1##2##3#1##4{##3#1{##4, {##2} }}%
+    \ekvletunknownNoVal\ekvc at set\ekvc at tmp
+    \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{}}}%
+    \ekvc at helpers@needed
+      {\expandafter\ekvc at setup@splitmacro\expandafter{\the\ekvc at keycount}}%
+      {}%
+  }
+\protected\def\ekvc at defarggobbler#1{\def\ekvc at tmp##1#1##2##{##1#1}}
+\begingroup
+\edef\ekvc at tmp
+  {%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@1\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        ##2##3%
+      {##3{##1}##2}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@2\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        ##3##4%
+      {##4{##1}{##2}##3}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@3\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        ##4##5%
+      {##5{##1}{##2}{##3}##4}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@4\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        ##5##6%
+      {##6{##1}{##2}{##3}{##4}##5}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@5\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@5\endcsname}##5%
+        ##6##7%
+      {##7{##1}{##2}{##3}{##4}{##5}##6}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@6\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@5\endcsname}##5%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@6\endcsname}##6%
+        ##7##8%
+      {##8{##1}{##2}{##3}{##4}{##5}{##6}##7}%
+    \long\gdef\ekv at unexpanded\expandafter{\csname ekvc at split@7\endcsname}%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@1\endcsname}##1%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@2\endcsname}##2%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@3\endcsname}##3%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@4\endcsname}##4%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@5\endcsname}##5%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@6\endcsname}##6%
+        \ekv at unexpanded\expandafter{\csname ekvc at splitmark@7\endcsname}##7%
+        ##8##9%
+      {##9{##1}{##2}{##3}{##4}{##5}{##6}{##7}##8}%
+  }
+\ekvc at tmp
+\endgroup
+\protected\def\ekvc at setup@splitmacro#1%
+  {%
+    \ekv at ifdefined{ekvc at split@#1}{}%
+      {%
+        \begingroup
+          \def\ekvc at tmp##1%
+            {%
+              \ekv at unexpanded\expandafter
+                {\csname ekvc at splitmark@\the\numexpr#1-##1\relax\endcsname}%
+            }%
+          \edef\ekvc at tmp
+            {%
+              \long\gdef
+                \ekv at unexpanded\expandafter{\csname ekvc at split@#1\endcsname}%
+                  ####1%
+                  \ekvc at tmp{6}####2%
+                  \ekvc at tmp{5}####3%
+                  \ekvc at tmp{4}####4%
+                  \ekvc at tmp{3}####5%
+                  \ekvc at tmp{2}####6%
+                  \ekvc at tmp{1}####7%
+                  \ekvc at tmp{0}####8%
+                  ####9%
+                {%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at split@\the\numexpr#1-7\relax\endcsname}%
+                  ####1{{####2}{####3}{####4}{####5}{####6}{####7}{####8}####9}%
+                }%
+            }%
+          \ekvc at tmp
+        \endgroup
+      }%
+  }
+\protected\long\def\ekvcHashAndUse#1#2%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcHashAndUse@#1{}{#2}}%
+  }
+\protected\long\def\ekvcHashAndUse@#1#2#3%
+  {%
+    \edef\ekvc at set{\string#1}%
+    \ekvc at SetupHashKeys{#3}%
+    \ekvc at helpers@needed
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded{\ekvc at hash@pack at argument}%
+            \ekv at unexpanded\expandafter{\ekvc at initials\ekvc at stop#2}%
+          }%
+      }%
+      {%
+        \ekvc at any@long\edef#1##1%
+          {%
+            \expandafter\ekvc at ekvset@pre at expander\expandafter{\ekvc at set}%
+            \ekv at unexpanded{#2}%
+            \ekv at unexpanded\expandafter{\ekvc at initials\ekvc at stop}%
+          }%
+      }%
+  }
+\protected\long\def\ekvcHashAndForward#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@firstoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {\ekvcHashAndUse@#1{{#2}}{#3}}%
+  }
+\protected\long\def\ekvcHash#1#2#3%
+  {%
+    \let\ekvc at helpers@needed\@secondoftwo
+    \ekvc at ifdefined#1%
+      {\ekvc at err@already at defined#1}%
+      {%
+        \expandafter
+        \ekvcHashAndUse@\expandafter#1\csname ekvc@\string#1\endcsname{#2}%
+        \ekvc at any@long\expandafter\def\csname ekvc@\string#1\endcsname
+            ##1\ekvc at stop
+          {#3}%
+      }%
+  }
+\long\def\ekvc at hash@pack at argument#1\ekvc at stop#2{#2{#1}}
+\protected\long\def\ekvc at SetupHashKeys
+  {%
+    \let\ekvc at any@long\ekv at empty
+    \let\ekvc at initials\ekv at empty
+    \ekvpParse at unsafe\ekvp@@p at ekvc@setup at hashkeys
+  }
+\ekvpNewParser{ekvc at setup@hashkeys}
+\ekvpDefType{ekvc at setup@hashkeys}{short}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupHashKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefType{ekvc at setup@hashkeys}{long}
+  {%
+    \let\ekvc at long\long
+    \let\ekvc at any@long\long
+    \expandafter\ekvc at SetupHashKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefNoType{ekvc at setup@hashkeys}
+  {%
+    \let\ekvc at long\ekv at empty
+    \expandafter\ekvc at SetupHashKeys@a\detokenize{#1}\ekv at stop{#3}%
+  }
+\ekvpDefNoValue{ekvc at setup@hashkeys}
+  {%
+    \begingroup
+      \edef\ekvc at tmp{\detokenize{#1}}%
+      \expandafter
+    \endgroup
+    \ifx\ekvc at tripledots\ekvc at tmp
+      \ekvc at SetupHashKeys@unknown
+      \let\ekvc at any@long\long
+    \else
+      \ekvc at err@value at required{#1}%
+    \fi
+  }
+\protected\long\def\ekvc at SetupHashKeys@a#1\ekv at stop
+  {%
+    \begingroup\expandafter\endgroup
+    \expandafter\ekvc at SetupHashKeys@b\csname ekvc at hashmark@#1\endcsname{#1}%
+  }
+\protected\long\def\ekvc at SetupHashKeys@b#1#2#3%
+  {%
+    \long\def\ekvc at tmp##1##2#1##3{##2#1{##1}}%
+    \ifx\ekvc at long\long
+    \else
+      \expandafter\let\csname ekvc@\ekvc at set(#2)\endcsname\ekvc at tmp
+      \edef\ekvc at tmp##1%
+        {%
+          \ekv at unexpanded\expandafter{\csname ekvc@\ekvc at set(#2)\endcsname}%
+          {##1}%
+        }%
+    \fi
+    \ekvlet\ekvc at set{#2}\ekvc at tmp
+    \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{#3}}}%
+    \ekvc at setup@hashmacro{#2}%
+  }
+\def\ekvc at SetupHashKeys@unknown#1%
+  {%
+    \protected\def\ekvc at SetupHashKeys@unknown
+      {%
+        \ekvletunknown\ekvc at set\ekvc at hash@unknown at kv
+        \ekvletunknownNoVal\ekvc at set\ekvc at hash@unknown at k
+        \edef\ekvc at initials{\ekv at unexpanded\expandafter{\ekvc at initials#1{}}}%
+        \ekvc at setup@hashmacro{...}%
+      }%
+    \long\def\ekvc at hash@unknown at kv##1##2##3##4#1##5{##4#1{##5, {##3} = {##1} }}%
+    \long\def\ekvc at hash@unknown at k##1##2##3#1##4{##3#1{##4, {##2} }}%
+  }
+\begingroup\expandafter\endgroup
+\expandafter\ekvc at SetupHashKeys@unknown
+  \csname ekvc at hashmark@\ekvc at tripledots\endcsname
+\protected\def\ekvc at setup@hashmacro#1%
+  {%
+    \ekv at ifdefined{ekvc at fasthash@#1}{}%
+      {%
+        \begingroup
+          \edef\ekvc at tmp
+            {%
+              \long\gdef
+                \ekv at unexpanded\expandafter{\csname ekvc at fasthash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at stop}%
+                {####2}%
+              \long\gdef
+                \ekv at unexpanded\expandafter{\csname ekvc at safehash@#1\endcsname}%
+                  ####1%
+                {%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc@@safehash@#1\endcsname}%
+                  ####1\ekv at unexpanded{\ekvc at mark}{}%
+                  \ekv at unexpanded\expandafter
+                    {%
+                      \csname ekvc at hashmark@#1\endcsname{}%
+                      \ekvc at mark{\ekvc at err@missing at hash{#1}}\ekvc at stop
+                    }%
+                }%
+              \long\gdef
+                \ekv at unexpanded\expandafter
+                  {\csname ekvc@@safehash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at mark}####4####5%
+                  \ekv at unexpanded{\ekvc at stop}%
+                {%
+                  ####4{####2}%
+                }%
+              \long\gdef\ekv at unexpanded\expandafter
+                {\csname ekvc at fastsplithash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at stop}####4%
+                {%
+                  ####4{####2}%
+                }%
+              \long\gdef\ekv at unexpanded\expandafter
+                {\csname ekvc at safesplithash@#1\endcsname}####1%
+                {%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc@@safesplithash@#1\endcsname}%
+                  ####1\ekv at unexpanded{\ekvc at mark\ekvc at safe@after at hash}%
+                  \ekv at unexpanded\expandafter
+                    {%
+                      \csname ekvc at hashmark@#1\endcsname{}%
+                      \ekvc at mark
+                      {\ekvc at err@missing at hash{#1}\ekvc at safe@after at hash}%
+                      \ekvc at stop
+                    }%
+                }%
+              \long\gdef\ekv at unexpanded\expandafter
+                {\csname ekvc@@safesplithash@#1\endcsname}%
+                  ####1%
+                  \ekv at unexpanded\expandafter
+                    {\csname ekvc at hashmark@#1\endcsname}%
+                  ####2####3\ekv at unexpanded{\ekvc at mark}####4####5%
+                  \ekv at unexpanded{\ekvc at stop}%
+                {%
+                  ####4{####2}%
+                }%
+            }%
+          \ekvc at tmp
+        \endgroup
+      }%
+  }
+\long\def\ekvcValue#1%
+  {%
+    \ekv at unexpanded
+    \expandafter\ekvcValue@\detokenize{#1}\ekvc at stop
+  }
+\def\ekvcValue@#1\ekvc at stop
+  {%
+    \ekv at ifdefined{ekvc at safehash@#1}%
+      {\csname ekvc at safehash@#1\endcsname}%
+      {\ekvc at err@unknown at hash{#1}\@firstoftwo{{}}}%
+  }
+\long\def\ekvcValueFast#1#2%
+  {\csname ekvc at fasthash@\detokenize{#1}\endcsname#2\ekvc at stop}
+\long\def\ekvcValueSplit#1%
+  {\expandafter\ekvcValueSplit@\detokenize{#1}\ekvc at stop}
+\def\ekvcValueSplit@#1\ekvc at stop
+  {%
+    \ekv at ifdefined{ekvc at safesplithash@#1}%
+      {\csname ekvc at safesplithash@#1\endcsname}%
+      {\ekvc at err@unknown at hash{#1}\ekvcValueSplit at recover}%
+  }
+\long\def\ekvcValueSplit at recover#1#2{#2{}}
+\long\def\ekvc at safe@after at hash#1#2%
+  {%
+    #2{#1}%
+  }
+\long\def\ekvcValueSplitFast#1#2%
+  {\csname ekvc at fastsplithash@\detokenize{#1}\endcsname#2\ekvc at stop}
+\long\def\ekvc at safehash@#1{\ekvc at err@empty at hash{}}
+\long\def\ekvc at fasthash@#1\ekvc at stop{\ekvc at err@empty at hash}
+\long\def\ekvc at safesplithash@#1#2{\ekvc at err@empty at hash#2{}}
+\long\def\ekvc at fastsplithash@#1\ekvc at stop#2{\ekvc at err@empty at hash#2{}}
+\ekvpNewParser{ekvc at setup@secondary}
+\ekvpValueAlwaysRequired{ekvc at setup@secondary}
+\protected\long\def\ekvcSecondaryKeys#1%
+  {%
+    \edef\ekvc at set{\string#1}%
+    \let\ekvc at long\ekv at empty
+    \ekvpParse at unsafe\ekvp@@p at ekvc@setup at secondary
+  }
+\protected\long\def\ekvcChange#1%
+  {%
+    \ekvifdefinedset{\string#1}%
+      {%
+        \ekvc at ifdefined#1%
+          {\ekvc at change#1}%
+          {\ekvc at err@no at key@macro#1\@gobble}%
+      }%
+      {\ekvc at err@no at key@macro#1\@gobble}%
+  }
+\protected\def\ekvc at change#1%
+  {\expandafter\ekvc at change@a\meaning#1\ekv at stop#1}
+\def\ekvc at change@a#1%
+  {%
+    \protected\def\ekvc at change@a##1#1##2->##3\ekv at stop
+      {%
+        \ekvc at change@iflong{##1}%
+          {\ekvc at change@b{}}%
+          {\ekvc at change@b{\long}}%
+      }%
+  }
+\expandafter\ekvc at change@a\expandafter{\detokenize{macro:}}
+\protected\def\ekvc at change@b#1#2%
+  {\expandafter\ekvc at change@c\expandafter{#2\ekvc at stop}{#1}#2}
+\ekv at exparg{\protected\long\def\ekvc at change@c#1#2#3#4}%
+  {%
+    \expandafter\iffalse\expandafter{\expandafter{\expandafter\fi
+      \ekvset{\string#3}{#4}%
+      \ekvc at change@d{#2}{#3}%
+      #1%
+    }}%
+  }
+\protected\def\ekvc at change@d#1#2%
+  {#1\edef#2##1{\expandafter\ekvc at change@e\iffalse}\fi}
+\long\def\ekvc at change@e#1\ekvc at stop
+  {\ekv at unexpanded{#1}##1\ekv at unexpanded\expandafter{\iffalse}\fi}
+\def\ekvc at change@iflong#1%
+  {%
+    \protected\def\ekvc at change@iflong##1%
+      {\expandafter\ekv at ifempty\expandafter{\ekvc at change@iflong@##1#1}}%
+    \def\ekvc at change@iflong@##1#1{}
+  }
+\expandafter\ekvc at change@iflong\expandafter{\string\long}
+\long\def\ekvcPass#1#2%
+  {%
+    \ekvifdefined{\string#1}{#2}%
+      {\csname\ekv at name{\string#1}{#2}\endcsname}%
+      {\ekvc at err@unknown at key@or at macro{#1}{#2}\@gobble}%
+  }
+\ekvpDefPrefixLet{ekvc at setup@secondary}{long}\ekvc at long\long\ekv at empty
+\ekvpDefType{ekvc at setup@secondary}{meta}
+  {\ekvc at type@meta\ekv at exparg\ekvc at long{##1}\ekvlet{#1}{#3}}
+\ekvpDefType{ekvc at setup@secondary}{nmeta}
+  {\ekvc at assert@not at long\ekvc at type@meta\ekv at expargtwice{}{}\ekvletNoVal{#1}{#3}}
+\protected\long\def\ekvc at type@meta#1#2#3#4#5#6%
+  {%
+    #1\ekvc at type@meta@{\ekvmorekv{#6}}{#2}{#3}%
+    #4\ekvc at set{#5}\ekvc at tmp
+  }
+\protected\long\def\ekvc at type@meta@#1#2#3{#2\def\ekvc at tmp#3{#1}}
+\ekvpDefType{ekvc at setup@secondary}{alias}
+  {%
+    \ekvc at assert@not at long
+    \ekvc at assert@k at or@p at defined{#3}%
+    \ekvifdefined\ekvc at set{#3}{\ekvletkv\ekvc at set{#1}\ekvc at set{#3}}{}%
+    \ekvifdefinedNoVal\ekvc at set{#3}{\ekvletkvNoVal\ekvc at set{#1}\ekvc at set{#3}}{}%
+  }
+\ekvpDefType{ekvc at setup@secondary}{default}
+  {%
+    \ekvc at assert@defined{#1}%
+    \ekvc at assert@not at long
+    \edef\ekvc at tmp
+      {%
+        \ekv at unexpanded\expandafter
+          {\csname\ekv at name\ekvc at set{#1}\endcsname{#3}}%
+      }%
+    \ekvletNoVal\ekvc at set{#1}\ekvc at tmp
+  }
+\def\ekvc at enum@name#1#2#3{ekvc#1(#2)#3}
+\ekvpDefType{ekvc at setup@secondary}{enum}
+  {\ekvpAssertTwoValues{#3}\ekvc at type@enum\ekvc at type@enum@{#1}#3}
+\ekvpDefType{ekvc at setup@secondary}{choice}
+  {\ekvpAssertTwoValues{#3}\ekvc at type@enum\ekvc at type@choice@{#1}#3}
+\protected\long\def\ekvc at type@enum#1#2#3%
+  {%
+    \ekvc at assert@defined{#3}%
+    \ekvc at long\edef\ekvc at tmp##1%
+      {%
+        \ekv at unexpanded{\expandafter\ekvc at h@enum\detokenize}{##1}%
+        \ekv at unexpanded{\ekvc at stop}%
+        {\ekvc at set}{#2}%
+      }%
+    \ekvlet\ekvc at set{#2}\ekvc at tmp
+    \def\ekvc at tmp{0}%
+    \expandafter\ekvcsvloop\expandafter
+      {\expandafter#1\csname\ekv at name\ekvc at set{#3}\endcsname{#2}}%
+  }
+\ekv at exparg{\protected\long\def\ekvc at type@enum@#1#2#3}%
+  {%
+    \expandafter\expandafter\expandafter\edef\expandafter
+        \csname\ekvc at enum@name\ekvc at set{#2}{\detokenize{#3}}\endcsname
+      {\ekv at unexpanded{#1}{\ekvc at tmp}}%
+    \edef\ekvc at tmp{\the\numexpr\ekvc at tmp+1\relax}%
+  }
+\ekv at exparg{\protected\long\def\ekvc at type@choice@#1#2#3}%
+  {%
+    \expandafter\expandafter\expandafter\edef\expandafter
+        \csname\ekvc at enum@name\ekvc at set{#2}{\detokenize{#3}}\endcsname
+      {\ekv at unexpanded{#1{#3}}}%
+  }
+\ekv at if@lastnamedcs
+  {%
+    \ekv at exparg{\def\ekvc at h@enum#1\ekvc at stop#2#3}%
+      {%
+        \expandafter\ifcsname\ekvc at enum@name{#2}{#3}{#1}\endcsname
+          \expandafter\ekvc at h@enum@\lastnamedcs
+        \fi
+        \ekvc at err@unknown at enum{#2}{#3}{#1}%
+      }
+    \def\ekvc at h@enum@#1\fi\ekvc at err@unknown at enum#2#3#4%
+      {%
+        \fi
+        \ifx#1\relax
+          \ekvc at err@unknown at enum{#2}{#3}{#4}%
+          \expandafter\@gobble
+        \fi
+        #1%
+      }
+  }
+  {%
+    \def\ekvc at h@enum#1%
+      {%
+        \def\ekvc at h@enum##1\ekvc at stop##2##3%
+          {%
+            \expandafter\ekvc at h@enum@
+              \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
+              {##2}{##3}{##1}%
+          }%
+      }
+    \expandafter\ekvc at h@enum\expandafter{\ekvc at enum@name{#2}{#3}{#1}}
+    \def\ekvc at h@enum@#1#2#3#4%
+      {%
+        \ifx#1\relax
+          \ekvc at err@unknown at enum{#2}{#3}{#4}%
+          \expandafter\@gobble
+        \fi
+        #1%
+      }
+  }
+\let\ekvc at enum@name\ekvc at undefined
+\ekvpDefType{ekvc at setup@secondary}{aggregate}
+  {%
+    \let\ekvc at type@aggregate at ifexpanded\@secondoftwo
+    \ekvc at type@aggregate{#1}{#3}%
+  }
+\ekvpDefType{ekvc at setup@secondary}{e-aggregate}
+  {%
+    \let\ekvc at type@aggregate at ifexpanded\@firstoftwo
+    \ekvc at type@aggregate{#1}{#3}%
+  }
+\protected\long\def\ekvc at type@aggregate#1#2%
+  {%
+    \ekvc at assert@not at long
+    \ekvpAssertTwoValues{#2}%
+    \ekvc at type@aggregate at a
+      \ekvc at type@aggregate at long\ekvc at type@aggregate at short
+      {#1}#2%
+  }
+\protected\long\def\ekvc at type@aggregate at a#1#2#3#4#5%
+  {%
+    \ekvc at assert@defined{#4}%
+    \def\ekvc at type@aggregate at tmp##1##2{#5}%
+    \begingroup\expandafter\endgroup
+    \expandafter\ekvc at type@aggregate at b
+      \csname\ekv at name\ekvc at set{#4}\expandafter\endcsname
+      \csname ekvc@\ekvc at set(#4)\endcsname
+      #1#2%
+      {#3}%
+  }
+\protected\long\def\ekvc at type@aggregate at b#1#2#3#4%
+  {%
+    \ekvc at type@aggregate at check@long#1#2%
+      {#3#1}%
+      {#4#2}%
+  }
+\protected\long\def\ekvc at type@aggregate at check@long#1#2%
+  {\expandafter\ekvc at type@aggregate at check@long at a\detokenize{#2}\ekv at stop#1}
+\protected\long\def\ekvc at type@aggregate at check@long at a#1\ekv at stop#2%
+  {%
+    \def\ekvc at type@aggregate at check@long@@##1#1{}%
+    \expandafter\ekvc at type@aggregate at check@long at b\meaning#2\ekv at stop{#1}%
+  }
+\protected\def\ekvc at type@aggregate at check@long at b#1\ekv at stop#2%
+  {\expandafter\ekv at ifempty\expandafter{\ekvc at type@aggregate at check@long@@#1#2}}
+\protected\long\def\ekvc at type@aggregate at long#1%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@aggregate at long@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+  }
+\protected\long\def\ekvc at type@aggregate at long@#1#2#3%
+  {%
+    \ekvc at type@aggregate at ifexpanded
+      {%
+        \long\def\ekvc at type@aggregate at tmp##1##2#1##3%
+          {\ekv at expanded{\ekv at unexpanded{##2#1}{#2}}}%
+      }%
+      {\long\def\ekvc at type@aggregate at tmp##1##2#1##3{##2#1{#2}}}%
+    \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+  }
+\protected\long\def\ekvc at type@aggregate at short#1#2%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@aggregate at short@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+      {#2}%
+  }
+\protected\long\def\ekvc at type@aggregate at short@#1#2#3#4%
+  {%
+    \ekvdef\ekvc at set{#4}{#2{##1}}%
+    \ekvc at type@aggregate at ifexpanded
+      {\long\def#2##1##2#1##3{\ekv at expanded{\ekv at unexpanded{##2#1}{#3}}}}%
+      {\long\def#2##1##2#1##3{##2#1{#3}}}%
+  }
+\ekvpDefType{ekvc at setup@secondary}{process}
+  {%
+    \ekvpAssertTwoValues{#3}%
+    \ifx\ekvc at long\long
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+      {%
+        \ekvc at type@aggregate at a
+          \ekvc at type@process at long\ekvc at type@process at long
+      }%
+      {%
+        \ekvc at type@aggregate at a
+          \ekvc at type@process at short\ekvc at type@process at short
+      }%
+      {#1}#3%
+  }
+\protected\long\def\ekvc at type@process at long#1%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@process at long@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+  }
+\protected\long\def\ekvc at type@process at long@#1#2#3%
+  {%
+    \long\def\ekvc at type@aggregate at tmp##1##2#1##3{#2##2#1{##3}}%
+    \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+  }
+\protected\long\def\ekvc at type@process at short#1#2%
+  {%
+    \begingroup\expandafter\endgroup\expandafter
+    \ekvc at type@process at short@
+      \csname\ekvc at extract@mark#1\expandafter\endcsname
+      \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+      \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+      {#2}%
+  }
+\protected\long\def\ekvc at type@process at short@#1#2#3#4%
+  {%
+    \ekvdef\ekvc at set{#4}{#2{##1}}%
+    \long\def#2##1##2#1##3{#3##2#1{##3}}%
+  }
+\ekvpDefType{ekvc at setup@secondary}{flag-bool}
+  {%
+    \ekvc at assert@not at long
+    \ekvpAssertOneValue{#3}%
+    \ifdefined#3\else\ekvcFlagNew#3\fi
+    \ekvdef\ekvc at set{#1}%
+      {%
+        \ekv at ifdefined{ekvc at flag@set@##1}%
+          {%
+            \csname ekvc at flag@set@##1\expandafter\endcsname
+              \ekvcFlagHeight#3\ekv at stop#3%
+          }%
+          {\ekvc at err@invalid at bool{##1}}%
+      }%
+  }
+\protected\def\ekvc at type@flag#1#2#3%
+  {%
+    \ekvc at assert@not at long
+    \ekvpAssertOneValue{#3}%
+    \ifdefined#3\else\ekvcFlagNew#3\fi
+    \ekv at exparg{\ekvdefNoVal\ekvc at set{#2}}{#1#3}%
+  }
+\ekvpDefType{ekvc at setup@secondary}{flag-true}
+  {\ekvc at type@flag\ekvcFlagSetTrue{#1}{#3}}
+\ekvpDefType{ekvc at setup@secondary}{flag-false}
+  {\ekvc at type@flag\ekvcFlagSetFalse{#1}{#3}}
+\ekvpDefType{ekvc at setup@secondary}{flag-raise}
+  {\ekvc at type@flag\ekvcFlagRaise{#1}{#3}}
+\def\ekvc at flag@name{ekvcf\string}
+\def\ekvc at flag@namescheme#1#2{ekvch#2#1}
+\let\ekvcFlagHeight\number
+\protected\def\ekvcFlagNew#1%
+  {%
+    \edef#1%
+      {%
+        \ekv at unexpanded{\ekvc at flag@height}%
+          \ekv at unexpanded\expandafter{\csname\ekvc at flag@name#1\endcsname}%
+      }%
+    \ekv at expargtwice
+      {\expandafter\def\csname\ekvc at flag@name#1\endcsname##1}%
+      {\expandafter\ekvc at flag@namescheme\expandafter{\string#1}{##1}}%
+  }
+\def\ekvc at flag@height#1%
+  {%
+    \ifcsname#10\endcsname
+      \ekvc at flag@height at 1\ekv at stop#1%
+    \fi
+    \@firstofone{0} % leave this space
+  }
+\def\ekvc at flag@height@#1\ekv at stop#2\fi\@firstofone#3%
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      \expandafter\ekvc at flag@height@\the\numexpr#1+1\relax\ekv at stop#2%
+    \fi
+    \@firstofone{#1}%
+  }
+\ekv at exparg{\def\ekvcFlagRaise#1}%
+  {%
+    \expandafter\expandafter\expandafter\@gobble\expandafter
+      \csname\ekvc at flag@namescheme{\string#1}{\ekvcFlagHeight#1}\endcsname
+  }
+\def\ekvcFlagSetTrue#1%
+  {\expandafter\ekvc at flag@set at true\ekvcFlagHeight#1\ekv at stop#1}
+\def\ekvcFlagSetFalse#1%
+  {\expandafter\ekvc at flag@set at false\ekvcFlagHeight#1\ekv at stop#1}
+\def\ekvc at flag@set at true#1%
+  {%
+    \def\ekvc at flag@set at true##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@gobble
+        \fi
+        \@firstofone{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+    \def\ekvc at flag@set at false##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@firstofone
+        \fi
+        \@gobble{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+  }
+\expandafter\ekvc at flag@set at true\expandafter
+  {\ekvc at flag@namescheme{\string#2}{#1}}
+\def\ekvcFlagIf#1%
+  {%
+    \ifodd#1%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+\ekv at exparg{\def\ekvcFlagIfRaised#1}%
+  {%
+    \expandafter\ifcsname\ekvc at flag@namescheme{\string#1}0\endcsname
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+\protected\def\ekvcFlagReset#1%
+  {\expandafter\ekvc at flag@reset\csname\ekvc at flag@name#1\endcsname{}}
+\protected\def\ekvcFlagResetGlobal#1%
+  {\expandafter\ekvc at flag@reset\csname\ekvc at flag@name#1\endcsname\global}
+\protected\def\ekvc at flag@reset#1#2%
+  {%
+    \ifcsname#10\endcsname
+      #2\expandafter\let\csname#10\endcsname\ekvc at undefined
+      \ekvc at flag@reset at 1\ekv at stop#1{#2}%
+    \fi
+  }
+\protected\def\ekvc at flag@reset@#1\ekv at stop#2#3\fi
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      #3\expandafter\let\csname#2{#1}\endcsname\ekvc at undefined
+      \expandafter\ekvc at flag@reset@\the\numexpr#1+1\relax\ekv at stop#2{#3}%
+    \fi
+  }
+\def\ekvcFlagGetHeight#1%
+  {\expandafter\ekvc at flag@get at height@single\ekvcFlagHeight#1\ekv at stop}
+\long\def\ekvc at flag@get at height@single#1\ekv at stop#2{#2{#1}}
+\def\ekvcFlagGetHeights#1%
+  {%
+    \ekvc at flag@get at heights#1\ekv at stop{}%
+  }
+\def\ekvc at flag@get at heights#1%
+  {%
+    \ekv at gobbleto@stop#1\ekvc at flag@get at heights@done\ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight#1\ekv at stop
+  }
+\def\ekvc at flag@get at heights@#1\ekv at stop#2\ekv at stop#3%
+  {\ekvc at flag@get at heights#2\ekv at stop{#3{#1}}}
+\long\def\ekvc at flag@get at heights@done
+    \ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight\ekv at stop\ekv at stop#1#2%
+  {#2{#1}}
+\def\ekvc at extract@mark#1{\expandafter\ekvc at extract@mark@\meaning#1\ekv at stop}
+\begingroup
+\lccode`;=`#
+\lccode`/=`\\
+\lowercase{\endgroup
+\def\ekvc at extract@mark@#1:#2/#3 ;#4\ekv at stop{#3}%
+}
+\ekv at exparg{\def\ekvc at assert@not at long}%
+  {\ekvpAssertIfNot{\ifx\ekvc at long\long}{`long' not accepted}}
+\long\def\ekvc at assert@defined#1%
+  {\ekvpAssertTF{\ekvifdefined\ekvc at set{#1}}{undefined key `#1'}}
+\long\def\ekvc at assert@k at or@p at defined#1%
+  {%
+    \ekvpAssertTF
+      {\ekvifdefined\ekvc at set{#1}\@firstoftwo{\ekvifdefinedNoVal\ekvc at set{#1}}}%
+      {undefined key `#1'}%
+  }
+\protected\long\def\ekvc at errm#1{\errmessage{expkv-cs Error: #1}}
+\protected\long\def\ekvc at err@toomany#1%
+  {\ekvc at errm{Too many keys for macro `\string#1'}}
+\protected\long\def\ekvc at err@value at required#1%
+  {\ekvc at errm{Missing value for key `\ekv at unexpanded{#1}'}}
+\protected\long\def\ekvc at err@already at defined#1%
+  {\ekvc at errm{Macro `\string#1' already defined}}
+\protected\long\def\ekvc at err@no at key@macro#1%
+  {\ekvc at errm{\string#1 is no key=val macro}}
+\ekv at exparg{\long\def\ekvc at err#1}{\ekverr{expkv-cs}{#1}}
+\long\def\ekvc at err@unknown at hash#1{\ekvc at err{unknown hash `#1'}}
+\long\def\ekvc at err@missing at hash#1{\ekvc at err{hash `#1' not found}}
+\long\def\ekvc at err@empty at hash{\ekvc at err{empty hash}}
+\def\ekvc at err@invalid at bool#1{\ekvc at err{invalid boolean value `#1'}}
+\long\def\ekvc at err@unknown at key@or at macro#1#2%
+  {\ekvc at err{unknown key `#2' for #1}}
+\def\ekvc at err@unknown at enum#1#2#3%
+  {\ekvc at err{unknown choice `#3' for `#2' in #1}}
+\catcode`\@=\ekvc at tmp
+%% 
+%%
+%% End of file `expkv-cs.tex'.


Property changes on: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-cs.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-def.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-def.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-def.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,867 @@
+%%
+%% This is file `expkv-def.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-def.dtx  (with options: `tex')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\input expkv-pop
+\expandafter\ifx\csname ekvdVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+\def\ekvdVersion{1.0}
+\def\ekvdDate{2023-01-23}
+\csname ekvd at tmp\endcsname
+\expandafter\chardef\csname ekvd at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+\protected\long\def\ekvd at ifprimitive#1%
+  {%
+    \begingroup
+      \edef\ekvd at tmpa{\string #1}%
+      \edef\ekvd at tmpb{\meaning#1}%
+      \expandafter
+    \endgroup
+    \ifx\ekvd at tmpa\ekvd at tmpb
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+\protected\def\ekvd at clear@prefixes
+  {%
+    \let\ekvd at long\ekv at empty
+    \let\ekvd at prot\ekv at empty
+    \let\ekvd at ifalso\@secondoftwo
+    \let\ekvd at do@new\@gobbletwo
+  }
+\ekvd at clear@prefixes
+\ekvpNewParser{ekvd at definekeys}
+\ekvpDefNoValuePrefix{ekvd at definekeys}
+  {\let\ekvd at ifnoarg\@firstoftwo}
+  {\let\ekvd at ifnoarg\@secondoftwo}
+\ekvpDefPrefixLet{ekvd at definekeys}{long}     \ekvd at long\long     \ekv at empty
+\ekvpDefPrefixLet{ekvd at definekeys}{protected}\ekvd at prot\protected\ekv at empty
+\ekvpDefPrefixLet{ekvd at definekeys}{protect}  \ekvd at prot\protected\ekv at empty
+\ekvpDefPrefixLet{ekvd at definekeys}{also}\ekvd at ifalso\@firstoftwo\@secondoftwo
+\ekvpDefPrefixLet{ekvd at definekeys}{new}\ekvd at do@new\ekvd at assert@new\@gobbletwo
+\ekvpDefAutoPrefix{ekvd at definekeys}{\edef\ekvd at cur{\detokenize{#3}}}{}
+\protected\edef\ekvdefinekeys#1%
+  {%
+    \ekv at unexpanded{\def\ekvd at set}{#1}%
+    \ekv at unexpanded{\ekvpParse at unsafe@auto\ekvp@@p at ekvd@definekeys}%
+    \ekv at unexpanded\expandafter{\csname\ekvp@@p at ekvd@definekeys{ppa}\endcsname}%
+  }
+\protected\def\ekvd at def@type#1#2%
+  {%
+    \ekv at exparg{\ekvpDefType{ekvd at definekeys}{#1}}
+      {%
+        \expandafter\expandafter\csname ekvd at th@#1\endcsname
+          \detokenize{##1}\ekv at stop{##2}{##3}%
+      }%
+    \long\expandafter\def\csname ekvd at th@#1\endcsname##1\ekv at stop##2##3{#2}%
+  }
+\protected\long\def\ekvd at def@type at fwd#1#2%
+  {\ekvpDefType{ekvd at definekeys}{#1}{\ekv at exparg{#2}{\detokenize{##1}}{##3}}}
+\ekvd at def@type{set}
+  {\ekvd at ifnoarg{\ekvd at type@set{#1}{#1}}{\ekvd at type@set{#1}{#3}}}
+\protected\def\ekvd at type@set#1#2%
+  {%
+    \ekvd at assert@not at long
+    \ekvd at assert@not at protected
+    \ekvd at do@new{NoVal}{#1}%
+    \ekv at ifempty{#2}%
+      {\ekvd at err@missing at definition}%
+      {%
+        \ekvd at ifalso
+          {%
+            \ekv at expargtwice{\ekvd at add@noval{#1}}%
+              {\ekvchangeset{#2}}%
+              \ekvd at assert@not at protected@also
+          }%
+          {\ekv at expargtwice{\ekvdefNoVal\ekvd at set{#1}}{\ekvchangeset{#2}}}%
+      }%
+  }
+\ekvd at def@type at fwd{noval}{\ekvd at type@noval\def}
+\ekvd at def@type at fwd{enoval}{\ekvd at type@noval\edef}
+\protected\long\def\ekvd at type@noval#1#2#3%
+  {%
+    \ekvd at do@new{NoVal}{#2}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at long
+    \ekvd at prot#1\ekvd at tmp{#3}%
+    \ekvd at ifalso
+      {\ekv at exparg{\ekvd at add@noval{#2}}\ekvd at tmp{}}%
+      {\ekvletNoVal\ekvd at set{#2}\ekvd at tmp}%
+  }
+\ekvd at def@type at fwd{code}{\ekvd at type@code\def}
+\ekvd at def@type at fwd{ecode}{\ekvd at type@code\edef}
+\protected\long\def\ekvd at type@code#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@arg
+    \ekvd at prot\ekvd at long#1\ekvd at tmp##1{#3}%
+    \ekvd at ifalso
+      {\ekv at exparg{\ekvd at add@val{#2}}{\ekvd at tmp{##1}}{}}%
+      {\ekvlet\ekvd at set{#2}\ekvd at tmp}%
+  }
+\ekvd at def@type at fwd{default}{\ekvd at type@default{\ekv at unexpanded\expandafter}{}}
+\ekvd at def@type at fwd{odefault}
+  {\ekvd at type@default{\ekv at unexpanded\expandafter\expandafter\expandafter}{}}
+\ekvpLet{ekvd at definekeys}{type}{qdefault}{odefault}
+\ekvd at def@type at fwd{fdefault}
+  {\ekvd at type@default{\ekv at unexpanded\expandafter}{\romannumeral`\^^@}}
+\protected\long\def\ekvd at type@default#1#2#3#4%
+  {%
+    \ekvd at assert@arg
+    \ekvd at do@new{NoVal}{#3}%
+    \ekvd at assert@not at long
+    \ekvifdefined\ekvd at set{#3}%
+      {%
+        \ekvd at prot\edef\ekvd at tmp
+          {#1{#2\csname\ekv at name\ekvd at set{#3}\endcsname{#4}}}%
+        \ekvd at ifalso
+          {\ekv at exparg{\ekvd at add@noval{#3}}\ekvd at tmp{}}%
+          {\ekvletNoVal\ekvd at set{#3}\ekvd at tmp}%
+      }%
+      {\ekvd at err@undefined at key{#3}}%
+  }
+\ekvd at def@type{edefault}
+  {%
+    \ekvd at assert@arg
+    \ekvd at do@new{NoVal}{#1}%
+    \ekvd at assert@not at long
+    \ekvifdefined\ekvd at set{#1}%
+      {%
+        \ekvd at prot\edef\ekvd at tmp
+          {%
+            \ekv at unexpanded\ekv at expanded
+              {{\csname\ekv at name\ekvd at set{#1}\endcsname{#3}}}%
+          }%
+        \ekvd at ifalso
+          {\ekv at exparg{\ekvd at add@noval{#1}}\ekvd at tmp{}}%
+          {\ekvletNoVal\ekvd at set{#1}\ekvd at tmp}%
+      }%
+      {\ekvd at err@undefined at key{#1}}%
+  }
+\ekvd at def@type at fwd{initial}{\ekvd at type@initial\@firstofone}
+\ekvd at def@type at fwd{oinitial}{\ekvd at type@initial\ekv at exparg}
+\ekvd at def@type at fwd{einitial}{\ekvd at type@initial\ekv at expandedarg}
+\ekvd at def@type at fwd{finitial}{\ekvd at type@initial\ekv at fexparg}
+\long\def\ekvd at type@initial#1#2#3%
+  {%
+    \ekvd at assert@not at new
+    \ekvd at assert@not at also
+    \ekvd at assert@not at long
+    \ekvd at assert@not at protected
+    \ekvd at ifnoarg
+      {%
+        \ekvifdefinedNoVal\ekvd at set{#2}%
+          {\csname\ekv at name\ekvd at set{#2}N\endcsname}%
+          {\ekvd at err@undefined at noval{#2}}%
+      }%
+      {%
+        \ekvifdefined\ekvd at set{#2}%
+          {#1{\csname\ekv at name\ekvd at set{#2}\endcsname}{#3}}%
+          {\ekvd at err@undefined at key{#2}}%
+      }%
+  }
+\ekvd at def@type at fwd{bool}{\ekvd at type@bool{}\iftrue\iffalse}
+\ekvd at def@type at fwd{gbool}{\ekvd at type@bool\global\iftrue\iffalse}
+\ekvd at def@type at fwd{boolTF}{\ekvd at type@bool{}\@firstoftwo\@secondoftwo}
+\ekvd at def@type at fwd{gboolTF}{\ekvd at type@bool\global\@firstoftwo\@secondoftwo}
+\ekvd at def@type at fwd{invbool}{\ekvd at type@bool{}\iffalse\iftrue}
+\ekvd at def@type at fwd{ginvbool}{\ekvd at type@bool\global\iffalse\iftrue}
+\ekvd at def@type at fwd{invboolTF}{\ekvd at type@bool{}\@secondoftwo\@firstoftwo}
+\ekvd at def@type at fwd{ginvboolTF}{\ekvd at type@bool\global\@secondoftwo\@firstoftwo}
+\protected\def\ekvd at type@bool#1#2#3#4#5%
+  {%
+    \ekvd at do@new{}{#4}%
+    \ekvd at do@new{NoVal}{#4}%
+    \ekvd at assert@filledarg{#5}%
+    \ekvd at newlet#5#3%
+    \ekvd at type@choice{#4}%
+    \protected\ekvdefNoVal\ekvd at set{#4}{#1\let#5#2}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{true}\endcsname
+      {#1\let#5#2}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{false}\endcsname
+      {#1\let#5#3}%
+  }
+\ekvd at def@type{boolpair}
+  {\ekvd at assert@twoargs{#3}\ekvd at type@boolpair{}\iftrue\iffalse{#1}#3}
+\ekvd at def@type{gboolpair}
+  {\ekvd at assert@twoargs{#3}\ekvd at type@boolpair\global\iftrue\iffalse{#1}#3}
+\ekvd at def@type{boolpairTF}
+  {\ekvd at assert@twoargs{#3}\ekvd at type@boolpair{}\@firstoftwo\@secondoftwo{#1}#3}
+\ekvd at def@type{gboolpairTF}
+  {%
+    \ekvd at assert@twoargs{#3}%
+    \ekvd at type@boolpair\global\@firstoftwo\@secondoftwo{#1}#3%
+  }
+\protected\def\ekvd at type@boolpair#1#2#3#4#5#6%
+  {%
+    \ekvd at do@new{}{#4}%
+    \ekvd at do@new{NoVal}{#4}%
+    \ekvd at newlet#5#3%
+    \ekvd at newlet#6#2%
+    \ekvd at type@choice{#4}%
+    \protected\ekvdefNoVal\ekvd at set{#4}{#1\let#5#2#1\let#6#3}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{true}\endcsname
+      {#1\let#5#2#1\let#6#3}%
+    \protected\expandafter\def
+      \csname\ekvd at choice@name\ekvd at set{#4}{false}\endcsname
+      {#1\let#5#3#1\let#6#2}%
+  }
+\ekvd at def@type at fwd{data}
+  {\ekvd at type@data\@secondoftwo\edef{####2}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{edata}
+  {%
+    \ekvd at type@data\@secondoftwo\edef
+      {####2}{\ekv at unexpanded\ekv at expanded{{##1}}}%
+  }
+\ekvd at def@type at fwd{gdata}
+  {\ekvd at type@data\@secondoftwo\xdef{####2}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{xdata}
+  {%
+    \ekvd at type@data\@secondoftwo\xdef
+      {####2}{\ekv at unexpanded\ekv at expanded{{##1}}}%
+  }
+\ekvd at def@type at fwd{dataT}{\ekvd at type@data\@gobble\edef{}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{edataT}
+  {\ekvd at type@data\@gobble\edef{}{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\ekvd at def@type at fwd{gdataT}{\ekvd at type@data\@gobble\xdef{}{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{xdataT}
+  {\ekvd at type@data\@gobble\xdef{}{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\protected\def\ekvd at type@data#1#2#3#4#5#6%
+  {%
+    \ekvd at do@new{}{#5}%
+    \ekvd at assert@filledarg{#6}%
+    \ekvd at newlet#6#1%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#5}{\long#2#6####1#3{####1{#4}}}{}%
+      }%
+      {%
+        \protected\ekvd at long\ekvdef\ekvd at set{#5}%
+          {\long#2#6####1#3{####1{#4}}}%
+      }%
+  }
+\ekvd at def@type at fwd{box}{\ekvd at type@box{}}
+\ekvd at def@type at fwd{gbox}{\ekvd at type@box\global}
+\protected\def\ekvd at type@box#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@filledarg{#3}%
+    \ekvd at newreg#3{box}%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#2}{#1\setbox#3=\hbox{\begingroup##1\endgroup}}{}%
+      }%
+      {%
+        \protected\ekvd at long\ekvdef\ekvd at set{#2}%
+          {#1\setbox#3=\hbox{\begingroup##1\endgroup}}%
+      }%
+  }
+\ekvd at def@type at fwd{toks}{\ekvd at type@toks{}}
+\ekvd at def@type at fwd{gtoks}{\ekvd at type@toks\global}
+\protected\def\ekvd at type@toks#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@filledarg{#3}%
+    \ekvd at newreg#3{toks}%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#2}{#1#3={##1}}{}%
+      }%
+      {\protected\ekvd at long\ekvdef\ekvd at set{#2}{#1#3={##1}}}%
+  }
+\ekvd at ifprimitive\toksapp
+  {%
+    \ekvd at def@type at fwd{apptoks}{\ekvd at type@preapptoks\toksapp}
+    \ekvd at def@type at fwd{gapptoks}{\ekvd at type@preapptoks\gtoksapp}
+    \ekvd at def@type at fwd{pretoks}{\ekvd at type@preapptoks\tokspre}
+    \ekvd at def@type at fwd{gpretoks}{\ekvd at type@preapptoks\gtokspre}
+    \protected\def\ekvd at type@preapptoks#1#2#3%
+      {%
+        \ekvd at do@new{}{#2}%
+        \ekvd at assert@filledarg{#3}%
+        \ekvd at newreg#3{toks}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#2}{#1#3{##1}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#2}{#1#3{##1}}}%
+      }
+  }
+  {%
+    \ekvd at def@type at fwd{apptoks}{\ekvd at type@apptoks{}}
+    \ekvd at def@type at fwd{gapptoks}{\ekvd at type@apptoks\global}
+    \protected\def\ekvd at type@apptoks#1#2#3%
+      {%
+        \ekvd at do@new{}{#2}%
+        \ekvd at assert@filledarg{#3}%
+        \ekvd at newreg#3{toks}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#2}{#1#3=\expandafter{\the#3##1}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#2}%
+              {#1#3=\expandafter{\the#3##1}}%
+          }%
+      }
+    \ekvd at def@type at fwd{pretoks}{\ekvd at type@pretoks{}}
+    \ekvd at def@type at fwd{gpretoks}{\ekvd at type@pretoks\global}
+    \newtoks\ekvd at toks
+    \protected\def\ekvd at type@pretoks#1#2#3%
+      {%
+        \ekvd at do@new{}{#2}%
+        \ekvd at assert@filledarg{#3}%
+        \ekvd at newreg#3{toks}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#2}%
+              {#1#3=\ekv at expanded{{\ekv at unexpanded{##1}\the#3}}}%
+              {}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#2}%
+              {#1#3=\ekv at expanded{{\ekv at unexpanded{##1}\the#3}}}%
+          }%
+      }
+  }
+\ekvd at def@type at fwd {int}{\ekvd at type@register{count}{}{}}
+\ekvd at def@type at fwd{eint}{\ekvd at type@register{count}{}\numexpr}
+\ekvd at def@type at fwd{gint}{\ekvd at type@register{count}\global{}}
+\ekvd at def@type at fwd{xint}{\ekvd at type@register{count}\global\numexpr}
+\ekvd at def@type at fwd {dimen}{\ekvd at type@register{dimen}{}{}}
+\ekvd at def@type at fwd{edimen}{\ekvd at type@register{dimen}{}\dimexpr}
+\ekvd at def@type at fwd{gdimen}{\ekvd at type@register{dimen}\global{}}
+\ekvd at def@type at fwd{xdimen}{\ekvd at type@register{dimen}\global\dimexpr}
+\ekvd at def@type at fwd {skip}{\ekvd at type@register{skip}{}{}}
+\ekvd at def@type at fwd{eskip}{\ekvd at type@register{skip}{}\glueexpr}
+\ekvd at def@type at fwd{gskip}{\ekvd at type@register{skip}\global{}}
+\ekvd at def@type at fwd{xskip}{\ekvd at type@register{skip}\global\glueexpr}
+\protected\def\ekvd at type@register#1#2#3#4#5%
+  {%
+    \ekvd at do@new{}{#4}%
+    \ekvd at assert@filledarg{#5}%
+    \ekvd at newreg#5{#1}%
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#4}{#2#5=#3##1\relax}{}%
+      }%
+      {\protected\ekvd at long\ekvdef\ekvd at set{#4}{#2#5=#3##1\relax}}%
+  }
+\ekvd at def@type at fwd{store}{\ekvd at type@store\edef{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{gstore}{\ekvd at type@store\xdef{\ekv at unexpanded{##1}}}
+\ekvd at def@type at fwd{estore}
+  {\ekvd at type@store\edef{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\ekvd at def@type at fwd{xstore}
+  {\ekvd at type@store\xdef{\ekv at unexpanded\ekv at expanded{{##1}}}}
+\protected\def\ekvd at type@store#1#2#3#4%
+  {%
+    \ekvd at do@new{}{#3}%
+    \ekvd at assert@filledarg{#4}%
+    \ekvd at newlet#4\ekv at empty
+    \ekvd at ifalso
+      {%
+        \let\ekvd at prot\protected
+        \ekvd at add@val{#3}{#1#4{#2}}{}%
+      }%
+      {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#1#4{#2}}}%
+  }
+\ekvd at def@type at fwd{meta}
+  {\ekvd at type@meta{}{##1}\ekvd at add@val{{##1}}{}\ekv at exparg}
+\ekvd at def@type at fwd{nmeta}
+  {%
+    \ekvd at assert@not at long
+    \ekvd at type@meta
+      {NoVal}{}\ekvd at add@noval{}\ekvd at assert@not at long@also\ekv at expargtwice
+  }
+\protected\long\def\ekvd at type@meta#1#2#3#4#5#6#7#8%
+  {%
+    \ekvd at do@new{#1}{#7}%
+    \ekvd at assert@filledarg{#8}%
+    #6{\ekvd at prot\ekvd at long\def\ekvd at tmp#2}{\ekvmorekv{#8}}%
+    \ekvd at ifalso
+      {\ekv at exparg{#3{#7}}{\ekvd at tmp#4}{#5}}%
+      {\csname ekvlet#1\endcsname\ekvd at set{#7}\ekvd at tmp}%
+  }
+\ekvd at def@type at fwd{smeta}{\ekvd at type@smeta{}{##1}\ekvd at add@val{{##1}}{}}
+\ekvd at def@type at fwd{snmeta}
+  {%
+    \ekvd at assert@not at long
+    \ekvd at type@smeta{NoVal}{}\ekvd at add@noval{}\ekvd at assert@not at long@also
+  }
+\protected\long\def\ekvd at type@smeta#1#2#3#4#5#6#7%
+  {%
+    \ekvd at do@new{#1}{#6}%
+    \ekvd at assert@twoargs{#7}%
+    \ekvd at type@smeta@#7{#2}%
+    \ekvd at ifalso
+      {\ekv at exparg{#3{#6}}{\ekvd at tmp#4}{#5}}%
+      {\csname ekvlet#1\endcsname\ekvd at set{#6}\ekvd at tmp}%
+  }
+\protected\long\def\ekvd at type@smeta@#1#2#3%
+  {\ekvd at prot\ekvd at long\ekv at expargtwice{\def\ekvd at tmp#3}{\ekvset{#1}{#2}}}
+\protected\def\ekvd at type@choice#1%
+  {%
+    \ekvd at assert@not at long
+    \ekv at expargtwice{\ekvd at prot\def\ekvd at tmp##1}%
+      {%
+        \expandafter\expandafter\expandafter
+        \ekvd at h@choice
+        \expandafter\expandafter\expandafter
+          {\expandafter\ekvd at choice@name\expandafter{\ekvd at set}{#1}{##1}}%
+      }%
+    \ekvd at ifalso
+      {%
+        \ekvd at assert@val{#1}%
+        \ekvd at if@not at already@choice{#1}%
+          {%
+            \ekv at exparg
+              {%
+                \expandafter\ekvd at add@aux
+                  \csname\ekv at name\ekvd at set{#1}\endcsname{{##1}}{#1}%
+              }%
+              {\ekvd at tmp{##1}}%
+              {\ekvd at long\ekvdef}\ekvd at assert@not at long@also
+          }%
+      }%
+      {\ekvlet\ekvd at set{#1}\ekvd at tmp}%
+  }
+\ekvpNewParser{ekvd at populate@choice}
+\ekvpValueAlwaysRequired{ekvd at populate@choice}
+\ekvpDefType{ekvd at populate@choice}{protect}
+  {\ekvd at populate@choice\protected{#1}{#3}}
+\ekvpDefType{ekvd at populate@choice}{unprotect}{\ekvd at populate@choice{}{#1}{#3}}
+\ekvpDefNoType{ekvd at populate@choice}         {\ekvd at populate@choice{}{#1}{#3}}
+\ekvpLet{ekvd at populate@choice}{type}{protected}{protect}
+\ekvpLet{ekvd at populate@choice}{type}{unprotected}{unprotect}
+\protected\long\def\ekvd at populate@choice#1#2#3%
+  {%
+    #1\expandafter\edef
+        \csname\ekvd at choice@name\ekvd at set\ekvd at set@choice{#2}\endcsname
+      {\ekv at unexpanded{#3}}%
+  }
+\ekvd at def@type{choice}
+  {%
+    \ekvd at do@new{}{#1}%
+    \ekvd at assert@arg
+    \ekvd at type@choice{#1}%
+    \def\ekvd at set@choice{#1}%
+    \ekvpParse at unsafe\ekvp@@p at ekvd@populate at choice{#3}%
+  }
+\ekvd at def@type at fwd{choice-store}
+  {\ekvd at type@choicespecial\ekvd at populate@choicestore}
+\ekvd at def@type at fwd{choice-enum}
+  {\ekvd at type@choicespecial\ekvd at populate@choiceenum}
+\protected\long\def\ekvd at type@choicespecial#1#2#3%
+  {%
+    \ekvd at do@new{}{#2}%
+    \ekvd at assert@twoargs{#3}%
+    \ekvd at type@choice{#2}%
+    \def\ekvd at set@choice{#2}%
+    #1#3%
+  }
+\protected\long\def\ekvd at populate@choicestore#1%
+  {%
+    \ekvd at newlet#1\ekv at empty
+    \ekvparse{\ekvd at populate@choicestore at k#1}{\ekvd at populate@choicestore at kv#1}%
+  }
+\protected\long\def\ekvd at populate@choicestore at kv#1#2#3%
+  {%
+    \protected\expandafter\edef
+      \csname\ekvd at choice@name\ekvd at set\ekvd at set@choice{#2}\endcsname
+      {\ekv at unexpanded{\edef#1{\ekv at unexpanded{#3}}}}%
+  }
+\ekv at exparg{\protected\long\def\ekvd at populate@choicestore at k#1#2}%
+  {\ekvd at populate@choicestore at kv{#1}{#2}{#2}}
+\protected\long\def\ekvd at populate@choiceenum#1%
+  {%
+    \ekvd at newreg#1{count}%
+    \def\ekvd at tmp{0}%
+    \ekvcsvloop{\ekvd at populate@choiceenum@#1}%
+  }
+\protected\long\def\ekvd at populate@choiceenum@#1#2%
+  {%
+    \protected\expandafter\edef
+      \csname\ekvd at choice@name\ekvd at set\ekvd at set@choice{#2}\endcsname
+      {#1=\@firstofone{\ekvd at tmp} }%
+    \edef\ekvd at tmp{\the\numexpr\ekvd at tmp+1\relax}%
+  }
+\ekvd at def@type{unknown-choice}
+  {%
+    \ekvd at do@new at for@name{\ekvd at unknown@choice at name\ekvd at set{#1}}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at long
+    \ekvd at assert@not at also
+    \ekvd at prot\expandafter
+    \def\csname\ekvd at unknown@choice at name\ekvd at set{#1}\endcsname##1{#3}%
+  }
+\ekvd at def@type{unknown}
+  {%
+    \ekv at ifdefined{ekvd at type@unknown@\detokenize{#1}}%
+      {\csname ekvd at type@unknown@\detokenize{#1}\endcsname{#3}}%
+      \ekvd at err@misused at unknown
+  }
+\protected\long\def\ekvd at type@unknown at noval#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}uN}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \ekvd at prot\ekvd at long\ekvdefunknownNoVal\ekvd at set{#1}%
+  }
+\protected\long\def\ekvd at type@unknown at code#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}u}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \begingroup
+      \def\ekvd at tmp##1##2##3{#1}%
+      \ekv at exparg
+      {%
+        \endgroup
+        \ekvd at prot\ekvd at long\ekvdefunknown\ekvd at set
+      }%
+      {\ekvd at tmp{##2}{##1}{##3}}%
+  }
+\protected\edef\ekvd at type@unknown at redirect#1%
+  {%
+    \expandafter\noexpand\csname ekvd at type@unknown at redirect-code\endcsname{#1}%
+    \expandafter\noexpand\csname ekvd at type@unknown at redirect-noval\endcsname{#1}%
+  }
+\protected\expandafter\def\csname ekvd at type@unknown at redirect-code\endcsname#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}u}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \ekvd at assert@not at protected
+    \expandafter\ekvredirectunknown\expandafter{\ekvd at set}{#1}%
+  }
+\protected\expandafter\def\csname ekvd at type@unknown at redirect-noval\endcsname#1%
+  {%
+    \ekvd at do@new at for@name{\ekv at name\ekvd at set{}uN}%
+    \ekvd at assert@arg
+    \ekvd at assert@not at also
+    \ekvd at assert@not at protected
+    \expandafter\ekvredirectunknownNoVal\expandafter{\ekvd at set}{#1}%
+  }
+\def\ekvd at h@choice#1%
+  {%
+    \expandafter\ekvd at h@choice@
+      \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
+      {#1}%
+  }
+\def\ekvd at h@choice@#1#2%
+  {%
+    \ifx#1\relax
+      \ekvd at err@choice at invalid{#2}%
+      \expandafter\@gobble
+    \fi
+    #1%
+  }
+\protected\long\def\ekvd at add@val#1#2#3%
+  {%
+    \ekvd at assert@val{#1}%
+    \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}\endcsname{{##1}}%
+      {#1}{#2}{\ekvd at long\ekvdef}{#3}%
+  }
+\protected\long\def\ekvd at add@noval#1#2#3%
+  {%
+    \ekvd at assert@noval{#1}%
+    \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}N\endcsname{}%
+      {#1}{#2}\ekvdefNoVal{#3}%
+  }
+\protected\long\def\ekvd at add@aux#1#2%
+  {%
+    \ekvd at extract@prefixes#1%
+    \expandafter\ekvd at add@aux@\expandafter{#1#2}%
+  }
+\protected\long\def\ekvd at add@aux@#1#2#3#4#5%
+  {%
+    #5%
+    \ekvd at prot#4\ekvd at set{#2}{#1#3}%
+    \ekvd at clear@prefixes
+  }
+\protected\def\ekvd at extract@prefixes#1%
+  {%
+    \expandafter\ekvd at extract@prefixes@\meaning#1\ekvd at stop
+  }
+\protected\def\ekvd at extract@prefixes@#1#2#3%
+  {%
+    \protected\def\ekvd at extract@prefixes@##1#1##2\ekvd at stop
+      {%
+        \ekvd at extract@prefixes at long
+          ##1\ekvd at mark\@firstofone#2\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at long\long}%
+        \ekvd at extract@prefixes at prot
+          ##1\ekvd at mark\@firstofone#3\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at prot\protected}%
+      }%
+    \protected\def\ekvd at extract@prefixes at long##1#2##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+    \protected\def\ekvd at extract@prefixes at prot##1#3##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+  }
+\begingroup
+\edef\ekvd at tmp
+  {%
+    \endgroup
+    \ekvd at extract@prefixes@
+      {\detokenize{macro:}}%
+      {\string\long}%
+      {\string\protected}%
+  }
+\ekvd at tmp
+\protected\def\ekvd at newlet#1#2%
+  {%
+    \ifdefined#1%
+      \ifx#1\relax\ekv at fi@gobble\fi\@firstofone
+      \ekv at fi@gobble
+    \fi
+    \@firstofone{\let#1#2}%
+  }
+\protected\def\ekvd at newreg#1#2%
+  {%
+    \ifdefined#1%
+      \ifx#1\relax\ekv at fi@gobble\fi\@firstofone
+      \ekv at fi@gobble
+    \fi
+    \@firstofone{\csname new#2\endcsname#1}%
+  }
+\long\def\ekvd at assert@twoargs#1%
+  {\ekvd at ifnottwoargs{#1}{\ekvd at err@missing at definition\ekvpGobbleT}{}}
+\long\def\ekvd at ifnottwoargs#1%
+  {%
+    \ekvd at ifempty@gtwo#1\ekv at ifempty@B
+      \ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+  }
+\long\def\ekvd at ifempty@gtwo#1#2{\ekv at ifempty@\ekv at ifempty@A}
+\protected\def\ekvd at assert@val#1%
+  {%
+    \ekvifdefined\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@val@\csname\ekv at name\ekvd at set{#1}\endcsname}%
+      {%
+        \ekvifdefinedNoVal\ekvd at set{#1}%
+          \ekvd at err@add at val@on at noval
+          {\ekvd at err@undefined at key{#1}}%
+        \ekvpGobbleT
+      }%
+  }
+\protected\def\ekvd at assert@val@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekvd at one@arg at string
+      \ekvd at err@unsupported at arg
+      \expandafter\ekvpGobbleT
+    \fi
+  }%
+\protected\def\ekvd at assert@noval#1%
+  {%
+    \ekvifdefinedNoVal\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@noval@\csname\ekv at name\ekvd at set{#1}N\endcsname}%
+      {%
+        \ekvifdefined\ekvd at set{#1}%
+          \ekvd at err@add at noval@on at val
+          {\ekvd at err@undefined at key{#1}}%
+        \ekvpGobbleT
+      }%
+  }
+\protected\def\ekvd at assert@noval@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekv at empty
+      \ekvd at err@unsupported at arg
+      \expandafter\ekvpGobbleT
+    \fi
+  }
+\protected\def\ekvd at extract@args#1%
+  {%
+    \protected\def\ekvd at extract@args##1#1##2->##3\ekvd at stop
+      {\def\ekvd at extracted@args{##2}}%
+  }
+\expandafter\ekvd at extract@args\expandafter{\detokenize{macro:}}
+\edef\ekvd at one@arg at string{\string#1}
+\def\ekvd at assert@arg{\ekvd at ifnoarg{\ekvd at err@missing at definition\ekvpGobbleT}{}}
+\let\ekvd at ifnoarg\@secondoftwo
+\long\def\ekvd at assert@filledarg#1%
+  {\ekvd at ifnoarg@or at empty{#1}{\ekvd at err@missing at definition\ekvpGobbleT}{}}
+\long\def\ekvd at ifnoarg@or at empty#1%
+  {%
+    \ekvd at ifnoarg
+      \@firstoftwo
+      {\ekv at ifempty{#1}}%
+  }
+\def\ekvd at assert@not at long{\ifx\ekvd at long\long\ekvd at err@no at prefix{long}\fi}
+\def\ekvd at assert@not at protected
+  {\ifx\ekvd at prot\protected\ekvd at err@no at prefix{protected}\fi}
+\def\ekvd at assert@not at also{\ekvd at ifalso{\ekvd at err@no at prefix{also}}{}}
+\def\ekvd at assert@not at long@also
+  {\ifx\ekvd at long\long\ekvd at err@no at prefix@also{long}\fi}
+\def\ekvd at assert@not at protected@also
+  {\ifx\ekvd at prot\protected\ekvd at err@no at prefix@also{protected}\fi}
+\def\ekvd at assert@new#1#2%
+  {%
+    \csname ekvifdefined#1\endcsname\ekvd at set{#2}%
+      {\ekvd at err@not at new\ekvpGobbleT}%
+      {}%
+  }
+\def\ekvd at assert@not at new
+  {\ifx\ekvd at do@new\ekvd at assert@new\ekvd at err@no at prefix{new}\fi}
+\def\ekvd at do@new at for@name#1%
+  {%
+    \ifx\ekvd at do@new\ekvd at assert@new
+      \ekv at fi@firstofone
+    \fi
+    \@gobble{\ekv at ifdefined{#1}{\ekvd at err@not at new\ekvpGobbleT}{}}%
+  }
+\protected\def\ekvd at if@not at already@choice#1%
+  {%
+    \expandafter\ekvd at if@not at already@choice at a
+      \csname\ekv at name\ekvd at set{#1}\endcsname
+      {}\ekvd at h@choice\ekvd at stop
+  }
+\protected\def\ekvd at if@not at already@choice at a
+  {%
+    \expandafter\ekvd at if@not at already@choice at b
+  }
+\long\protected\def\ekvd at if@not at already@choice at b#1\ekvd at h@choice#2\ekvd at stop
+  {%
+    \ekv at ifempty{#2}\@firstofone\@gobble
+  }
+\long\def\ekvd at ifspace#1%
+  {%
+    \ekvd at ifspace@#1 \ekv at ifempty@B
+      \ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+  }
+\long\def\ekvd at ifspace@#1 % keep this space
+  {%
+    \ekv at ifempty@\ekv at ifempty@A
+  }
+\protected\long\def\ekvd at errm#1{\errmessage{expkv-def Error: #1}}
+\protected\def\ekvd at err@missing at definition
+  {\ekvd at errm{Missing definition for key `\ekvd at cur'}}
+\protected\def\ekvd at err@missing at type
+  {\ekvd at errm{Missing type prefix for key `\ekvd at cur'}}
+\protected\def\ekvd at err@undefined at prefix#1%
+  {%
+    \ekvd at errm
+      {%
+        Undefined prefix `\ekv at unexpanded{#1}' found while processing
+        `\ekvd at cur'%
+      }%
+  }
+\protected\def\ekvd at err@undefined at key#1%
+  {%
+    \ekvd at errm
+      {Undefined key `\ekv at unexpanded{#1}' found while processing `\ekvd at cur'}%
+  }
+\protected\def\ekvd at err@undefined at noval#1%
+  {%
+    \ekvd at errm
+      {%
+        Undefined noval key `\ekv at unexpanded{#1}' found while processing
+        `\ekvd at cur'%
+      }%
+  }
+\protected\def\ekvd at err@no at prefix#1%
+  {\ekvd at errm{prefix `#1' not accepted in `\ekvd at cur'}}
+\protected\def\ekvd at err@no at prefix@also#1%
+  {\ekvd at errm{`\ekvd at cur' not allowed with a `#1' key}}
+\protected\def\ekvd at err@add at val@on at noval
+  {\ekvd at errm{`\ekvd at cur' not allowed with a NoVal key}}
+\protected\def\ekvd at err@add at noval@on at val
+  {\ekvd at errm{`\ekvd at cur' not allowed with a value taking key}}
+\protected\def\ekvd at err@unsupported at arg
+  {%
+    \ekvd at errm
+      {%
+        Existing key-macro has the unsupported argument string
+        `\ekvd at extracted@args' for key `\ekvd at cur'%
+      }%
+  }
+\protected\def\ekvd at err@not at new
+  {\ekvd at errm{The key for `\ekvd at cur' is already defined}}
+\protected\long\def\ekvd at err@misused at unknown
+  {\ekvd at errm{Misuse of the unknown type found while processing `\ekvd at cur'}}
+\def\ekvd at err@choice at invalid#1%
+  {%
+    \ekvd at err@choice at invalid@#1%
+  }
+\begingroup
+\catcode40=8
+\catcode41=8
+\@firstofone{\endgroup
+\def\ekvd at choice@name#1#2#3%
+  {%
+    ekvd#1(#2)\detokenize{#3}%
+  }
+\def\ekvd at unknown@choice at name#1#2%
+  {%
+    ekvd:u:#1(#2)%
+  }
+\def\ekvd at err@choice at invalid@ ekvd#1(#2)\detokenize#3%
+  {%
+    \ekv at ifdefined{\ekvd at unknown@choice at name{#1}{#2}}%
+      {\csname\ekvd at unknown@choice at name{#1}{#2}\endcsname{#3}}%
+      {\ekvd at err{invalid choice `#3' for `#2' in set `#1'}}%
+  }
+}
+\ekv at exparg{\long\def\ekvd at err#1}{\ekverr{expkv-def}{#1}}
+\catcode`\@=\ekvd at tmp
+%% 
+%%
+%% End of file `expkv-def.tex'.


Property changes on: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-def.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-pop.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-pop.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-pop.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,326 @@
+%%
+%% This is file `expkv-pop.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-pop.dtx  (with options: `tex')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\input expkv
+\expandafter\ifx\csname ekvpVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+\def\ekvpVersion{1.0}
+\def\ekvpDate{2023-01-23}
+\csname ekvp at tmp\endcsname
+\expandafter\chardef\csname ekvp at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+\long\def\ekvpParse#1#2%
+  {%
+    \ekv at unexpanded\ekv at expanded
+      {{\expandafter\ekvpParse at a\detokenize{#1}\ekv at mark{#2}}}%
+  }
+\def\ekvpParse at a#1\ekv at mark
+  {%
+    \ekv at ifdefined{ekvp@@p@#1}%
+      {\expandafter\ekvpParse at b\csname ekvp@@p@#1\endcsname}%
+      {\ekvp at err@unknownparser{#1}\@gobble}%
+  }
+\def\ekvpParse at b#1%
+  {%
+    \ekv at ifdefined{#1{ppa}}%
+      {%
+        \expandafter\ekvpParse at c\expandafter
+          {\expandafter#1\csname#1{ppa}\endcsname}%
+      }%
+      {\ekvpParse at c{#1{}}}%
+  }
+\def\ekvpParse at c#1#2#3{#2#3}
+\ekv at expargtwice{\long\def\ekvpParse at c#1#2}%
+  {\expandafter\ekvpParse at c\ekvparse{\ekvp at k#1}{\ekvp at p#1}{#2}}
+\long\def\ekvpParse at unsafe#1#2#3{\ekv at unexpanded\ekv at expanded{{#2#3}}}
+\ekv at expargtwice{\long\def\ekvpParse at unsafe@auto#1#2#3}
+  {\expandafter\ekvpParse at unsafe\ekvparse{\ekvp at k#1#2}{\ekvp at p#1#2}{#3}}
+\ekv at expargtwice{\long\def\ekvpParse at unsafe#1#2}%
+  {\expandafter\ekvpParse at unsafe\ekvparse{\ekvp at k#1{}}{\ekvp at p#1{}}{#2}}
+\def\ekvp at k#1{\csname #1k\endcsname#1}
+\long\def\ekvp at ifspace#1%
+  {%
+    \ekvp at ifspace@#1 \ekv at ifempty@B\ekv at ifempty@false
+      \ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+  }
+\long\def\ekvp at ifspace@#1 % keep this space
+  {\ekv at ifempty@\ekv at ifempty@A}
+\ekv at exparg{\long\def\ekvp at prefix#1}%
+  {%
+    \ekvp at ifspace{#1}%
+      {\ekvp at prefix@a#1\ekv at stop}%
+      {\ekvp at noprefix{#1}}%
+  }
+\ekv at exparg{\long\def\ekvp at p#1#2#3}{\ekvp at prefix{#3}#1{#2}{#3}}
+\long\def\ekvp at prefix@a#1 % keep this space
+  {\expandafter\ekvp at prefix@b\detokenize{#1}\ekv at mark{#1}}
+\ekv at exparg{\long\def\ekvp at prefix@b#1\ekv at mark#2#3\ekv at stop#4}%
+  {%
+    \ekv at ifdefined{#4{pt}@#1}
+      {\expandafter\ekvp at prefix@pt\csname #4{pt}@#1\endcsname{#1}}%
+      {%
+        \ekv at ifdefined{#4{pp}@#1}%
+          {\expandafter\ekvp at prefix@pp\csname #4{pp}@#1\endcsname}%
+          {\@firstoftwo{\ekvp at noprefix{#2 #3}}}%
+      }%
+      {#3}#4%
+  }
+\long\def\ekvp at prefix@pt#1#2#3#4#5#6#7%
+  {%
+    \ekvp at prefix@pt@{#2}{#3}{#6}#5{\@firstoftwo#1}{#7}\ekvpEOT
+    \ekv at unexpanded{\ekvpEOA{#6}}%
+  }
+\long\def\ekvp at prefix@pt@#1#2#3#4{#4{#1}{#2}{#3}}
+\ekv at exparg{\long\def\ekvp at prefix@pp#1#2#3#4}{\ekvp at prefix{#2}#3{#4#1}}
+\long\def\ekvp at noprefix#1#2%
+  {%
+    \ekv at ifdefined{#2{pn}}
+      {\expandafter\ekvp at prefix@pt\csname #2{pn}\endcsname{}{#1}}
+      \ekvp at err@missingtype
+      #2%
+  }
+\protected\long\def\ekvpNewParser#1%
+  {\expandafter\ekvpNewParser@\detokenize{#1}\ekv at mark}
+\protected\def\ekvpNewParser@#1\ekv at mark
+  {%
+    \ekv at ifdefined{ekvp@@p@#1}%
+      {\ekvp at errm{Parser `#1' already defined}}%
+      {%
+        \expandafter\def\csname ekvp@@p@#1\endcsname##1{ekvp@@##1@#1}
+        \expandafter
+        \let\csname\csname ekvp@@p@#1\endcsname k\endcsname\ekvp at k@default
+      }%
+  }
+\protected\long\def\ekvpValueAlwaysRequired#1%
+  {\ekvp at parser@def{#1}\ekvpValueAlwaysRequired@{}}
+\protected\def\ekvpValueAlwaysRequired@#1%
+  {\expandafter\let\csname#1k\endcsname\ekvp at err@noval}
+\protected\long\def\ekvpDefNoValue#1%
+  {\ekvp at parser@def{#1}\ekvpDefNoValue@\@gobble}
+\protected\long\def\ekvpDefNoValue@#1#2%
+  {%
+    \def\ekvp at tmp##1{\ekv at unexpanded{#2}}%
+    \ekv at exparg{\long\expandafter\def\csname#1k\endcsname##1##2##3}%
+      {\ekvp at tmp{##3}}%
+  }
+\protected\long\def\ekvpUseNoValueMarker#1%
+  {\ekvp at parser@def{#1}\ekvpUseNoValueMarker@\@gobble}
+\protected\long\def\ekvpUseNoValueMarker@#1#2%
+  {%
+    \long\expandafter\edef\csname#1k\endcsname##1##2##3%
+      {\ekv at unexpanded{\ekvp at p}##1{##2}{##3}{\ekv at unexpanded{#2}}}%
+  }
+\protected\long\def\ekvpDefNoValuePrefix#1%
+  {\ekvp at parser@def{#1}\ekvpDefNoValuePrefix@\@gobbletwo}
+\protected\def\ekvpDefNoValuePrefix@#1%
+  {\expandafter\ekvpDefNoValuePrefix@@\csname#1{ppn}\endcsname#1}
+\protected\long\def\ekvpDefNoValuePrefix@@#1#2%
+  {%
+    \long\def#1\ekvp at p##1##2##3%
+      {%
+        \ekv at unexpanded{\ekvp at p}%
+          ####1{####2\ekv at unexpanded{#1}}{####3}{\ekv at unexpanded{##3}}%
+      }%
+    \long\expandafter\edef\csname#2k\endcsname##1##2##3%
+      {\expandafter\expandafter\expandafter#1\csname#2k\endcsname{}{}{}}%
+    \ekvp at parser@def at prefix#1%
+  }
+\protected\long\def\ekvpDefAutoPrefix#1%
+  {\ekvp at parser@def{#1}\ekvpDefAutoPrefix@\@gobbletwo}
+\protected\long\def\ekvpDefAutoPrefix@#1%
+  {\expandafter\ekvp at parser@def at prefix\csname#1{ppa}\endcsname}
+\long\def\ekvp at parser@def#1%
+  {\expandafter\ekvp at parser@def@\detokenize{#1}\ekv at mark}
+\def\ekvp at parser@def@#1\ekv at mark#2#3%
+  {%
+    \ekv at ifdefined{ekvp@@p@#1}%
+      {\ekv at exparg{#2}{\csname ekvp@@p@#1\endcsname}}%
+      {\ekvp at errm{Parser `#1' not defined}#3}%
+  }
+\protected\long\def\ekvpDefPrefix#1%
+  {\ekvp at parser@def{#1}\ekvpDefPrefix@\@gobblethree}
+\protected\long\def\ekvpDefPrefix@#1#2%
+  {\expandafter\ekvp at parser@def at prefix\csname#1{pp}@\detokenize{#2}\endcsname}
+\protected\long\def\ekvp at parser@def at prefix#1#2#3%
+  {%
+    \def#1##1##2##3{#2#3}%
+    \long\def#1##1##2##3##4##5\ekvpEOT
+      {\ekv at unexpanded{#2}##4{##1}{##2}{##3}##5\ekvpEOT\ekv at unexpanded{#3}}%
+  }
+\ekv at exparg{\protected\long\def\ekvpDefPrefixLet#1#2#3#4#5}%
+  {\ekvpDefPrefix{#1}{#2}{\ekvpProtect{\let#3= #4}}{\ekvpProtect{\let#3= #5}}}
+\ekv at exparg{\protected\long\def\ekvpDefPrefixStore#1#2#3#4#5}%
+  {%
+    \ekvpDefPrefix{#1}{#2}%
+      {\ekvpProtect{\edef#3{\ekv at unexpanded{#4}}}}%
+      {\ekvpProtect{\edef#3{\ekv at unexpanded{#5}}}}%
+  }
+\protected\long\def\ekvpDefType#1{\ekvp at parser@def{#1}\ekvpDefType@\@gobbletwo}
+\protected\long\def\ekvpDefType@#1#2%
+  {\ekvpDefType at NoType{#1{pt}@\detokenize{#2}}}%
+\protected\long\def\ekvpDefNoType#1{\ekvp at parser@def{#1}\ekvpDefNoType@\@gobble}
+\protected\long\def\ekvpDefNoType@#1{\ekvpDefType at NoType{#1{pn}}}
+\protected\long\def\ekvpDefType at NoType#1#2%
+  {%
+    \long\expandafter\def\csname#1\endcsname##1##2##3\ekvpEOT
+      {\ekv at unexpanded{\ekvpEOP{##2}#2\ekvpEOT{##2}}}%
+  }%
+\protected\long\def\ekvpLet#1#2#3{\ekvoptarg{\ekvpLet at a{#1}{#2}{#3}}{#1}}
+\protected\long\def\ekvpLet at a#1%
+  {\ekvp at parser@def{#1}\ekvpLet at b{\@firstoftwo\@gobblethree}}
+\protected\long\def\ekvpLet at b#1#2#3#4%
+  {\ekvp at parser@def{#4}\ekvpLet at c{\@firstoftwo\@gobblethree}#1{#2}{#3}}
+\protected\long\def\ekvpLet at c#1#2#3%
+  {%
+    \ekv at ifdefined{ekvpLet@@\detokenize{#3}}%
+      {\expandafter\ekvpLet at d\csname ekvpLet@@\detokenize{#3}\endcsname{#1}{#2}}%
+      {\ekvp at errm{unknown type \detokenize{#3}}\@gobbletwo}%
+  }
+\protected\long\def\ekvpLet at d#1#2#3#4#5%
+  {%
+    \ekv at ifdefined{#2{#1}@\detokenize{#5}}%
+      {%
+        \expandafter\let
+          \csname#3{#1}@\detokenize{#4}\expandafter\endcsname
+          \csname#2{#1}@\detokenize{#5}\endcsname
+      }%
+      {\ekvp at errm{Undefined prefix/type \detokenize{#5} can't be copied}}%
+  }
+\def\ekvpLet@@prefix{pp}
+\def\ekvpLet@@type{pt}
+\ekv at ifdefined{c_novalue_tl}
+  {\expandafter\let\expandafter\ekvp at novalflag\csname c_novalue_tl\endcsname}
+  {%
+    \begingroup
+    \lccode`\Z=`\-
+    \lccode`\:=`\-
+    \lccode`\N=\z@
+    \lccode`\V=\z@
+    \lowercase{\endgroup\def\ekvp at novalflag{ZNoValue:}}%
+  }
+\def\ekvpIfNoVal#1%
+  {%
+    \long\def\ekvpIfNoVal##1%
+      {%
+        \ekvp at ifnoval{}##1{}?!#1??!\ekv at ifempty@B\ekv at ifempty@true
+          \ekv at ifempty@A\ekv at ifempty@B\@secondoftwo
+      }%
+    \long\def\ekvp at ifnoval##1#1##2?##3?!{\ekv at ifempty@\ekv at ifempty@A##1##2}%
+    \long\def\ekvp at k@default##1##2##3{\ekvp at p##1{##2}{##3}{#1}}%
+  }
+\expandafter\ekvpIfNoVal\expandafter{\ekvp at novalflag}
+\let\ekvp at novalflag\ekvp at undefined
+\def\ekvpAssertIf{\romannumeral\ekv at alignsafe\ekvoptarg{\ekvpAssertIf@{}}{EOT}}
+\def\ekvpAssertIfNot
+  {\romannumeral\ekv at alignsafe\ekvoptarg{\ekvpAssertIf@\else}{EOT}}
+\long\def\ekvpAssertIf@#1#2#3%
+  {%
+    #3#1\ekvpAssertIf at good\fi
+    \ekvpAssert at notgood{#2}%
+  }
+\long\def\ekvpAssertIf at good\fi\ekvpAssert at notgood#1#2%
+  {\fi\ekv at endalignsafe\ekv at zero}
+\long\def\ekvpAssert at notgood#1%
+  {%
+    \ekv at ifdefined{ekvpAssert@@#1}%
+      {\csname ekvpAssert@@#1\endcsname}%
+      {\ekvp at err@unknownmarker{#1}\ekvpAssert@@EOA}%
+  }
+\def\ekvpAssertTF{\ekvoptarg{\ekvpAssertTF@{}}{EOT}}
+\def\ekvpAssertTFNot{\ekvoptarg{\ekvpAssertTF@{\@secondoftwo\@firstoftwo}}{EOT}}
+\long\def\ekvpAssertTF@#1#2#3%
+  {%
+    \ekv at alignsafe
+    #3#1%
+      {\ekv at endalignsafe\@gobble}%
+      {\romannumeral\ekvpAssert at notgood{#2}}%
+  }
+\ekv at exparg{\def\ekvpAssert at further#1#2#3}%
+  {\ekvoptarg{\ekvpAssert at further{#1}{#2}{#3}}{EOT}}
+\ekv at exparg{\def\ekvpAssertValue}%
+  {\ekvpAssert at further{\@secondoftwo\@firstoftwo}{\ekvpIfNoVal}{missing value}}
+\ekv at exparg{\def\ekvpAssertNoValue}%
+  {\ekvpAssert at further{}{\ekvpIfNoVal}{superfluous value}}
+\ekv at exparg{\def\ekvpAssertOneValue}%
+  {\ekvpAssert at further{}{\ekvp at assert@num at args\@gobble}{argument count != 1}}
+\ekv at exparg{\def\ekvpAssertTwoValues}%
+  {\ekvpAssert at further{}{\ekvp at assert@num at args\@gobbletwo}{argument count != 2}}
+\long\def\ekvp at assert@num at args#1#2%
+  {%
+    \expandafter\ekv at ifempty@\expandafter\ekv at ifempty@A#1#2\ekv at ifempty@B
+      \ekv at ifempty@true\ekv at ifempty@A\ekv at ifempty@B\@secondoftwo
+  }
+\long\def\ekvpAssert at further#1#2#3#4#5{\ekvpAssertTF@{#1}{#4}{#2{#5}}{#3}}
+\def\ekvpAssert@@EOA#1#2%
+  {\long\def#1##1##2#2##3{\ekvp at err{##1 at `##3'}\ekv at endalignsafe\ekv at zero}}
+\ekvpAssert@@EOA\ekvpAssert@@EOP\ekvpEOP
+\ekvpAssert@@EOA\ekvpAssert@@EOT\ekvpEOT
+\ekvpAssert@@EOA\ekvpAssert@@EOA\ekvpEOA
+\long\def\ekvpGobbleP#1\ekvpEOP#2{}
+\long\def\ekvpGobbleT#1\ekvpEOT#2{}
+\long\def\ekvpGobbleA#1\ekvpEOA#2{}
+\let\ekvpEOP\@gobble
+\let\ekvpEOT\@gobble
+\let\ekvpEOA\@gobble
+\def\ekvpProtect{\ekvpProtect@\ekvpProtect@@}
+\protected\long\def\ekvpProtect@\ekvpProtect@@#1{#1}
+\long\def\ekvpProtect@@#1{\ekv at unexpanded{\ekvpProtect@@{#1}}}
+\protected\long\def\ekvp at errm#1{\errmessage{expkv-pop Error: #1}}
+\ekv at exparg{\long\def\ekvp at err#1}{\ekverr{expkv-pop}{#1}}
+\def\ekvp at err@unknownparser#1{\ekvp at err{unknown parser `#1'}}
+\long\def\ekvp at err@noval#1#2#3{\ekvp at err{missing value for `#3'}}
+\long\def\ekvp at err@missingtype#1#2#3#4{\ekvp at err{missing type in `#3'}}
+\long\def\ekvp at err@unknownmarker#1{\ekvp at err{unknown marker `#1'}}
+\let\ekvp at prefix\ekvp at undefined
+\catcode`\@=\ekvp at tmp
+%% 
+%%
+%% End of file `expkv-pop.tex'.


Property changes on: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv-pop.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv.tex	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,1245 @@
+%%
+%% This is file `expkv.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv.dtx  (with options: `tex')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\expandafter\ifx\csname ekvVersion\endcsname\relax
+\else
+  \expandafter\endinput
+\fi
+\begingroup
+  \edef\ekvtmpa{\string\expanded}
+  \edef\ekvtmpb{\meaning\expanded}
+  \expandafter
+\endgroup
+\ifx\ekvtmpa\ekvtmpb
+  \expandafter\let\csname ekv at expanded\endcsname\expanded
+  \expandafter\let\csname ekv at unexpanded\endcsname\unexpanded
+\else
+  \begingroup
+    \edef\ekvtmpa{\string\expanded}
+    \edef\ekvtmpb{\meaning\normalexpanded}
+    \expandafter
+  \endgroup
+  \ifx\ekvtmpa\ekvtmpb
+    \expandafter\let\csname ekv at expanded\endcsname\normalexpanded
+    \expandafter\let\csname ekv at unexpanded\endcsname\normalunexpanded
+  \else
+    \errmessage
+      {expkv Error: e-TeX and the \noexpand\expanded primitive required}%
+    \expandafter\endinput
+  \fi
+\fi
+\def\ekvVersion{2.0}
+\def\ekvDate{2023-01-23}
+\csname ekv at tmp\endcsname
+\expandafter\chardef\csname ekv at tmp\endcsname=\catcode`\@
+\catcode`\@=11
+\begingroup
+  \edef\ekv at tmpa{\string \lastnamedcs}
+  \edef\ekv at tmpb{\meaning\lastnamedcs}
+  \ifx\ekv at tmpa\ekv at tmpb
+    \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##1}}
+  \else
+    \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##2}}
+  \fi
+  \expandafter
+\endgroup
+\ekv at if@lastnamedcs
+\def\ekv at empty{}
+\long\def\@gobble#1{}
+\long\def\@gobbletwo#1#2{}
+\long\def\@gobblethree#1#2#3{}
+\long\def\@firstofone#1{#1}
+\long\def\@firstoftwo#1#2{#1}
+\long\def\@secondoftwo#1#2{#2}
+\long\def\ekv at fi@gobble\fi\@firstofone#1{\fi}
+\long\def\ekv at fi@firstofone\fi\@gobble#1{\fi#1}
+\long\def\ekv at fi@firstoftwo\fi\@secondoftwo#1#2{\fi#1}
+\long\def\ekv at fi@secondoftwo\fi\@firstoftwo#1#2{\fi#2}
+\def\ekv at gobble@mark\ekv at mark{}
+\long\def\ekv at gobbleto@stop#1\ekv at stop{}
+\long\def\ekv at gobble@from at mark@to at stop\ekv at mark#1\ekv at stop{}
+\long\def\ekv at ifempty#1%
+  {%
+    \ekv at ifempty@\ekv at ifempty@A#1\ekv at ifempty@B\ekv at ifempty@true
+      \ekv at ifempty@A\ekv at ifempty@B\@secondoftwo
+  }
+\long\def\ekv at ifempty@#1\ekv at ifempty@A\ekv at ifempty@B{}
+\long\def\ekv at ifempty@true\ekv at ifempty@A\ekv at ifempty@B\@secondoftwo#1#2{#1}
+\long\def\ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo#1#2{#2}
+\long\def\ekv at ifempty@true at F\ekv at ifempty@A\ekv at ifempty@B\@firstofone#1{}
+\long\def\ekv at ifempty@true at F@gobble\ekv at ifempty@A\ekv at ifempty@B\@firstofone#1#2%
+  {}
+\long\def\ekv at ifempty@true at F@gobbletwo
+    \ekv at ifempty@A\ekv at ifempty@B\@firstofone#1#2#3%
+  {}
+\long\def\ekv at ifblank#1%
+  {\ekv at ifblank@#1\ekv at stop\ekv at ifblank@false\ekv at stop\@firstoftwo}
+\long\def\ekv at ifblank@\ekv at mark#1#2\ekv at stop{}
+\long\def\ekv at ifblank@false\ekv at stop\@firstoftwo#1#2{#2}
+\def\ekv at ifblank@gobbletrue\ekv at stop#1{}
+\ekv at if@lastnamedcs
+  {%
+    \long\def\ekv at ifdefined#1{\ifcsname#1\endcsname\ekv at ifdef@\fi\@secondoftwo}
+    \def\ekv at ifdef@\fi\@secondoftwo
+      {%
+        \fi
+        \expandafter\ifx\lastnamedcs\relax
+          \ekv at fi@secondoftwo
+        \fi
+        \@firstoftwo
+      }
+  }
+  {%
+    \long\def\ekv at ifdefined#1%
+      {%
+        \ifcsname#1\endcsname\ekv at ifdef@\fi\ekv at ifdef@false#1\endcsname\relax
+          \ekv at fi@secondoftwo
+        \fi
+        \@firstoftwo
+      }
+    \def\ekv at ifdef@\fi\ekv at ifdef@false{\fi\expandafter\ifx\csname}
+    \long\def\ekv at ifdef@false
+        #1\endcsname\relax\ekv at fi@secondoftwo\fi\@firstoftwo#2#3%
+      {#3}
+  }
+\def\ekv at strip#1%
+  {%
+    \long\def\ekv at strip##1%
+      {%
+        \ekv at strip@a
+          ##1\ekv at nil
+          \ekv at mark#1%
+          #1\ekv at nil
+      }%
+    \long\def\ekv at strip@a##1\ekv at mark#1{\ekv at strip@b##1\ekv at mark}%
+  }
+\ekv at strip{ }
+\long\def\ekv at strip@b#1 \ekv at nil{\ekv at strip@c#1\ekv at nil}
+\long\def\ekv at strip@c\ekv at mark#1\ekv at nil\ekv at mark#2\ekv at nil#3{#3{#1}}
+\def\ekv at strip@key#1%
+  {%
+    \long\def\ekv at strip@key##1{\ekv at strip@key at a##1\ekv at nil\ekv at mark#1#1\ekv at nil}
+    \long\def\ekv at strip@key at a##1\ekv at mark#1{\ekv at strip@key at b##1\ekv at mark}
+  }
+\ekv at strip@key{ }
+\long\def\ekv at strip@key at b#1 \ekv at nil{\ekv at strip@key at c#1\ekv at nil}
+\long\def\ekv at strip@key at c\ekv at mark#1\ekv at nil\ekv at mark#2\ekv at nil#3%
+  {\expandafter#3\detokenize{#1}\ekv at mark{#1}}
+\let\ekv at zero\z@
+\long\def\ekv at exparg#1#2%
+  {\ekv at expanded{\ekv at unexpanded{#1}\expandafter}\expandafter{#2}}
+\long\def\ekv at expandafter#1{\ekv at expanded{\ekv at unexpanded{#1}\expandafter}}
+\long\def\ekv at exparg@#1#2{#2{#1}}%
+\long\def\ekv at expandedarg#1#2{\ekv at expanded{\ekv at unexpanded{#1}{#2}}}
+\long\def\ekv at fexparg#1#2%
+  {%
+    \ekv at expanded{\ekv at unexpanded{#1}\expandafter}\expandafter
+      {\romannumeral`\^^@#2}%
+  }
+\long\def\ekv at expargtwice#1#2{\expandafter\ekv at expargtwice@\expandafter{#2}{#1}}
+\def\ekv at expargtwice@{\expandafter\ekv at exparg@\expandafter}
+\begingroup
+\def\ekvcsvloop#1{%
+\endgroup
+\long\def\ekvcsvloop##1##2%
+  {\ekv at csv@loop at active{##1}\ekv at mark##2#1\ekv at stop#1}
+\long\def\ekv at csv@loop at active##1##2#1%
+  {%
+    \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at active@end\ekv at stop
+    \ekv at csv@loop{##1}##2,\ekv at stop,%
+  }%
+\long\def\ekv at csv@loop at active@end
+    \ekv at stop
+    \ekv at csv@loop##1\ekv at mark\ekv at stop,\ekv at stop,%
+  {}%
+}
+\catcode`\,=13
+\ekvcsvloop,
+\def\ekv at csv@loop#1%
+  {%
+    \long\def\ekv at csv@loop##1##2,%
+      {%
+        \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at end\ekv at stop
+        \ekv at ifblank@##2\ekv at stop\ekv at ifblank@gobbletrue
+          \ekv at stop\ekv at csv@loop at blank
+        #1\ekv at csv@loop at do{##1}%
+      }%
+  }
+\expandafter\ekv at csv@loop\expandafter{\ekv at strip{#2}}
+\long\def\ekv at csv@loop at do#1#2{\ekv at unexpanded{#2{#1}}\ekv at csv@loop{#2}\ekv at mark}
+\def\ekv at csv@loop at end#1%
+  {%
+    \long\def\ekv at csv@loop at end
+        \ekv at stop
+        \ekv at ifblank@\ekv at mark\ekv at stop\ekv at stop\ekv at ifblank@gobbletrue
+        \ekv at stop\ekv at csv@loop at blank
+        #1\ekv at csv@loop at do##1%
+      {\ekv at csv@loop at active{##1}\ekv at mark}%
+  }
+\expandafter\ekv at csv@loop at end\expandafter{\ekv at strip{\ekv at mark\ekv at stop}}
+\long\expandafter\def\expandafter\ekv at csv@loop at blank
+    \ekv at strip{\ekv at mark#1}\ekv at csv@loop at do#2%
+  {\ekv at csv@loop{#2}\ekv at mark}
+\def\ekv at name@set#1{ekv#1(}
+\long\def\ekv at name@key#1{#1)}
+\edef\ekv at name
+  {%
+    \ekv at unexpanded\expandafter{\ekv at name@set{#1}}%
+    \ekv at unexpanded\expandafter{\ekv at name@key{\detokenize{#2}}}%
+  }
+\long\ekv at exparg{\def\ekv at name#1#2}{\ekv at name}
+\def\ekv at undefined@set#1{! expkv Error: Set `#1' undefined.}
+\edef\ekv at checkvalid
+  {%
+    \ekv at unexpanded\expandafter{\ekv at ifempty{#1}}%
+    \ekv at unexpanded
+      {{%
+        \def\ekv at tmp{}%
+        \ekv at errm{empty set name not allowed}%
+      }}%
+      {%
+        \ekv at unexpanded\expandafter{\ekv at ifempty{#2}}%
+        \ekv at unexpanded
+          {%
+            {%
+              \def\ekv at tmp{}%
+              \ekv at errm{empty key name not allowed}%
+            }%
+            \@secondoftwo
+          }%
+      }%
+    \ekv at unexpanded{\@gobble}%
+  }
+\ekv at exparg{\protected\def\ekv at checkvalid#1#2}{\ekv at checkvalid}%
+\ekv at expargtwice{\long\def\ekvifdefined#1#2}%
+  {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}}}
+\ekv at expargtwice{\long\def\ekvifdefinedNoVal#1#2}%
+  {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}N}}
+\def\ekvdef#1#2#3#4#5#6%
+  {%
+    \protected\long\def\ekvdef##1##2##3%
+      {#1{\expandafter\def\csname#2\endcsname####1{##3}#4}}%
+    \protected\long\def\ekvdefNoVal##1##2##3%
+      {#1{\expandafter\def\csname#2N\endcsname{##3}#4}}%
+    \protected\long\def\ekvlet##1##2##3%
+      {#1{\expandafter\let\csname#2\endcsname##3#4}}%
+    \protected\long\def\ekvletNoVal##1##2##3%
+      {#1{\expandafter\let\csname#2N\endcsname##3#4}}%
+    \ekv at expargtwice{\protected\long\def\ekv at defunknown##1##2##3##4}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\ekv at zero\ekv at checkvalid{##3}.}%
+          {%
+            \expandafter\expandafter\expandafter
+            \def\expandafter\csname\ekv at name{##3}{}u##1\endcsname##2{##4}%
+            #6%
+          }%
+      }%
+    \ekv at expargtwice{\protected\long\def\ekv at letunknown##1##2##3}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\ekv at zero\ekv at checkvalid{##2}.}%
+          {%
+            \expandafter\expandafter\expandafter
+            \let\expandafter\csname\ekv at name{##2}{}u##1\endcsname##3%
+            #5%
+          }%
+      }%
+    \protected\long\def\ekvletkv##1##2##3##4%
+      {%
+        #1%
+          {%
+            \expandafter\let\csname#2\expandafter\endcsname
+            \csname#3\endcsname
+            #4%
+          }%
+      }%
+    \protected\long\def\ekvletkvNoVal##1##2##3##4%
+      {%
+        #1%
+          {%
+            \expandafter\let\csname#2N\expandafter\endcsname
+            \csname#3N\endcsname
+            #4%
+          }%
+      }%
+  }
+\edef\ekvdefNoVal
+  {%
+    {\ekv at unexpanded\expandafter{\ekv at checkvalid{#1}{#2}}}%
+    {\ekv at unexpanded\expandafter{\ekv at name{#1}{#2}}}%
+    {\ekv at unexpanded\expandafter{\ekv at name{#3}{#4}}}%
+    {%
+      \ekv at unexpanded{\expandafter\ekv at defsetmacro\csname}%
+      \ekv at unexpanded\expandafter{\ekv at undefined@set{#1}\endcsname{#1}}%
+    }%
+    {%
+      \ekv at unexpanded{\expandafter\ekv at defsetmacro\csname}%
+      \ekv at unexpanded\expandafter{\ekv at undefined@set{#2}\endcsname{#2}}%
+    }%
+    {%
+      \ekv at unexpanded{\expandafter\ekv at defsetmacro\csname}%
+      \ekv at unexpanded\expandafter{\ekv at undefined@set{#3}\endcsname{#3}}%
+    }%
+  }
+\expandafter\ekvdef\ekvdefNoVal
+\ekv at exparg{\protected\long\def\ekvdefunknown#1#2}%
+  {\ekv at defunknown{}{##1##2##3}{#1}{#2}}
+\ekv at exparg{\protected\long\def\ekvdefunknownNoVal#1#2}%
+  {\ekv at defunknown{N}{##1##2}{#1}{#2}}
+\ekv at exparg{\protected\long\def\ekvletunknown#1#2}%
+  {\ekv at letunknown{}{#1}{#2}}
+\ekv at exparg{\protected\long\def\ekvletunknownNoVal#1#2}%
+  {\ekv at letunknown{N}{#1}{#2}}
+\let\ekv at defunknown\ekv at undefined
+\let\ekv at letunknown\ekv at undefined
+\protected\def\ekv at defredirectunknown#1#2#3#4#5#6%
+  {%
+    \begingroup
+    \edef\ekv at tmp
+      {%
+        \ekvcsvloop#1{#6}%
+        \ekv at unexpanded{#2}%
+        {\ekvcsvloop{}{#5,#6}}%
+      }%
+    \ekv at expargtwice
+      {\endgroup\long#3{#5}}%
+      {\expandafter#4\ekv at tmp\ekv at stop}%
+  }
+\ekv at exparg{\protected\def\ekvredirectunknown#1#2}%
+  {%
+    \ekv at defredirectunknown
+      \ekv at redirect@kv
+      \ekv at err@redirect at kv@notfound
+      \ekvdefunknown
+      \ekv at redirectunknown@aux
+      {#1}{#2}%
+  }
+\ekv at exparg{\protected\def\ekvredirectunknownNoVal#1#2}%
+  {%
+    \ekv at defredirectunknown
+      \ekv at redirect@k
+      \ekv at err@redirect at k@notfound
+      \ekvdefunknownNoVal
+      \ekv at redirectunknownNoVal@aux
+      {#1}{#2}%
+  }
+\def\ekv at redirectunknown@aux#1{#1{##1}{##2}}
+\def\ekv at redirectunknownNoVal@aux#1{#1{##1}}
+\let\ekv at defredirectunknown\ekv at undefined
+\def\ekv at redirect@k#1#2#3#4%
+  {%
+    \ekv at if@lastnamedcs
+      {%
+        \def\ekv at redirect@k##1##2##3%
+          {%
+            \ifcsname#1\endcsname\ekv at redirect@k at a\fi
+            ##3{##1}%
+          }%
+        \def\ekv at redirect@k at a\fi{\fi\expandafter\ekv at redirect@k at b\lastnamedcs}%
+        \long\def\ekv at redirect@kv##1##2##3##4%
+          {%
+            \ifcsname#2\endcsname\ekv at redirect@kv at a\fi\@gobble{##1}%
+            ##4{##1}{##2}%
+          }%
+        \def\ekv at redirect@kv at a\fi\@gobble
+          {\fi\expandafter\ekv at redirect@kv at b\lastnamedcs}%
+      }
+      {%
+        \def\ekv at redirect@k##1##2##3%
+          {%
+            \ifcsname#1\endcsname\ekv at redirect@k at a\fi\ekv at redirect@k at a@
+              #1\endcsname
+            ##3{##1}%
+          }%
+        \def\ekv at redirect@k at a@#3\endcsname{}%
+        \def\ekv at redirect@k at a\fi\ekv at redirect@k at a@
+          {\fi\expandafter\ekv at redirect@k at b\csname}%
+        \long\def\ekv at redirect@kv##1##2##3##4%
+          {%
+            \ifcsname#2\endcsname\ekv at redirect@kv at a\fi\ekv at redirect@kv at a@
+              #2\endcsname{##1}%
+            ##4{##1}{##2}%
+          }%
+        \long\def\ekv at redirect@kv at a@#4\endcsname##3{}%
+        \def\ekv at redirect@kv at a\fi\ekv at redirect@kv at a@
+          {\fi\expandafter\ekv at redirect@kv at b\csname}%
+      }%
+  }
+\def\ekv at redirect@kv#1\detokenize#2#3\ekv at stop{\ekv at unexpanded{#1#2#3}}
+\edef\ekv at redirect@kv
+  {%
+    {\expandafter\ekv at redirect@kv\ekv at name{#2}{#1}N\ekv at stop}%
+    {\expandafter\ekv at redirect@kv\ekv at name{#3}{#2}\ekv at stop}%
+    {\expandafter\ekv at redirect@kv\ekv at name{#1}{#2}N\ekv at stop}%
+    {\expandafter\ekv at redirect@kv\ekv at name{#1}{#2}\ekv at stop}%
+  }
+\expandafter\ekv at redirect@k\ekv at redirect@kv
+\def\ekv at redirect@k at b#1%
+  {\ifx\relax#1\ekv at redirect@k at c\fi\ekv at redirect@k at d#1}
+\def\ekv at redirect@k at c\fi\ekv at redirect@k at d#1{\fi}
+\def\ekv at redirect@k at d#1#2\ekv at stop{#1}
+\def\ekv at redirect@kv at b#1%
+  {\ifx\relax#1\ekv at redirect@kv at c\fi\ekv at redirect@kv at d#1}
+\long\def\ekv at redirect@kv at c\fi\ekv at redirect@kv at d#1#2{\fi}
+\long\def\ekv at redirect@kv at d#1#2#3\ekv at stop{#1{#2}}
+\edef\ekv at defsetmacro
+  {%
+    \ekv at unexpanded{\ifx#1\relax\edef#1##1}%
+      {%
+        \ekv at unexpanded\expandafter{\ekv at name@set{#2}}%
+        \ekv at unexpanded\expandafter{\ekv at name@key{##1}}%
+      }%
+    \ekv at unexpanded{\fi}%
+  }
+\ekv at exparg{\protected\def\ekv at defsetmacro#1#2}{\ekv at defsetmacro}
+\ekv at expargtwice{\def\ekvifdefinedset#1}%
+  {\expandafter\ekv at ifdefined\expandafter{\ekv at undefined@set{#1}}}
+\def\ekv at ifexp#1#2%
+  {%
+    \long\def\ekv at ifexp@split at o@or at other
+        ##1: ##2\ekv at stop##3%
+        ##4#1##5\ekv at stop##6%
+        ##7#2##8\ekv at stop##9%
+      {##9##6##3##1\ekv at stop##2}%
+    \long\def\ekv at ifexp@split at a@or at l
+        ##1#1##2\ekv at stop##3%
+        ##4#2##5\ekv at stop##6%
+      {##6##3##1\ekv at stop##2}%
+    \long\def\ekv at ifexp@split at a##1#1##2\ekv at stop##3%
+      {##3##1\ekv at stop##2}%
+    \long\def\ekv at ifexp@split at l##1#2##2\ekv at stop##3%
+      {##3##1\ekv at stop##2}%
+    \long\def\ekv at ifexp##1%
+      {%
+        \ekv at ifexp@split at o@or at other
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@o
+          : \ekv at stop\ekv at ifexp@none
+          ##1\ekv at stop\ekv at ifexp@a#1\ekv at stop{}%
+          ##1\ekv at stop\ekv at ifexp@l#2\ekv at stop{}%
+      }%
+    \long\def\ekv at ifexp@o##1\ekv at stop
+      {\ekv at ifexp@done{##1}\ekv at mark}%
+    \long\def\ekv at ifexp@none
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@o\ekv at stop
+        ##2##3%
+      {##3}%
+    \def\ekv at ifexp@a##1%
+      {%
+        \ekv at ifexp@a at i
+          ##1\ekv at ifexp@a at ii
+          \ekv at ifexp@none\ekv at ifexp@a at or@o
+      }%
+    \def\ekv at ifexp@a at i##1\ekv at ifexp@none{}%
+    \long\def\ekv at ifexp@a at ii
+        \ekv at ifexp@none\ekv at ifexp@a at or@o
+        ##1#1##2\ekv at stop\ekv at ifexp@o\ekv at stop
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+    \long\def\ekv at ifexp@a at or@o##1\ekv at stop
+      {%
+        \ekv at ifexp@split at a
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@o
+          #1\ekv at stop\ekv at ifexp@o at not@a
+      }%
+    \long\def\ekv at ifexp@a at not@o##1\ekv at stop
+      {\ekv at ifexp@a at not@o@{##1}\ekv at mark}
+    \long\def\ekv at ifexp@a at not@o@
+        ##1##2\ekv at nil#1\ekv at stop\ekv at ifexp@o at not@a
+      {\ekv at ifexp@done{##1}##2: }%
+    \long\def\ekv at ifexp@o at not@a
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@o\ekv at stop
+      {\ekv at ifexp@done{##1}\ekv at mark}%
+    \def\ekv at ifexp@l##1%
+      {%
+        \ekv at ifexp@l at i
+          ##1\ekv at ifexp@l at ii
+          \ekv at ifexp@none{}%
+          ##1\ekv at ifexp@l at or@o
+          \ekv at ifexp@o
+        \ekv at ifexp@l at or@a
+      }%
+    \def\ekv at ifexp@l at i
+        ##1\ekv at ifexp@none##2%
+        ##3\ekv at ifexp@o
+      {##2}%
+    \long\def\ekv at ifexp@l at ii
+        \ekv at ifexp@l at or@a##1#2##2\ekv at stop
+        \ekv at ifexp@o\ekv at stop#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+    \long\def\ekv at ifexp@l at or@o
+        \ekv at ifexp@o\ekv at ifexp@l at or@a
+        ##1\ekv at stop
+      {%
+        \ekv at ifexp@split at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@o
+          #2\ekv at stop\ekv at ifexp@o at not@l
+      }%
+    \long\def\ekv at ifexp@l at not@o##1\ekv at stop
+      {\ekv at ifexp@l at not@o@{##1}\ekv at mark}
+    \long\def\ekv at ifexp@l at not@o@
+        ##1##2\ekv at nil#2\ekv at stop\ekv at ifexp@o at not@l
+        ##3#2\ekv at stop##4%
+      {\ekv at ifexp@done{##1}##2: ##3}%
+    \long\def\ekv at ifexp@o at not@l
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@o\ekv at stop
+        ##2#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+    \def\ekv at ifexp@l at or@a##1%
+      {%
+        \ekv at ifexp@a at i
+          ##1\ekv at ifexp@l at or@a at not@o
+          \ekv at ifexp@none
+        \ekv at ifexp@l at or@a at or@o
+      }%
+    \long\def\ekv at ifexp@l at or@a at not@o
+        \ekv at ifexp@none\ekv at ifexp@l at or@a at or@o
+        ##1#1%
+      {%
+        \ekv at ifexp@split at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@a
+          #2\ekv at stop\ekv at ifexp@a at not@l
+      }%
+    \long\def\ekv at ifexp@l at not@a##1\ekv at stop
+      {\ekv at ifexp@l at not@a@{##1}\ekv at mark}%
+    \long\def\ekv at ifexp@l at not@a@
+        ##1##2\ekv at nil#2\ekv at stop\ekv at ifexp@a at not@l
+        ##3\ekv at stop\ekv at ifexp@o\ekv at stop#2\ekv at stop##4%
+      {\ekv at ifexp@done{##1}##2#1##3}%
+    \long\def\ekv at ifexp@a at not@l
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@l at not@a\ekv at stop
+        ##2\ekv at stop\ekv at ifexp@o\ekv at stop#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+    \long\def\ekv at ifexp@l at or@a at or@o##1\ekv at stop
+      {%
+        \ekv at ifexp@split at a@or at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@l at or@o
+          #1\ekv at stop\ekv at ifexp@o at not@l at or@a
+          ##1\ekv at stop\ekv at ifexp@l at or@a at or@o at i#2\ekv at stop{}%
+      }%
+    \long\def\ekv at ifexp@o at not@l at or@a
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@a at not@l at or@o\ekv at stop
+        ##2#2\ekv at stop##3%
+      {\ekv at ifexp@done{##1}\ekv at mark##2}%
+    \long\def\ekv at ifexp@a at not@l at or@o##1\ekv at stop
+      {\ekv at ifexp@a at not@l at or@o@{##1}\ekv at mark}
+    \long\def\ekv at ifexp@a at not@l at or@o@
+        ##1##2\ekv at nil##3#2\ekv at stop##4%
+      {\ekv at ifexp@done{##1}##2: ##3}%
+    \def\ekv at ifexp@l at or@a at or@o at i##1%
+      {%
+        \ekv at ifexp@l at or@a at or@o at ii
+          ##1\ekv at ifexp@l at or@a at or@o at iii
+          \ekv at ifexp@o at not@l at or@a
+        \ekv at ifexp@why
+      }%
+    \def\ekv at ifexp@l at or@a at or@o at ii
+        ##1\ekv at ifexp@o at not@l at or@a
+      {}%
+    \long\def\ekv at ifexp@l at or@a at or@o at iii
+        \ekv at ifexp@o at not@l at or@a\ekv at ifexp@why
+        ##1#2%
+      {\ekv at ifexp@l at or@a at or@o at iv{##1}\ekv at mark}%
+    \long\def\ekv at ifexp@l at or@a at or@o at iv
+        ##1##2\ekv at nil\ekv at stop\ekv at ifexp@a at not@l at or@o\ekv at stop
+        #2\ekv at stop##3##4#2\ekv at stop##5%
+      {\ekv at ifexp@done{##1}##2: ##4}%
+    \long\def\ekv at ifexp@why##1\ekv at stop
+      {%
+        \ekv at ifexp@split at l
+          ##1\ekv at nil\ekv at stop\ekv at ifexp@why at l
+          #2\ekv at stop\ekv at ifexp@why at a
+      }%
+    \long\def\ekv at ifexp@why at l##1\ekv at stop
+      {\ekv at ifexp@why at l@i{##1}\ekv at mark}
+    \long\def\ekv at ifexp@why at l@i
+        ##1##2\ekv at nil#2\ekv at stop\ekv at ifexp@why at a
+      {\ekv at ifexp@why at l@ii{##1}##2#1}
+    \long\def\ekv at ifexp@why at l@ii
+        ##1##2\ekv at nil#2\ekv at stop##3##4#2\ekv at stop##5%
+      {\ekv at ifexp@done{##1}##2: ##4}%
+    \long\def\ekv at ifexp@why at a
+        ##1\ekv at nil\ekv at stop\ekv at ifexp@why at l\ekv at stop
+        ##2\ekv at nil#2\ekv at stop##3##4#2\ekv at stop##5%
+      {\ekv at ifexp@done{##1}\ekv at mark##2: ##4}%
+    \ekv at exparg{\long\def\ekv at ifexp@done##1##2\ekv at nil}%
+      {%
+        \@firstofone
+          {\ekv at ifexp@done at test##1\ekv at nil\ekv at ifexp@panic} \ekv at nil{}%
+          ##2\ekv at stop\ekv at ifexp@done@{##1}{##2}\ekv at stop\@secondoftwo
+      }
+    \long\def\ekv at ifexp@done at test##1 ##2\ekv at nil##3##4##5##6\ekv at stop{##3}
+    \ekv at exparg{\long\def\ekv at ifexp@done@##1##2\ekv at stop\@secondoftwo##3}%
+      {\ekv at strip{##2}{##3{##1}}}%
+    \long\def\ekv at ifexp@panic##1\@secondoftwo##2##3{##3}
+  }
+\begingroup
+  \catcode`\~=13
+  \lccode`\~=`\:
+  \catcode`\z=11
+  \lccode`\z=`\:
+\lowercase{\endgroup
+\ekv at ifexp{~ }{z }}
+\begingroup
+\def\ekvset#1#2{%
+\endgroup
+\ekv at exparg{\long\def\ekvset##1##2}%
+  {%
+    \expandafter\expandafter\expandafter
+    \ekv at set\expandafter\csname\ekv at undefined@set{##1}\endcsname
+      \ekv at mark##2#1\ekv at stop#1{}%
+  }
+\long\def\ekv at set##1##2#1%
+  {%
+    \ekv at gobble@from at mark@to at stop##2\ekv at endset\ekv at stop
+    \ekv at set@other##1##2,\ekv at stop,%
+  }
+\long\def\ekv at endset\ekv at stop\ekv at set@other##1\ekv at mark\ekv at stop,\ekv at stop,##2%
+  {##2}
+\long\def\ekv at eq@other at or@active
+    ##1=##2\ekv at mark##3%
+    ##4#2##5\ekv at mark##6%
+  {##6##3##1\ekv at stop\ekv at mark##2}
+\long\def\ekv at eq@other##1=##2\ekv at mark##3{##3##1\ekv at stop\ekv at mark##2}
+\long\def\ekv at eq@active##1#2##2\ekv at mark##3{##3##1\ekv at stop\ekv at mark##2}
+\long\def\ekv at set@other##1##2,%
+  {%
+    \ekv at gobble@from at mark@to at stop##2\ekv at endset@other\ekv at stop
+    \ekv at eq@other at or@active
+      ##2\ekv at nil\ekv at mark\ekv at set@eq at other
+      =\ekv at mark\ekv at set@noeq
+      ##2\ekv at mark\ekv at set@eq at active
+      #2\ekv at mark{}%
+    ##1%
+    \ekv at mark
+  }
+\ekv at exparg{\long\def\ekv at set@next at other##1##2\ekv at set@other##3##4,}%
+  {\ekv at set@other{##3}{##4},}
+\ekv at exparg{\long\def\ekv at endset@other
+    \ekv at stop\ekv at eq@other at or@active
+    \ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at set@eq at other
+    =\ekv at mark\ekv at set@noeq
+    \ekv at mark\ekv at stop\ekv at mark\ekv at set@eq at active#2\ekv at mark##1%
+    ##2##3#1}%
+  {\ekv at set{##2}{##3}#1}
+\ekv at exparg{\long\def\ekv at set@eq at other##1\ekv at stop}%
+  {\ekv at strip@key{##1}\ekv at set@pair}
+\def\ekv at set@if at noeq##1\ekv at set@noeq{}
+\def\ekv at set@eq at active##1%
+  {\ekv at set@if at noeq##1\ekv at set@eq at active@\ekv at set@noeq\ekv at set@eq at mixed}
+\ekv at exparg{\long\def\ekv at set@eq at active@
+    \ekv at set@noeq\ekv at set@eq at mixed
+    ##1#2##2\ekv at mark
+    \ekv at set@eq at other\ekv at stop\ekv at mark#2\ekv at mark##3}%
+  {\ekv at strip@key{##1}\ekv at set@pair\ekv at mark##2}
+\long\def\ekv at set@eq at mixed##1\ekv at stop
+  {%
+    \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at mixed@a
+      #2\ekv at mark\ekv at set@eq at mixed@o
+  }
+\ekv at exparg{\long\def\ekv at set@eq at mixed@o
+    ##1\ekv at nil\ekv at mark\ekv at set@eq at mixed@a\ekv at stop\ekv at mark
+    ##2\ekv at nil#2\ekv at mark##3}%
+  {\ekv at strip@key{##1}\ekv at set@pair##2\ekv at nil}
+\ekv at exparg{\long\def\ekv at set@eq at mixed@a
+    ##1\ekv at stop
+    ##2\ekv at nil#2\ekv at mark\ekv at set@eq at mixed@o\ekv at mark
+    ##3#2\ekv at mark##4}%
+  {\ekv at strip@key{##1}\ekv at set@pair##2=##3}
+\ekv at expandedarg
+  {%
+    \long\def\ekv at set@noeq
+      ##1\ekv at nil\ekv at mark\ekv at set@eq at other\ekv at stop\ekv at mark
+  }%
+  {%
+    \ekv at unexpanded
+      {%
+        \ekv at ifblank@##1\ekv at stop\ekv at ifblank@gobbletrue
+          \ekv at stop\ekv at set@was at blank
+      }%
+    \ekv at unexpanded\expandafter{\ekv at strip@key{##1}\ekv at set@key}%
+  }
+\ekv at exparg{\long\expandafter\def\expandafter\ekv at set@was at blank
+    \ekv at strip@key{\ekv at mark##1}\ekv at set@key
+    ##2##3,}%
+  {\ekv at set@other{##2}{##3},}
+\long\def\ekvbreak##1##2\ekv at stop#1##3{##1}
+\long\def\ekvbreakPreSneak ##1##2\ekv at stop#1##3{##1##3}
+\long\def\ekvbreakPostSneak##1##2\ekv at stop#1##3{##3##1}
+\long\def\ekvsneak##1##2\ekv at stop#1##3{##2\ekv at stop#1{##3##1}}
+\long\def\ekvsneakPre##1##2\ekv at stop#1##3{##2\ekv at stop#1{##1##3}}
+\long\def\ekvparse##1##2##3%
+  {%
+    \ekv at unexpanded\ekv at expanded
+      {{\ekv at parse{##1}{##2}\ekv at mark##3#1\ekv at stop#1}}%
+  }
+\long\def\ekv at parse##1##2##3#1%
+  {%
+    \ekv at gobble@from at mark@to at stop##3\ekv at endparse\ekv at stop
+    \ekv at parse@other{##1}{##2}##3,\ekv at stop,%
+  }
+\long\def\ekv at endparse\ekv at stop\ekv at parse@other##1\ekv at mark\ekv at stop,\ekv at stop,%
+  {}
+\long\def\ekv at parse@other##1##2##3,%
+  {%
+    \ekv at gobble@from at mark@to at stop##3\ekv at endparse@other\ekv at stop
+    \ekv at eq@other at or@active
+      ##3\ekv at nil\ekv at mark\ekv at parse@eq at other
+      =\ekv at mark\ekv at parse@noeq
+      ##3\ekv at mark\ekv at parse@eq at active#2\ekv at mark{}%
+    {##1}{##2}%
+    \ekv at mark
+  }
+\ekv at exparg{\long\def\ekv at endparse@other
+    \ekv at stop\ekv at eq@other at or@active
+    \ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at parse@eq at other
+    =\ekv at mark\ekv at parse@noeq
+    \ekv at mark\ekv at stop\ekv at mark\ekv at parse@eq at active#2\ekv at mark##1%
+    ##2##3##4#1}%
+  {\ekv at parse{##2}{##3}{##4}#1}
+\ekv at exparg{\long\def\ekv at parse@eq at other##1\ekv at stop}%
+  {\ekv at strip{##1}\ekv at parse@pair}%
+\def\ekv at parse@if at noeq##1\ekv at parse@noeq{}
+\def\ekv at parse@eq at active##1%
+  {%
+    \ekv at parse@if at noeq##1\ekv at parse@eq at active@\ekv at parse@noeq
+    \ekv at parse@eq at mixed
+  }
+\ekv at exparg{\long\def\ekv at parse@eq at active@
+    \ekv at parse@noeq\ekv at parse@eq at mixed
+    ##1#2##2\ekv at mark
+    \ekv at parse@eq at other\ekv at stop\ekv at mark#2\ekv at mark##3}%
+  {\ekv at strip{##1}\ekv at parse@pair\ekv at mark##2}
+\long\def\ekv at parse@eq at mixed##1\ekv at stop
+  {%
+    \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at mixed@a
+      #2\ekv at mark\ekv at parse@eq at mixed@o
+  }
+\ekv at exparg{\long\def\ekv at parse@eq at mixed@a
+    ##1\ekv at stop
+    ##2\ekv at nil#2\ekv at mark\ekv at parse@eq at mixed@o\ekv at mark
+    ##3#2\ekv at mark##4}%
+  {\ekv at strip{##1}\ekv at parse@pair##2=##3}
+\ekv at exparg{\long\def\ekv at parse@eq at mixed@o
+    ##1\ekv at nil\ekv at mark\ekv at parse@eq at mixed@a\ekv at stop\ekv at mark
+    ##2\ekv at nil#2\ekv at mark##3}%
+  {\ekv at strip{##1}\ekv at parse@pair##2\ekv at nil}
+\ekv at expandedarg
+  {%
+    \long\def\ekv at parse@noeq
+      ##1\ekv at nil\ekv at mark\ekv at parse@eq at other\ekv at stop\ekv at mark
+  }%
+  {%
+    \ekv at unexpanded
+      {%
+        \ekv at ifblank@##1\ekv at stop\ekv at ifblank@gobbletrue
+          \ekv at stop\ekv at parse@was at blank
+      }%
+    \ekv at unexpanded\expandafter{\ekv at strip{##1}\ekv at parse@key}%
+  }
+\ekv at exparg{\long\expandafter\def\expandafter\ekv at parse@was at blank
+    \ekv at strip{\ekv at mark##1}\ekv at parse@key
+    ##2##3##4,}%
+  {\ekv at parse@other{##2}{##3}{##4},}
+\ekv at exparg{\long\def\ekv at parse@pair##1##2\ekv at nil}%
+  {\ekv at strip{##2}\ekv at parse@pair@{##1}}
+\ekv at exparg{\long\def\ekv at parse@pair@##1##2##3##4}%
+  {%
+    \ekv at ifexp{##2}%
+      {\ekv at expansion@parse at pair{##1}{##4}}%
+      {\ekv at unexpanded{##4{##2}{##1}}}%
+    \ekv at parse@other{##3}{##4}%
+  }
+\ekv at exparg{\long\def\ekv at parse@key##1##2}%
+  {%
+    \ekv at ifexp{##1}%
+      {\ekv at expansion@parse at key{##2}}%
+      {\ekv at unexpanded{##2{##1}}}%
+    \ekv at parse@other{##2}%
+  }
+}
+\catcode`\,=13
+\catcode`\==13
+\ekvset,=
+\edef\ekvsetSneaked
+  {%
+    \ekv at unexpanded{\ekvsneak{#2}}%
+    \ekv at unexpanded\expandafter{\ekvset{#1}{#3}}%
+  }
+\ekv at expargtwice{\long\def\ekvsetSneaked#1#2#3}{\ekvsetSneaked}
+\ekv at exparg{\def\ekvchangeset#1}%
+  {%
+    \expandafter\expandafter\expandafter
+    \ekv at changeset\expandafter\csname\ekv at undefined@set{#1}\endcsname\ekv at empty
+  }
+\long\def\ekv at changeset#1#2\ekv at set@other#3{#2\ekv at set@other#1}
+\def\ekvmorekv#1%
+  {%
+    \long\def\ekvmorekv##1%
+      {%
+        \expandafter\ekv at morekv\ekv at expanded
+          {{\ekv at morekv@loop\ekv at empty##1\ekv at stop\ekv at morekv@done#1}}%
+        \ekv at empty
+      }%
+    \long\def\ekv at parse@more##1\@gobble##2%
+      {%
+        \expandafter\ekv at parse@more@\ekv at expanded
+          {{\ekv at morekv@loop\ekv at empty##1\ekv at stop\ekv at morekv@done#1}}%
+      }%
+    \long\def\ekv at parse@more@##1\ekv at parse@other##2##3\ekv at mark
+      {\ekv at parse@other{##2}{##3}\ekv at mark##1,}%
+    \long\def\ekv at morekv##1##2\ekv at set@other##3\ekv at mark
+      {##2\ekv at set@other##3\ekv at mark##1,}
+    \long\def\ekv at morekv@loop##1#1%
+      {\ekv at morekv@wrap##1\ekv at stop,\ekv at morekv@loop\ekv at empty}%
+    \long\def\ekv at morekv@wrap##1\ekv at stop{\ekv at unexpanded\expandafter{##1}}%
+    \def\ekv at morekv@done\ekv at stop,\ekv at morekv@loop\ekv at empty{}%
+  }
+\begingroup\catcode`\,=13 \@firstofone{\endgroup\ekvmorekv,}
+\protected\def\ekv at def@expansion at rule#1#2#3#4%
+  {%
+    \long\expandafter\def\csname ekv at expansion@rule@#1\endcsname##1#2%
+      {#3\ekv at expansion@rule@#4}%
+  }
+\protected\def\ekv at def@expansion at rule@ea#1#2%
+  {\ekv at def@expansion at rule{#1}{#2}\expandafter}
+\long\def\ekv at expansion@csname#1\ekv at stop
+  {%
+    ekv at expansion@rule@%
+    \ifcsname ekv at expansion@rule@#1\endcsname
+      #1%
+    \else
+      \ekv at err@undefined at expansion{#1}%
+    \fi
+  }
+\long\def\ekv at expansion@rule@#1#2%
+  {\csname\expandafter\ekv at expansion@csname\string#2\ekv at stop\endcsname{#1}}
+\ekv at exparg
+  {%
+    \long\expandafter
+    \def\csname ekv at expansion@rule@\string\ekv at mark\endcsname
+      #1\ekv at stop#2#3#4#5%
+  }%
+  {%
+    \romannumeral\ekv at exparg{\expandafter\ekv at zero\ekv at ifempty{#3}{#5{#2}{#1}}}%
+      {\ekv at ifempty{#2}{#4{#1}}{\ekv at err@val at no@reinsert{#2}}}%
+  }
+\ekv at def@expansion at rule@ea{o}{}{\expandafter{#1}}
+\ekv at def@expansion at rule@ea{e}{}{\ekv at expanded{{#1}}}
+\ekv at def@expansion at rule@ea{c}{}{\csname#1\endcsname}
+\ekv at def@expansion at rule@ea{f}{}{\expandafter{\romannumeral`\^^@#1}}
+\ekv at exparg{\ekv at def@expansion at rule{s}{}}{\ekv at strip{\ekv at mark#1}}{}
+\ekv at def@expansion at rule{b}{}{}{{{#1}}}
+\ekv at def@expansion at rule{\string\r}{#2\ekv at stop#3#4}{}{{#1}#2\ekv at stop{#3}{#4r}}
+\ekv at def@expansion at rule@ea{g}{}{\expandafter{\@gobble#1}}
+\ekv at def@expansion at rule{p}{#2}{}{{#2#1}}
+\ekv at def@expansion at rule{P}{#2}{}{{#1#2}}
+\long\def\ekv at expansion@rule at V#1%
+  {%
+    \ifx\relax#1\ekv at err@erroneous at variable{#1}\ekv at expansion@@clean at V\fi
+    \ekv at expansion@@V{#1}%
+  }
+\ekv at expandedarg{\long\def\ekv at expansion@rule at v#1}%
+  {%
+    \ekv at unexpanded{\ekv at ifdefined{#1}%
+      {\expandafter\ekv at expansion@@V\csname#1\endcsname}}%
+      {%
+        \ekv at unexpanded{\expandafter\ekv at err@erroneous at variable\ekv at expanded}%
+          {{\expandafter\@gobble\string\\#1}}%
+        \ekv at unexpanded{\ekv at expansion@rule@}{}%
+      }%
+  }
+\ekv at exparg{\long\def\ekv at expansion@rule at r#1#2\ekv at stop#3#4}%
+  {\ekv at expansion@rule at v{#1}#2\ekv at stop{#3}{#4r}}
+\ekv at exparg{\long\def\ekv at expansion@rule at R#1#2\ekv at stop#3#4}%
+  {\ekv at expansion@rule at V{#1}#2\ekv at stop{#3}{#4r}}
+\long\def\ekv at expansion@@V#1%
+  {%
+    \expandafter\ifx\noexpand#1#1%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+    {\expandafter\ekv at expansion@rule@\expandafter{\the#1}}%
+    {\expandafter\ekv at expansion@rule@\expandafter{#1}}%
+  }
+\long\def\ekv at expansion@@clean at V\fi\ekv at expansion@@V#1%
+  {\fi\ekv at expansion@rule@{}}
+\ekv at def@expansion at rule{\string\key}{#2#3\ekv at stop#4}%
+  {}{{#4}#2\ekv at key@after\ekv at stop{#1}{}{#3}}
+\ekv at exparg{\ekv at def@expansion at rule{\string\ekv at key@after}{\ekv at stop#2#3#4}}%
+  {\ekv at ifempty{#3}{}\ekv at err@key at no@reinsert}
+  {{#2}#4\ekv at stop{#1}}
+\ekv at if@lastnamedcs
+  {%
+    \long\def\ekv at set@pair#1\ekv at mark#2#3\ekv at nil#4%
+      {%
+        \ifcsname#4{#1}\endcsname\expandafter\ekv at set@pair@\lastnamedcs\fi
+        \ekv at set@pair at undefined{#3}{#1}{#2}%
+        \ekv at set@other#4%
+      }
+    \ekv at exparg{\long\def\ekv at set@pair at undefined#1#2#3\ekv at set@other#4}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\expandafter\ekv at zero\ekv at ifexp{#3}}%
+          {\ekv at strip{#1}\ekv at expansion@set at pair}%
+          {%
+            \ifcsname#4{}u\endcsname\expandafter\ekv at set@pair at u\lastnamedcs\fi
+            \ekv at set@pair at no@u{#1}{#2}{#3}%
+          }%
+        \ekv at set@other#4%
+      }
+  }
+  {%
+    \long\def\ekv at set@pair#1\ekv at mark#2#3\ekv at nil#4%
+      {%
+        \ifcsname#4{#1}\endcsname
+          \expandafter\ekv at set@pair@\csname#4{#1}\endcsname
+        \fi
+        \ekv at set@pair at undefined{#3}{#1}{#2}%
+        \ekv at set@other#4%
+      }
+    \ekv at exparg{\long\def\ekv at set@pair at undefined#1#2#3\ekv at set@other#4}%
+      {%
+        \romannumeral
+        \ekv at exparg
+          {\expandafter\ekv at zero\ekv at ifexp{#3}}%
+          {\ekv at strip{#1}\ekv at expansion@set at pair}%
+          {%
+            \ifcsname#4{}u\endcsname
+              \expandafter\ekv at set@pair at u\csname#4{}u\endcsname
+            \fi
+            \ekv at set@pair at no@u{#1}{#2}{#3}%
+          }%
+        \ekv at set@other#4%
+      }
+  }
+\ekv at expandedarg{\long\def\ekv at set@pair@#1\fi\ekv at set@pair at undefined#2}%
+  {%
+    \ekv at unexpanded{\fi\ifx#1\relax\ekv at set@pair at relax\fi}%
+    \ekv at unexpanded\expandafter{\ekv at strip{#2}#1\ekv at set@next at other}%
+  }
+\ekv at expandafter{\long\def\ekv at set@pair at relax\fi}%
+    \ekv at strip{#1}#2\ekv at set@next at other
+  {\fi\ekv at set@pair at undefined{#1}}
+\ekv at expandedarg{\long\def\ekv at set@pair at u#1\fi\ekv at set@pair at no@u#2}%
+  {%
+    \ekv at unexpanded
+      {%
+        \fi
+        \ifx\relax#1%
+          \ekv at set@pair at u@relax
+        \fi
+      }%
+    \ekv at unexpanded\expandafter{\ekv at strip{#2}#1}%
+  }
+\ekv at expandafter{\long\def\ekv at set@pair at u@relax\fi}\ekv at strip{\ekv at mark#1}#2%
+  {\fi\ekv at set@pair at no@u.}
+\long\def\ekv at set@pair at no@u#1#2#3\ekv at set@other#4%
+  {%
+    \ekv at ifdefined{#4{#2}N}%
+      \ekv at err@noarg
+      \ekv at err@unknown
+        #4{#2}{#3}%
+    \ekv at set@other#4%
+  }
+\ekv at if@lastnamedcs
+  {%
+    \long\def\ekv at set@key#1\ekv at mark#2#3%
+      {%
+        \ifcsname#3{#1}N\endcsname\expandafter\ekv at set@key@\lastnamedcs\fi
+        \ekv at set@key at undefined{#1}{#2}%
+        \ekv at set@other#3%
+      }
+    \ekv at exparg{\long\def\ekv at set@key at undefined#1#2\ekv at set@other#3}%
+      {%
+        \ekv at ifexp{#2}%
+          \ekv at expansion@set at key
+          {%
+            \ifcsname#3{}uN\endcsname\expandafter\ekv at set@key at u\lastnamedcs\fi
+            \ekv at set@key at no@u{#1}{#2}%
+          }%
+        \ekv at set@other#3%
+      }
+  }
+  {%
+    \long\def\ekv at set@key#1\ekv at mark#2#3%
+      {%
+        \ifcsname#3{#1}N\endcsname
+          \expandafter\ekv at set@key@\csname#3{#1}N\endcsname
+        \fi
+        \ekv at set@key at undefined{#1}{#2}%
+        \ekv at set@other#3%
+      }
+    \ekv at exparg{\long\def\ekv at set@key at undefined#1#2\ekv at set@other#3}%
+      {%
+        \ekv at ifexp{#2}%
+          \ekv at expansion@set at key
+          {%
+            \ifcsname#3{}uN\endcsname
+              \expandafter\ekv at set@key at u\csname#3{}uN\endcsname
+            \fi
+            \ekv at set@key at no@u{#1}{#2}%
+          }%
+        \ekv at set@other#3%
+      }
+  }
+\long\def\ekv at set@key@#1\fi\ekv at set@key at undefined
+  {\fi\ifx#1\relax\ekv at set@key at relax\fi#1\ekv at set@next at other}
+\long\def\ekv at set@key at relax\fi#1\ekv at set@next at other{\fi\ekv at set@key at undefined}
+\long\def\ekv at set@key at u#1\fi\ekv at set@key at no@u
+  {\fi\ifx\relax#1\ekv at set@key at u@relax\fi#1}
+\def\ekv at set@key at u@relax\fi#1{\fi\ekv at set@key at no@u}
+\long\def\ekv at set@key at no@u#1#2\ekv at set@other#3%
+  {%
+    \ekv at ifdefined{#3{#1}}%
+      \ekv at err@reqval
+      \ekv at err@unknown
+        #3{#1}{#2}%
+    \ekv at set@other#3%
+  }
+\long\def\ekv at expansion@set at key#1#2#3%
+  {%
+    \ekv at expansion@rule@{#2}#1\ekv at mark\ekv at stop{}{}\ekvmorekv
+    \ekv at expansion@set at key@
+  }
+\long\def\ekv at expansion@set at key@#1#2\ekv at set@other#3%
+  {\expandafter\ekv at set@key\detokenize{#2}\ekv at mark{#2}#3}
+\long\def\ekv at expansion@set at pair#1#2#3#4%
+  {%
+    \ekv at expansion@rule@{#1}#2\ekv at mark\ekv at stop{#3}{}\ekvmorekv
+    \ekv at expansion@set at pair@
+  }
+\long\def\ekv at expansion@set at pair@#1#2\ekv at set@other#3%
+  {\expandafter\ekv at set@pair\detokenize{#1}\ekv at mark{#1}\ekv at mark{#2}\ekv at nil#3}
+\long\def\ekv at expansion@parse at key#1#2#3#4%
+  {%
+    \ekv at expansion@rule@{#3}#2\ekv at mark\ekv at stop{}{}\ekv at parse@more
+    \ekv at expansion@parse at key@\@gobble{#1}%
+  }
+\long\def\ekv at expansion@parse at key@#1#2\@gobble#3{\ekv at unexpanded{#3{#2}}}
+\long\def\ekv at expansion@parse at pair#1#2#3#4#5%
+  {%
+    \ekv at expansion@rule@{#1}#3\ekv at mark\ekv at stop{#4}{}\ekv at parse@more
+    \ekv at expansion@parse at pair@\@gobble{#2}%
+  }
+\long\def\ekv at expansion@parse at pair@#1#2\@gobble#3{\ekv at unexpanded{#3{#1}{#2}}}
+\ekv at expargtwice{\protected\def\ekvsetdef#1#2}%
+  {%
+    \romannumeral
+    \ekv at exparg{\ekv at zero\ekv at exparg{\def#1##1}}%
+      {\ekvset{#2}{##1}}%
+  }
+\ekv at expargtwice{\protected\def\ekvsetSneakeddef#1#2}%
+  {%
+    \romannumeral
+    \ekv at exparg{\ekv at zero\ekv at exparg{\long\def#1##1##2}}%
+      {\ekvsetSneaked{#2}{##1}{##2}}%
+  }
+\ekv at expargtwice{\protected\def\ekvsetdefSneaked#1#2#3}%
+  {%
+    \romannumeral
+    \ekv at exparg{\ekv at zero\ekv at exparg{\long\def#1##1}}%
+      {\ekvsetSneaked{#2}{#3}{##1}}%
+  }
+\begingroup
+\catcode`\^^@=2
+\@firstofone{\endgroup
+  \def\ekv at alignsafe{\romannumeral\iffalse{\fi`^^@ }
+}
+\def\ekv at endalignsafe{\ifnum`{=\ekv at zero}\fi}
+\begingroup
+\def\ekvoptarg#1#2{%
+\endgroup
+\def\ekvoptarg{#1\ekv at optarg@a}
+\long\def\ekv at optarg@a##1##2##3%
+  {%
+    \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optarg@b\ekv at mark[\ekv at mark
+    #2%
+    \@firstofone{ ##1}{##2}{##3}%
+  }%
+\def\ekvoptargTF{#1\ekv at optargTF@a}
+\long\def\ekv at optargTF@a##1##2##3%
+  {%
+    \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optargTF@b{##1}\ekv at mark[\ekv at mark
+    #2%
+    \@firstofone{ ##2}{##3}%
+  }
+\long\def\ekv at optarg@b\ekv at mark[\ekv at mark\ifnum`##1\fi\@firstofone##2##3##4##5]%
+  {#2##2{##5}}
+\long\def\ekv at optargTF@b
+    ##1\ekv at mark[\ekv at mark\ifnum`##2\fi\@firstofone##3##4##5]%
+  {#2 ##1{##5}}
+}
+\ekv at exparg
+  {%
+    \expandafter\ekv at strip\expandafter
+      {\expandafter\ekv at mark\ekv at alignsafe}%
+      \ekvoptarg
+  }%
+  \ekv at endalignsafe
+\long\def\ekv at optarg@if#1\ekv at mark[\ekv at mark{}
+\long\def\ekv at ifstar#1#2#3%
+  {%
+    \if*\string#3%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+      {#1}%
+      {#2{#3}}%
+  }
+\protected\long\def\ekvcompile
+  {%
+    \ekv at alignsafe
+    \ekv at ifstar{\ekv at compile{}}{\ekv at compile{\expandafter\expandafter}}%
+  }
+\def\ekv at compile#1#2#3#{\ekv at compile@{#1}{#2#3}}
+\def\ekv at compile@#1#2#3{#2#3}
+\ekv at exparg{\protected\long\def\ekv at compile@#1#2#3#4}%
+  {%
+    \expandafter\ekv at expanded\expandafter
+      {%
+        \romannumeral\ekv at expargtwice{\ekv at zero\def\ekv at unexpanded{#2}}%
+          {%
+            \expandafter\ekv at compile@
+            \ekvparse
+              {\ekv at compile@key{#1}{#3}}%
+              {\ekv at compile@pair{#1}{#3}}%
+              {#4}%
+          }%
+      }%
+    \ekv at endalignsafe
+  }
+\ekv at exparg{\long\def\ekv at compile@key#1#2#3}%
+  {%
+    \ekvifdefinedNoVal{#2}{#3}%
+      {\ekv at unexpanded#1\expandafter{\csname\ekv at name{#2}{#3}N\endcsname}}%
+      {%
+        \ekv at ifdefined{\ekv at name{#2}{}uN}
+          {%
+            \ekv at unexpanded#1\expandafter
+              {%
+                \csname\ekv at name{#2}{}uN\expandafter\endcsname
+                  \expandafter{\detokenize{#3}}{#3}%
+              }%
+          }%
+          {%
+            \ekvifdefined{#2}{#3}%
+              {\ekv at err{missing value for `#3' in set `#2'}}%
+              {\ekv at err{unknown key `#3' in set `#2'}}%
+          }%
+      }%
+  }
+\ekv at exparg{\long\def\ekv at compile@pair#1#2#3#4}%
+  {%
+    \ekvifdefined{#2}{#3}%
+      {\ekv at unexpanded#1\expandafter{\csname\ekv at name{#2}{#3}\endcsname{#4}}}%
+      {%
+        \ekv at ifdefined{\ekv at name{#2}{}u}%
+          {%
+            \ekv at unexpanded#1\expandafter
+              {%
+                \csname\ekv at name{#2}{}u\ekv at expanded{\endcsname
+                  {\ekv at unexpanded{#4}}{\detokenize{#3}}}{#3}%
+              }%
+          }%
+          {%
+            \ekvifdefinedNoVal{#2}{#3}%
+              {\ekv at err{unwanted value for `#3' in set `#2'}}%
+              {\ekv at err{unknown key `#3' in set `#2'}}%
+          }%
+      }%
+  }
+\def\ekv at err@cleanup\par{}
+\def\ekv at err@collect#1%
+  {%
+    \def\ekv at err@collect##1\par##2%
+      {%
+        \expandafter
+        \ekv at err@cleanup
+        #1! ##2 Error: ##1\par
+      }%
+    \def#1##1\thanks at jfbu{}%
+  }
+\def\ekverr{ }
+\expandafter\ekv at err@collect\csname <an-expandable-macro>^^J%
+  completed due to above exception. \ekverr If the error^^J%
+  summary is \ekverr not comprehensible \ekverr see the package^^J%
+  documentation.^^J%
+  I will try to recover now. \ekverr If you're in inter-^^J%
+  active mode hit <return> \ekverr at the ? prompt and I^^J%
+  continue hoping recovery\endcsname
+\long\def\ekverr#1#2{\expandafter\ekv at err@collect\detokenize{#2}\par{#1}}
+\ekv at exparg{\long\def\ekv at err#1}{\ekverr{expkv}{#1}}
+\protected\long\def\ekv at errm#1{\errmessage{expkv Error: #1}}
+\long\def\ekv at err@common #1#2{\expandafter\ekv at err@common@\string#2{#1}}
+\ekv at exparg{\long\def\ekv at err@common@#1`#2' #3.#4#5}%
+  {\ekv at err{#4 `#5' in set `#2'}}
+\ekv at exparg{\long\def\ekv at err@unknown#1#2}{\ekv at err@common{unknown key}{#1}}
+\ekv at exparg{\long\def\ekv at err@noarg#1#2}
+  {\ekv at err@common{unwanted value for}{#1}}
+\ekv at exparg{\long\def\ekv at err@reqval#1#2}%
+  {\ekv at err@common{missing value for}{#1}}
+\ekv at exparg{\long\def\ekv at err@redirect at kv@notfound#1#2#3\ekv at stop}%
+  {\ekv at err{no key `#2' in sets #3}}
+\ekv at exparg{\def\ekv at err@redirect at k@notfound#1#2\ekv at stop}%
+  {\ekv at err{no NoVal key `#1' in sets #2}}
+\ekv at exparg{\def\ekv at err@undefined at expansion#1\fi}%
+  {\expandafter\fi\ekv at err{Undefined expansion rule `#1'}}%
+\ekv at exparg{\def\ekv at err@erroneous at variable#1}%
+  {\ekv at err{Erroneous variable `#1' used}}
+\ekv at exparg{\def\ekv at err@key at no@reinsert}%
+  {\ekv at err{Reinsertion in \key expansion forbidden}}
+\ekv at exparg{\def\ekv at err@val at no@reinsert#1}%
+  {\ekv at err{Reinsertion with key `#1' forbidden}}
+\catcode`\@=\ekv at tmp
+%% 
+%%
+%% End of file `expkv.tex'.


Property changes on: trunk/Master/texmf-dist/tex/generic/expkv-bundle/expkv.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-cs.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-cs.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-cs.sty	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,67 @@
+%%
+%% This is file `expkv-cs.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-cs.dtx  (with options: `pkg')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\RequirePackage{expkv-pop}
+\def\ekvc at tmp
+  {%
+    \ProvidesFile{expkv-cs.tex}%
+      [%
+        \ekvcDate\space v\ekvcVersion\space
+        define expandable key=val macros using expkv%
+      ]%
+  }
+\input{expkv-cs.tex}
+\ProvidesPackage{expkv-cs}%
+  [%
+    \ekvcDate\space v\ekvcVersion\space
+    define expandable key=val macros using expkv%
+  ]
+%% 
+%%
+%% End of file `expkv-cs.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-cs.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-def.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-def.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-def.sty	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,61 @@
+%%
+%% This is file `expkv-def.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-def.dtx  (with options: `pkg')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\RequirePackage{expkv-pop}
+\def\ekvd at tmp
+  {%
+    \ProvidesFile{expkv-def.tex}%
+      [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]%
+  }
+\input{expkv-def.tex}
+\ProvidesPackage{expkv-def}%
+  [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]
+%% 
+%%
+%% End of file `expkv-def.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-def.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt-2020-10-10.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt-2020-10-10.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt-2020-10-10.sty	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,288 @@
+%%
+%% This is file `expkv-opt-2020-10-10.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-opt-2020-10-10.dtx  (with options: `pkg')
+%% 
+%% --------------------------------------------------------------
+%% expkv-opt -- parse class and package options with expkv
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% --------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the file  expkv-opt.dtx
+%% and the derived files           expkv-opt.pdf
+%%                                 expkv-opt.sty
+%% and the file                    expkv-opt-2020-10-10.dtx
+%% and the derived file            expkv-opt-2020-10-10.sty
+%% 
+\newcommand*\ekvoVersion{0.1c}
+\newcommand*\ekvoDate{2020-10-10}
+\ProvidesPackage{expkv-opt}
+  [%
+    \ekvoDate\space v\ekvoVersion\space
+    parse class and package options with expkv%
+  ]
+\RequirePackage{expkv}
+\protected\long\def\ekvo at CurrentOption@loop#1#2%
+  {%
+    \ekvo at CurrentOption@loop@#2\ekv at set@other\ekv at mark#1,\ekv at stop,\ekvo at tail
+  }
+\long\def\ekvo at CurrentOption@loop@#1\ekv at set@other#2,%
+  {%
+    \ekv at gobble@from at mark@to at stop#2\ekvo at end@loop\ekv at stop
+    \ekv at ifblank{#2}%
+      {}%
+      {%
+        \edef\CurrentOption{\unexpanded\expandafter{\ekv at gobble@mark#2}}%
+        #1{#2}%
+      }%
+    \ekvo at CurrentOption@loop@#1\ekv at set@other\ekv at mark
+  }
+\long\def\ekvo at end@loop#1\ekvo at tail{}
+\def\ekvo at ifx@TF#1#2{\ifx#1#2\ekv at fi@firstoftwo\fi\@secondoftwo}
+\def\ekvo at ifx@F#1#2{\ifx#1#2\ekv at fi@gobble\fi\@firstofone}
+\protected\def\ekvo at do@with at set#1#2%
+  {%
+    \ekvifdefinedset{#1}%
+      {%
+        \expandafter
+        \let\expandafter\ekvo at name\csname\ekv at undefined@set{#1}\endcsname
+        \def\ekvo at setname{#1}%
+        #2%
+      }%
+      {\ekvo at err@undefined at set{#1}}%
+  }
+\protected\long\def\ekvo at handle@undefined at k@pkg#1%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {\ekvo at err@value at required{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+\def\ekvo at handle@undefined at kv@pkg#1#2%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {\ekvo at err@value at forbidden{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+\long\def\ekvo at addto@unused at one#1{\ekvo at addto@list\@unusedoptionlist}
+\long\def\ekvo at addto@unused at two#1#2{\ekvo at addto@list\@unusedoptionlist}
+\long\def\ekvo at rmfrom@unused at one#1{\ekvo at rmfrom@list\@unusedoptionlist}
+\long\def\ekvo at rmfrom@unused at two#1#2{\ekvo at rmfrom@list\@unusedoptionlist}
+\protected\def\ekvo at set@handlers at local
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \ifx\@currext\@clsextension
+          \ifx\@classoptionslist\relax
+            \let\ekvo at handle@undefined at k\@gobble
+            \let\ekvo at handle@undefined at kv\@gobbletwo
+          \else
+            \expandafter
+            \ifx\csname opt@\@currname.\@currext\endcsname\@classoptionslist
+              \let\ekvo at handle@undefined at k\ekvo at addto@unused at one
+              \let\ekvo at handle@undefined at kv\ekvo at addto@unused at two
+            \else
+              \let\ekvo at handle@undefined at k\@gobble
+              \let\ekvo at handle@undefined at kv\@gobbletwo
+            \fi
+          \fi
+        \else
+          \let\ekvo at handle@undefined at k\ekvo at handle@undefined at k@pkg
+          \let\ekvo at handle@undefined at kv\ekvo at handle@undefined at kv@pkg
+        \fi
+      }%
+  }
+\protected\def\ekvo at set@handlers at global
+  {%
+    \unless\ifx\@unusedoptionlist\@empty
+      \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+      \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+    \fi
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+\protected\def\ekvo at set@handlers at unusedglobal
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\ekvo at addto@unused at one
+        \let\ekvo at handle@undefined at kv\ekvo at addto@unused at two
+        \let\@unusedoptionlist\@empty
+        \@gobbletwo
+      }%
+    \@firstofone
+      {%
+        \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+        \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+      }%
+  }
+\protected\def\ekvo at set@handlers at list
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+\let\ekvo at if@need at handlers\@firstofone
+\protected\long\def\ekvo at dont@need at handlers#1%
+  {%
+    \let\ekvo at if@need at handlers\@firstofone
+  }%
+\let\ekvo at handle@defined at k\@gobble
+\let\ekvo at handle@defined at kv\@gobbletwo
+\protected\def\ekvo at process@common#1#2#3%
+  {%
+    #1{\ekvo at do@with at set{#3}{#2}}%
+  }
+\protected\def\ekvo at process@list#1%
+  {%
+    \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at parse
+  }
+\protected\long\def\ekvo at parse#1%
+  {%
+    \ekv at expanded
+      {\ekv at unexpanded{\ekvparse\ekvo at set@k\ekvo at set@kv}\expandafter}%
+      \expandafter{\ekv at gobble@mark#1}\ekvo at tail
+  }
+\protected\def\ekvo at set@k#1#2\ekvo at tail
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {%
+        \ekvo at handle@defined at k{#1}%
+        \csname\ekvo at name{#1}N\endcsname
+      }%
+      {\ekvo at handle@undefined at k{#1}}%
+  }
+\protected\def\ekvo at set@kv#1#2#3\ekvo at tail
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {%
+        \ekvo at handle@defined at kv{#1}{#2}%
+        \csname\ekvo at name{#1}\endcsname{#2}%
+      }%
+      {\ekvo at handle@undefined at kv{#1}{#2}}%
+  }
+\protected\def\ekvo at addto@list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      {\let#1\CurrentOption}%
+      {%
+        \edef#1%
+          {%
+            \unexpanded\expandafter{#1},%
+            \unexpanded\expandafter{\CurrentOption}%
+          }%
+      }%
+  }
+\protected\def\ekvo at rmfrom@list#1%
+  {%
+    \ekvo at ifx@F#1\@empty
+      {%
+        \let\ekvo at tmp@list\@empty
+        \let\ekvo at curropt\CurrentOption
+        \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at rmfrom@list@
+        \let\CurrentOption\ekvo at curropt
+        \let#1\ekvo at tmp@list
+      }%
+  }
+\protected\long\def\ekvo at rmfrom@list@#1%
+  {%
+    \ekvo at ifx@F\CurrentOption\ekvo at curropt
+      {\ekvo at addto@list\ekvo at tmp@list}%
+  }
+\protected\def\ekvo at err@undefined at key#1%
+  {%
+    \PackageError{expkv-opt}{Undefined key `#1' in set `\ekvo at setname'}{}%
+  }
+\protected\def\ekvo at err@value at required#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Value required for key `#1' in set `\ekvo at setname'}%
+      {}%
+  }
+\protected\def\ekvo at err@value at forbidden#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Value forbidden for key `#1' in set `\ekvo at setname'}%
+      {}%
+  }
+\protected\def\ekvo at err@undefined at set#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Undefined set `#1'}%
+      {The set for which you try to parse options isn't defined in expkv.}%
+  }
+\protected\def\ekvoProcessLocalOptions
+  {%
+    \ekvo at process@common
+      {\ekv at ifdefined{opt@\@currname.\@currext}\@firstofone\@gobble}%
+      {%
+        \ekvo at set@handlers at local
+        \expandafter
+        \ekvo at process@list\csname opt@\@currname.\@currext\endcsname
+        \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+      }%
+  }
+\protected\def\ekvoProcessGlobalOptions
+  {%
+    \ekvo at process@common{\ekvo at ifx@F\@classoptionslist\relax}%
+      {%
+        \ekvo at set@handlers at global
+        \ekvo at process@list\@classoptionslist
+        \let\ekvo at handle@defined at k\@gobble
+        \let\ekvo at handle@defined at kv\@gobbletwo
+      }%
+  }
+\protected\def\ekvoProcessUnusedGlobalOptions
+  {%
+    \ekvo at process@common{\ekvo at ifx@F\@unusedoptionlist\@empty}%
+      {%
+        \let\ekvo at tmp@list\@unusedoptionlist
+        \ekvo at set@handlers at unusedglobal
+        \ekvo at process@list\ekvo at tmp@list
+        \let\ekvo at handle@defined at k\@gobble
+        \let\ekvo at handle@defined at kv\@gobbletwo
+      }%
+  }
+\protected\def\ekvoProcessOptionsList#1%
+  {%
+    \ekvo at process@common{\ekvo at ifx@F#1\@empty}%
+      {%
+        \ekvo at set@handlers at list
+        \ekvo at process@list#1%
+      }%
+  }
+\protected\def\ekvoUseUnknownHandlers#1#2%
+  {%
+    \let\ekvo at handle@undefined at k#1\relax
+    \let\ekvo at handle@undefined at kv#2\relax
+    \let\ekvo at if@need at handlers\ekvo at dont@need at handlers
+  }
+\@onlypreamble\ekvoProcessLocalOptions
+\@onlypreamble\ekvoProcessGlobalOptions
+\@onlypreamble\ekvoProcessUnusedGlobalOptions
+\@onlypreamble\ekvoProcessOptionsList
+\@onlypreamble\ekvoUseUnknownHandlers
+%% 
+%%
+%% End of file `expkv-opt-2020-10-10.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt-2020-10-10.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt.sty	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,517 @@
+%%
+%% This is file `expkv-opt.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-opt.dtx  (with options: `pkg')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\IfFormatAtLeastTF{2021/05/01}
+  {}
+  {%
+    \ifx\pkgcls at targetlabel\@empty
+      \ifnum\requestedLaTeXdate=\pkgcls at targetdate
+        \pkgcls at parse@date at arg{=v0.1}%
+      \fi
+    \fi
+  }
+\DeclareRelease{v0.1}{2020/10/10}{expkv-opt-2020-10-10.sty}
+\DeclareCurrentRelease{v0.2}{2021/04/04}
+\newcommand*\ekvoVersion{1.0}
+\newcommand*\ekvoDate{2023-01-23}
+\ProvidesPackage{expkv-opt}
+  [%
+    \ekvoDate\space v\ekvoVersion\space
+    parse class and package options with expkv%
+  ]
+\RequirePackage{expkv}
+\protected\long\def\ekvo at CurrentOption@loop#1#2%
+  {%
+    \ekvo at CurrentOption@loop@#2\ekv at set@other\ekv at mark#1,\ekv at stop,\ekvo at tail
+  }
+\long\def\ekvo at CurrentOption@loop@#1\ekv at set@other#2,%
+  {%
+    \ekv at gobble@from at mark@to at stop#2\ekvo at end@loop\ekv at stop
+    \ekv at ifblank{#2}%
+      {}%
+      {%
+        \edef\CurrentOption{\unexpanded\expandafter{\ekv at gobble@mark#2}}%
+        #1{#2}%
+      }%
+    \ekvo at CurrentOption@loop@#1\ekv at set@other\ekv at mark
+  }
+\long\def\ekvo at end@loop#1\ekvo at tail{}
+\def\ekvo at ifx@TF#1#2{\ifx#1#2\ekv at fi@firstoftwo\fi\@secondoftwo}
+\def\ekvo at ifx@T#1#2{\ifx#1#2\ekv at fi@firstofone\fi\@gobble}
+\def\ekvo at ifx@F#1#2{\ifx#1#2\ekv at fi@gobble\fi\@firstofone}
+\protected\def\ekvo at do@with at set#1#2%
+  {%
+    \ekvifdefinedset{#1}%
+      {%
+        \expandafter
+        \let\expandafter\ekvo at name\csname\ekv at undefined@set{#1}\endcsname
+        \def\ekvo at setname{#1}%
+        #2%
+      }%
+      {\ekvo at err@undefined at set{#1}}%
+  }
+\protected\long\def\ekvo at handle@undefined at k@pkg#1%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {\ekvo at err@value at required{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+\def\ekvo at handle@undefined at kv@pkg#1#2%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {\ekvo at err@value at forbidden{#1}}%
+      {\ekvo at err@undefined at key{#1}}%
+  }
+\long\def\ekvo at addto@unused at one#1{\ekvo at do@unusedoptionlist\ekvo at addnewto@list}
+\long\def\ekvo at addto@unused at two#1#2{\ekvo at do@unusedoptionlist\ekvo at addnewto@list}
+\long\def\ekvo at rmfrom@unused at one#1%
+  {%
+    \ekvo at ifx@F\@unusedoptionlist\@empty
+      {\ekvo at do@unusedoptionlist\ekvo at rmfrom@list}%
+  }
+\long\def\ekvo at rmfrom@unused at two#1#2%
+  {%
+    \ekvo at ifx@F\@unusedoptionlist\@empty
+      {\ekvo at do@unusedoptionlist\ekvo at rmfrom@list}%
+  }
+\protected\def\ekvo at do@unusedoptionlist#1%
+  {%
+    \let\ekvo at unpreparedCurrentOption\CurrentOption
+    \edef\CurrentOption
+      {\expandafter\ekvo at prepare@unusedoption\CurrentOption=\ekv at mark}%
+    #1\@unusedoptionlist
+    \let\CurrentOption\ekvo at unpreparedCurrentOption
+  }
+\def\ekvo at prepare@unusedoption{\ekvo at prepare@unusedoption at a\@empty}
+\def\ekvo at prepare@unusedoption at a#1%
+  {%
+    \long\def\ekvo at prepare@unusedoption at a##1=##2\ekv at mark
+      {%
+        \ekvo at prepare@unusedoption at b##1\ekv at stop
+          \ekv at mark\ekvo at prepare@unusedoption at b
+          #1\ekv at mark\ekvo at prepare@unusedoption at c
+      }%
+  }
+\ekvo at prepare@unusedoption at a{ }
+\long\def\ekvo at prepare@unusedoption at b#1 #2\ekv at mark#3{#3#1#2\ekv at mark#3}
+\long\def\ekvo at prepare@unusedoption at c
+    #1\ekv at stop
+    \ekv at mark\ekvo at prepare@unusedoption at b\ekv at mark\ekvo at prepare@unusedoption at c
+  {\unexpanded\expandafter{#1}}
+\protected\def\ekvo at set@handlers at local
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \ifx\@currext\@clsextension
+          \ifx\@classoptionslist\relax
+            \let\ekvo at handle@undefined at k\@gobble
+            \let\ekvo at handle@undefined at kv\@gobbletwo
+          \else
+            \expandafter
+            \ifx
+                \csname @raw at opt@\@currname.\@currext\endcsname
+                \@raw at classoptionslist
+              \let\ekvo at handle@undefined at k\ekvo at addto@unused at one
+              \let\ekvo at handle@undefined at kv\ekvo at addto@unused at two
+              \unless\ifx\@unusedoptionlist\@empty
+                \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+                \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+              \fi
+            \else
+              \let\ekvo at handle@undefined at k\@gobble
+              \let\ekvo at handle@undefined at kv\@gobbletwo
+            \fi
+          \fi
+        \else
+          \let\ekvo at handle@undefined at k\ekvo at handle@undefined at k@pkg
+          \let\ekvo at handle@undefined at kv\ekvo at handle@undefined at kv@pkg
+        \fi
+      }%
+  }
+\protected\def\ekvo at set@handlers at global
+  {%
+    \unless\ifx\@unusedoptionlist\@empty
+      \let\ekvo at handle@defined at k\ekvo at rmfrom@unused at one
+      \let\ekvo at handle@defined at kv\ekvo at rmfrom@unused at two
+    \fi
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+\protected\def\ekvo at set@handlers at list
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \let\ekvo at handle@undefined at k\@gobble
+        \let\ekvo at handle@undefined at kv\@gobbletwo
+      }%
+  }
+\let\ekvo at if@need at handlers\@firstofone
+\protected\long\def\ekvo at dont@need at handlers#1%
+  {%
+    \let\ekvo at if@need at handlers\@firstofone
+  }%
+\let\ekvo at handle@defined at k\@gobble
+\let\ekvo at handle@defined at kv\@gobbletwo
+\protected\def\ekvo at process@common#1#2#3%
+  {%
+    #1{\ekvo at do@with at set{#3}{#2}}%
+  }
+\protected\def\ekvo at process@list#1%
+  {%
+    \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at parse
+  }
+\long\def\ekvo at parse#1%
+  {%
+    \ekv at eq@other#1\ekv at nil\ekv at mark\ekvo at parse@kv
+      =\ekv at mark\ekvo at parse@k
+  }
+\long\def\ekvo at parse@kv#1\ekv at stop#2\ekv at nil=\ekv at mark\ekvo at parse@k
+  {\ekv at strip{#2}{\ekv at strip{#1}\ekvo at parse@kv@}}
+\long\def\ekvo at parse@kv@#1#2%
+  {%
+    \ekv at ifexp{#1}%
+      {\ekvo at expansion@kv{#2}}%
+      {\ekvo at set@kv{#1}{#2}}%
+  }
+\long\def\ekvo at expansion@kv#1#2#3#4%
+  {%
+    \ekv at expansion@rule@{#1}#2\ekv at mark\ekv at stop{#3}{}%
+      {\ekvo at handle@defined at kv{#3}{#1}\ekvmorekv}%
+    \ekvo at expansion@kv@
+  }
+\long\def\ekvo at expansion@kv@#1#2{\ekvo at set@kv{#1}{#2}}
+\long\def\ekvo at parse@k#1\ekv at nil\ekv at mark\ekvo at parse@kv\ekv at stop\ekv at mark
+  {\ekv at strip{#1}\ekvo at parse@k@}
+\long\def\ekvo at parse@k@#1%
+  {%
+    \ekv at ifexp{#1}%
+      \ekvo at expansion@k
+      {\ekvo at set@k{#1}}%
+  }
+\long\def\ekvo at expansion@k#1#2#3%
+  {%
+    \ekv at expansion@rule@{#2}#1\ekv at mark\ekv at stop{}{}%
+      {\ekvo at handle@defined at k{#2}\ekvmorekv}%
+    \ekvo at expansion@k@
+  }
+\long\def\ekvo at expansion@k@#1#2{\ekvo at set@k{#2}}
+\protected\def\ekvo at set@k#1%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}N}%
+      {%
+        \ekvo at handle@defined at k{#1}%
+        \csname\ekvo at name{#1}N\endcsname
+      }%
+      {\ekvo at handle@undefined at k{#1}}%
+  }
+\protected\def\ekvo at set@kv#1#2%
+  {%
+    \ekv at ifdefined{\ekvo at name{#1}}%
+      {%
+        \ekvo at handle@defined at kv{#1}{#2}%
+        \csname\ekvo at name{#1}\endcsname{#2}%
+      }%
+      {\ekvo at handle@undefined at kv{#1}{#2}}%
+  }
+\protected\def\ekvo at addto@list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      {\let#1\CurrentOption}%
+      {%
+        \edef#1%
+          {%
+            \unexpanded\expandafter{#1},%
+            \unexpanded\expandafter{\CurrentOption}%
+          }%
+      }%
+  }
+\protected\def\ekvo at addnewto@list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      {\let#1\CurrentOption}%
+      {%
+        \ekvo at if@in at list#1%
+          {}%
+          {%
+            \edef#1%
+              {%
+                \unexpanded\expandafter{#1},%
+                \unexpanded\expandafter{\CurrentOption}%
+              }%
+          }%
+      }%
+  }
+\protected\def\ekvo at if@in at list#1%
+  {%
+    \ekvo at ifx@TF#1\@empty
+      \@secondoftwo
+      {%
+        \let\ekvo at curropt\CurrentOption
+        \let\ekvo at if@in at list@result\@secondoftwo
+        \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at if@in at list@
+        \let\CurrentOption\ekvo at curropt
+        \ekvo at if@in at list@result
+      }%
+  }
+\protected\long\def\ekvo at if@in at list@#1%
+  {%
+    \ekvo at ifx@T\ekvo at curropt\CurrentOption
+      {%
+        \let\ekvo at if@in at list@result\@firstoftwo
+        \ekvo at end@loop
+      }%
+  }
+\protected\def\ekvo at rmfrom@list#1%
+  {%
+    \ekvo at ifx@F#1\@empty
+      {%
+        \let\ekvo at tmp@list\@empty
+        \let\ekvo at curropt\CurrentOption
+        \expandafter\ekvo at CurrentOption@loop\expandafter{#1}\ekvo at rmfrom@list@
+        \let\CurrentOption\ekvo at curropt
+        \let#1\ekvo at tmp@list
+      }%
+  }
+\protected\long\def\ekvo at rmfrom@list@#1%
+  {%
+    \ekvo at ifx@F\CurrentOption\ekvo at curropt
+      {\ekvo at addto@list\ekvo at tmp@list}%
+  }
+\protected\def\ekvo at err@undefined at key#1%
+  {%
+    \ekvo at pkg@cls at error
+      {Undefined option `\detokenize{#1}'}%
+      {The used option was not defined. Perhaps you misspelled it?}%
+  }
+\protected\def\ekvo at err@value at required#1%
+  {%
+    \ekvo at pkg@cls at error
+      {Missing value for option `\detokenize{#1}'}%
+      {The used option requires a value or you misspelled its name.}%
+  }
+\protected\def\ekvo at err@value at forbidden#1%
+  {%
+    \ekvo at pkg@cls at error
+      {Unwanted value for option `\detokenize{#1}'}%
+      {The used option doesn't support a value or you misspelled its name.}%
+  }
+\protected\def\ekvo at err@undefined at set#1%
+  {%
+    \PackageError{expkv-opt}%
+      {Undefined set `#1'}%
+      {The set for which you try to parse options isn't defined in expkv.}%
+  }
+\protected\def\ekvo at pkg@cls at error
+  {%
+    \ekvo at ifx@TF\@currext\@clsextension
+      \ClassError
+      \PackageError
+        \@currname
+  }
+\protected\def\ekvoProcessOptions#1%
+  {%
+    \ekvo at if@need at handlers
+      {%
+        \ekvoProcessGlobalOptions{#1}%
+        \ekvoProcessLocalOptions {#1}%
+        \ekvoProcessFutureOptions{#1}%
+        \@gobbletwo
+      }%
+    \@firstofone
+      {%
+        \let\ekvo at tmpa\ekvo at handle@undefined at k
+        \let\ekvo at tmpb\ekvo at handle@undefined at kv
+        \ekvoUseUnknownHandlers\ekvo at tmpa\ekvo at tmpb
+        \ekvoProcessGlobalOptions{#1}%
+        \ekvoUseUnknownHandlers\ekvo at tmpa\ekvo at tmpb
+        \ekvoProcessLocalOptions {#1}%
+        \ekvoUseUnknownHandlers\ekvo at tmpa\ekvo at tmpb
+        \ekvoProcessFutureOptions{#1}%
+        \let\ekvo at tmpa\ekvo at undefined
+        \let\ekvo at tmpb\ekvo at undefined
+      }%
+  }
+\protected\def\ekvoProcessLocalOptions
+  {%
+    \ekvo at process@common
+      {\ekv at ifdefined{@raw at opt@\@currname.\@currext}\@firstofone\@gobble}%
+      {%
+        \ekvo at set@handlers at local
+        \expandafter
+        \ekvo at process@list\csname @raw at opt@\@currname.\@currext\endcsname
+        \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+      }%
+  }
+\protected\def\ekvoProcessGlobalOptions
+  {%
+    \ekvo at process@common{\ekvo at ifx@F\@classoptionslist\relax}%
+      {%
+        \ekvo at set@handlers at global
+        \ekvo at process@list\@raw at classoptionslist
+        \let\ekvo at handle@defined at k\@gobble
+        \let\ekvo at handle@defined at kv\@gobbletwo
+      }%
+  }
+\protected\def\ekvoProcessUnusedGlobalOptions#1%
+  {%
+    \PackageError{expkv-opt}%
+      {%
+        \noexpand
+        \ekvoProcessUnusedGlobalOptions no longer works because of changes in%
+        \MessageBreak
+        the LaTeX2e kernel%
+      }%
+      {}%
+  }
+\IfFormatAtLeastTF{2022/11/01}
+  {%
+    \protected\def\ekvoProcessFutureOptions#1%
+      {%
+        \ekvo at if@need at handlers\@gobbletwo
+        \@firstofone
+          {%
+            \expandafter\let
+              \csname ekvo at future@undefined at k@\@currname.\@currext\endcsname
+              \ekvo at handle@undefined at k
+            \expandafter\let
+              \csname ekvo at future@undefined at kv@\@currname.\@currext\endcsname
+              \ekvo at handle@undefined at kv
+          }%
+        \protected\expandafter
+        \xdef\csname opt at handler@\@currname.\@currext\endcsname
+          {\ekv at unexpanded{\ekvo at future{#1}}}%
+      }
+    \protected\def\ekvo at future
+      {%
+        \ekvo at process@common
+          {\ekv at ifdefined{@raw at opt@\@currname.\@currext}\@firstofone\@gobble}%
+          {%
+            \ekvo at set@handlers at future
+            \expandafter\ekvo at process@list
+              \csname @raw at opt@\@currname.\@currext\endcsname
+            \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+          }%
+      }
+    \protected\def\ekvo at set@handlers at future
+      {%
+        \expandafter\let\expandafter
+          \ekvo at handle@undefined at k
+          \csname
+            \ekv at ifdefined{ekvo at future@undefined at k@\@currname.\@currext}%
+              {ekvo at future@undefined at k@\@currname.\@currext}%
+              {ekvo at handle@undefined at k@pkg}%
+          \endcsname
+        \expandafter\let\expandafter
+          \ekvo at handle@undefined at kv
+          \csname
+            \ekv at ifdefined{ekvo at future@undefined at kv@\@currname.\@currext}%
+              {ekvo at future@undefined at kv@\@currname.\@currext}%
+              {ekvo at handle@undefined at kv@pkg}%
+          \endcsname
+      }
+  }
+  {%
+    \protected\def\ekvoProcessFutureOptions#1%
+      {%
+        \PackageWarning{expkv-opt}%
+          {LaTeX-kernel is too old to process future options.\@gobbletwo}%
+        \protected\gdef\ekvoProcessFutureOptions##1{}%
+      }%
+  }
+\protected\def\ekvoProcessOptionsList#1%
+  {%
+    \ekvo at process@common{\ekvo at ifx@F#1\@empty}%
+      {%
+        \ekvo at set@handlers at list
+        \ekvo at process@list#1%
+      }%
+  }
+\protected\def\ekvoUseUnknownHandlers
+  {%
+    \let\ekvo at if@need at handlers\ekvo at dont@need at handlers
+    \@ifstar\ekvoUseUnknownHandlers at s\ekvoUseUnknownHandlers at n
+  }
+\protected\def\ekvoUseUnknownHandlers at s
+  {%
+    \long\def\ekvo at handle@undefined at k##1%
+      {%
+        \ekv at ifdefined{\ekvo at name{}uN}%
+          {%
+            \csname\ekvo at name{}uN\expandafter\endcsname\expandafter
+              {\detokenize{##1}}{##1}%
+          }%
+          {\@gobble}%
+      }%
+    \long\def\ekvo at handle@undefined at kv##1##2%
+      {%
+        \ekv at ifdefined{\ekvo at name{}u}%
+          {%
+            \csname\ekvo at name{}u\ekv at expanded{\endcsname
+              {\ekv at unexpanded{##2}}{\detokenize{##1}}}{##1}%
+          }%
+          {}%
+      }%
+  }
+\protected\def\ekvoUseUnknownHandlers at n#1#2%
+  {%
+    \let\ekvo at handle@undefined at k#1\relax
+    \let\ekvo at handle@undefined at kv#2\relax
+  }
+\@onlypreamble\ekvoProcessOptions
+\@onlypreamble\ekvoProcessLocalOptions
+\@onlypreamble\ekvoProcessGlobalOptions
+\@onlypreamble\ekvoProcessFutureOptions
+\@onlypreamble\ekvoProcessOptionsList
+\@onlypreamble\ekvoUseUnknownHandlers
+%% 
+%%
+%% End of file `expkv-opt.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-opt.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-pop.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-pop.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-pop.sty	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,61 @@
+%%
+%% This is file `expkv-pop.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv-pop.dtx  (with options: `pkg')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\RequirePackage{expkv}
+\def\ekvp at tmp
+  {%
+    \ProvidesFile{expkv-pop.tex}%
+      [\ekvpDate\space v\ekvpVersion\space a prefix oriented parser]%
+  }
+\input{expkv-pop.tex}
+\ProvidesPackage{expkv-pop}%
+  [\ekvpDate\space v\ekvpVersion\space a prefix oriented parser]
+%% 
+%%
+%% End of file `expkv-pop.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv-pop.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv.sty	2023-01-24 20:57:30 UTC (rev 65623)
@@ -0,0 +1,68 @@
+%%
+%% This is file `expkv.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% expkv.dtx  (with options: `pkg')
+%% 
+%% ----------------------------------------------------------------
+%% expkv-bundle -- an expandable key=val implementation and friends
+%% E-mail: jspratte at yahoo.de
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%% 
+%% Copyright (C) 2020-2023 Jonathan P. Spratte
+%% 
+%% This  work may be  distributed and/or  modified under  the conditions  of the
+%% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
+%% (at your option) any later version.  The latest version of this license is in
+%% the file:
+%% 
+%%   http://www.latex-project.org/lppl.txt
+%% 
+%% This work is "maintained" (as per LPPL maintenance status) by
+%%   Jonathan P. Spratte.
+%% 
+%% This work consists of the files  expkv-bundle.ins
+%%                                  expkv.dtx
+%%                                  expkv-cs.dtx
+%%                                  expkv-def.dtx
+%%                                  expkv-opt.dtx
+%%                                  expkv-pop.dtx
+%% and the derived files            expkv.sty
+%%                                  expkv.tex
+%%                                  t-expkv.tex
+%%                                  expkv-cs.sty
+%%                                  expkv-cs.tex
+%%                                  t-expkv-cs.tex
+%%                                  expkv-def.sty
+%%                                  expkv-def.tex
+%%                                  t-expkv-def.tex
+%%                                  expkv-opt.sty
+%%                                  expkv-pop.sty
+%%                                  expkv-pop.tex
+%%                                  t-expkv-pop.tex
+%% 
+%% as well as any documentation files shipped with it.
+%% 
+\def\ekv at tmp
+  {%
+    \ProvidesFile{expkv.tex}%
+      [\ekvDate\space v\ekvVersion\space an expandable key=val implementation]%
+  }
+\input{expkv.tex}
+\ProvidesPackage{expkv}%
+  [\ekvDate\space v\ekvVersion\space an expandable key=val implementation]
+\let\ekv at tmp\@empty
+\DeclareOption{all}
+  {%
+    \def\ekv at tmp
+      {\RequirePackage{expkv-pop,expkv-cs,expkv-def,expkv-opt}}%
+  }
+\ProcessOptions\relax
+\ekv at tmp
+%% 
+%%
+%% End of file `expkv.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/expkv-bundle/expkv.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/tlpkg/tlpsrc/expkv-bundle.tlpsrc
===================================================================


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