texlive[59655] Master/texmf-dist: expkv-cs (20jun21)

commits+karl at tug.org commits+karl at tug.org
Sun Jun 20 21:56:27 CEST 2021


Revision: 59655
          http://tug.org/svn/texlive?view=revision&revision=59655
Author:   karl
Date:     2021-06-20 21:56:27 +0200 (Sun, 20 Jun 2021)
Log Message:
-----------
expkv-cs (20jun21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md
    trunk/Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdf
    trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
    trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex

Modified: trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md	2021-06-20 19:56:11 UTC (rev 59654)
+++ trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md	2021-06-20 19:56:27 UTC (rev 59655)
@@ -1,7 +1,7 @@
 -------------------------------------------------------------------------------
 # expkv-cs -- define expandable key=val macros using expkv
 
-Version 2021-06-03 v0.10
+Version 2021-06-20 v1.0
 
 Released under the LaTeX Project Public License v1.3c or later
 See http://www.latex-project.org/lppl.txt

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

Modified: trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx	2021-06-20 19:56:11 UTC (rev 59654)
+++ trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx	2021-06-20 19:56:27 UTC (rev 59655)
@@ -86,7 +86,7 @@
 \RequirePackage{caption}
 \RequirePackage{microtype}
 \RequirePackage{accsupp}
-\lstdefinelanguage{expkvd}[primitive]{TeX}
+\lstdefinelanguage{expkvc}[primitive]{TeX}
   {
     ,moretexcs=[4]^^A e-TeX
       {
@@ -124,6 +124,7 @@
         ekvcHash,ekvcHashAndForward,ekvcHashAndUse,
         ekvcValue,ekvcValueFast,ekvcValueSplit,ekvcValueSplitFast,
         ekvcSecondaryKeys,
+        ekvcChange,
         ekvcFlagNew,
         ekvcFlagHeight,
         ekvcFlagRaise,
@@ -130,7 +131,8 @@
         ekvcFlagSetTrue,ekvcFlagSetFalse,
         ekvcFlagIf,ekvcFlagIfRaised,
         ekvcFlagReset,
-        ekvcFlagGetHeight,ekvcFlagGetHeights
+        ekvcFlagGetHeight,ekvcFlagGetHeights,
+        ekvcPass
       }
     ,moretexcs=[3]^^A expkv-pkg macros
       {
@@ -157,7 +159,7 @@
 \def\mylstwd{.55em}
 \lstset
   {
-    ,language=expkvd
+    ,language=expkvc
     ,flexiblecolumns=false
     ,basewidth=\mylstwd
     ,gobble=2
@@ -214,6 +216,7 @@
 \definecolor{expkvred}{HTML}{9F393D}
 \colorlet{expkvgrey}{black!75}
 \makeatletter
+\newcommand*\example{\par\smallskip\noindent\textit{Example:} \ignorespaces}
 \newcommand*\expkv
   {^^A
     \texorpdfstring
@@ -282,9 +285,11 @@
 \DoNotIndex{\protected,\ProvidesFile,\ProvidesPackage,\relax,\space,\advance}
 \DoNotIndex{\@,\unexpanded,\string,\expanded,\dimexpr,\global,\glueexpr,\hbox}
 \DoNotIndex{\numexpr,\RequirePackage,\setbox,\the,\unless,\xdef,\gdef,\newcount}
-\DoNotIndex{\^,\@firstofone,\@firstoftwo,\@gobble}
+\DoNotIndex{\number,\detokenize,\meaning}
+\DoNotIndex{\^,\@firstofone,\@firstoftwo,\@gobble,\@secondoftwo}
 \DoNotIndex{\ifcsname}
 \DoNotIndex{\ifx}
+\DoNotIndex{\ifodd}
 \DoNotIndex{\ifnum}
 \DoNotIndex{\ifdefined}
 \DoNotIndex{\iffalse}
@@ -296,6 +301,7 @@
 \@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}
@@ -357,12 +363,14 @@
 % has its own set of primary and secondary keys.
 %
 % A word of advice you should consider: If your macro doesn't have to be
-% expandable (and often it doesn't) don't use \expkvc. The interface has some
-% overhead (though it still can be considered fast -- check \autoref{sec:speed})
-% and the approach has its limits in versatility. If you don't need to be
+% expandable (and often it doesn't) consider not using \expkvc. The interface
+% has some overhead (though it still is fast -- check \autoref{sec:speed}) and
+% the approach has its limits in versatility. If you don't need to be
 % expandable, you should consider either defining your keys manually using
 % \expkv\ or using \expkvd\ for convenience. Or you resort to another \kv\
-% interface.
+% interface. Nevertheless setting up macros with \expkvc, especially with
+% |\ekvcSplit|, is very convenient in my opinion, so if you just want to define
+% a single macro with just a few keys this might be the way to go.
 %
 % \expkvc\ is usable as generic code and as a \LaTeX\ package. It'll
 % automatically load \expkv\ in the same mode as well. To use it, just use one
@@ -373,13 +381,14 @@
 % \end{lstlisting}
 %
 %
-% \subsection{Define Macros and Primary Keys}
+% \subsection{Define Macros and Primary Keys}\label{sec:define}
 %
 % All macros defined with \expkvc\ have to be previously undefined or have the
-% |\meaning| of |\relax|. This is necessary as there is no way to undefine keys
-% once they are set up (neither \expkv\ nor \expkvc\ keep track of defined
-% keys) -- so to make sure there are no conflicts only new definitions are
-% allowed (that's not the case for individual keys, only for frontend macros).
+% |\meaning| of |\relax|. This is necessary as there is no way to automatically
+% undefine keys once they are set up (neither \expkv\ nor \expkvc\ keep track of
+% defined keys) -- so to make sure there are no conflicts only new definitions
+% are allowed (that's not the case for individual keys, only for frontend
+% macros).
 %
 %
 % \subsubsection{Primary Keys}\label{sec:primaries}
@@ -389,12 +398,37 @@
 % primary key and \val\ the associated initial value. By default all keys are
 % defined short, but you can define long keys by prefixing \key\ with |long|
 % (\emph{e.g.}, \texttt{long name=Jonathan P. Spratte}). You only need |long| if
-% the key should be able to take a |\par| token. Note however that |long| keys
-% are a microscopic grain faster (due to some internals of \expkvc). Only if at
-% least one of the keys was |long| the \meta{cs} in the following defining
-% macros will be |\long|. For obvious reasons there is no possibility to define
-% a macro or key as |\protected|.
+% the key should be able to take an explicit |\par| token. Note however that
+% |long| keys are a microscopic grain faster (due to some internals of \expkvc).
+% Only if at least one of the keys was |long| the \meta{cs} in the following
+% defining macros will be |\long|. For obvious reasons there is no possibility
+% to define a macro or key as |\protected|.
 %
+% To allow keys not defined |long| which key names should start with |long|, you
+% can also use the prefix |short| (|short| and |long| are mutually exclusive,
+% which ever comes first defines the behaviour, the latter is considered part of
+% the key name). Note that this is the only reason for |short|'s existance,
+% essentially it does nothing.
+%
+% The consequence culminates in the following:
+% \begin{lstlisting}
+% \ekvcSplit\foo
+%   {
+%      long short = abc\par
+%     ,short long = def
+%   }
+%   {#1#2}
+% \end{lstlisting}
+% will define a macro |\foo| that knows two primary keys, the first one is
+% called |short|, and accepts explicit |\par| tokens inside its values, the
+% second one is called |long| and will not accept |\par| tokens (leading to a
+% low level \TeX\ error). A description of |\ekvcSplit| follows shortly.
+%
+% There is one exception to these syntax rules of \meta{primary keys}: One can
+% include a key named |...| without a value. If this is found the \meta{cs} will
+% be defined |\long|. Any unknown keys found at use time will end up in a list
+% at this spot. See some examples in \autoref{sec: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.
@@ -420,6 +454,20 @@
 %   key defined first). With |\ekvcSplit| you can define macros using at most
 %   nine primary keys.
 % \end{function}
+% \example The following defines a macro |\foo| that takes the keys |a| and |b|
+% and outputs their values in a textual form:\\
+% \begin{minipage}{.75\linewidth}
+% \begin{lstlisting}
+% \ekvcSplit\foo{a=a,b=b}{a is #1.\par b is #2.\par}
+% \foo{}
+% \foo{b=e}
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \ekvcSplit\foo{a=a,b=b}{a is #1.\par b is #2.\par}
+%   \foo{}
+%   \foo{b=e}
+% \end{exresult}
 %
 % \begin{function}{\ekvcSplitAndForward}
 %   \begin{syntax}
@@ -439,6 +487,9 @@
 % \ekvcSplitAndForward\foo{\foo at aux{more args}}{keyA = A, keyB = B}
 % \end{lstlisting}
 % \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}
@@ -448,20 +499,23 @@
 %   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{syntax}
-%     \meta{cs}\{\key=\val, \ldots\}\marg{after}
-%   \end{syntax}
+% \begin{quote}
+%   \ttfamily
+%   \meta{cs}\{\key=\val, \ldots\}\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}
 %
 % 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 much slower (for a
-% primitive macro with a single key benchmarking was almost $1.7$ times slower,
-% the root of which being the key access with |\ekvcValue|, not the parsing, and
-% for a key access using |\ekvcValueFast| it was still about $1.2$ times
-% slower). So if your macro uses less than ten primary keys, you should most
-% likely use the split approach.
+% 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 |\ekvcValue|, not the
+% parsing, and for a key access using |\ekvcValueFast| it was still about $1.2$
+% times slower). So if your macro uses less than ten primary keys, you should
+% consider using the split approach.
 %
 % \begin{function}{\ekvcHash}
 %   \begin{syntax}
@@ -474,6 +528,22 @@
 %   \meta{definition}, in which you can access the \val\ of a \key\ by using
 %   \texttt{\cs[no-index]{ekvcValue}\{\key\}\{\#1\}}.
 % \end{function}
+% \example This defines an equivalent macro to the |\foo| defined with
+% |\ekvcSplit| earlier:\\
+% \begin{minipage}{.75\linewidth}
+% \begin{lstlisting}
+% \ekvcHash\foo{a=a,b=b}{a is \ekvcValue{a}{#1}.\par
+%                        b is \ekvcValue{b}{#1}.\par}
+% \foo{}
+% \foo{b=e}
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \ekvcHash\foo{a=a,b=b}{a is \ekvcValue{a}{#1}.\par
+%                          b is \ekvcValue{b}{#1}.\par}
+%   \foo{}
+%   \foo{b=e}
+% \end{exresult}
 %
 % \begin{function}{\ekvcHashAndForward}
 %   \begin{syntax}
@@ -489,6 +559,13 @@
 %   \texttt{\cs[no-index]{ekvcValue}\{\key\}\{\#1\}} (or whichever argument the
 %   hashed \kv\ list will be).
 % \end{function}
+% \example This defines a macro |\foo| processing two keys, and passing the
+% result to |\foobar|:
+% \begin{lstlisting}
+% \ekvcHashAndForward\foo\foobar{a=a,b=b}
+% \newcommand*\foobar[1]{a is \ekvcValue{a}{#1}.\par
+%                        b is \ekvcValue{b}{#1}.\par}
+% \end{lstlisting}
 %
 % \begin{function}{\ekvcHashAndUse}
 %   \begin{syntax}
@@ -495,12 +572,13 @@
 %     \cs{ekvcHashAndUse}\meta{cs}\marg{primary keys}
 %   \end{syntax}
 %   This will roughly do the same as |\ekvcHashAndForward|, but instead of
-%   specifying what will be used after hashing the keys, \meta{cs} will use what
-%   follows the \kv\ list. So its syntax will be
+%   specifying what will be used after hashing the keys at install time,
+%   \meta{cs} will use what follows the \kv\ list. So its syntax will be
 % \end{function}
-%   \begin{syntax}
-%     \meta{cs}\{\key=\val, \ldots\}\marg{after}
-%   \end{syntax}
+% \begin{quote}
+%   \ttfamily
+%   \meta{cs}\{\key=\val, \ldots\}\marg{after}
+% \end{quote}
 %
 % \begin{function}{\ekvcValue}
 %   \begin{syntax}
@@ -525,9 +603,9 @@
 %   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 \key).
-%   Use it if you know what you're doing. This macro needs exactly three steps
-%   of expansion in the no-errors case.
+%   key for another macro -- all macros share the same hash function per \key\
+%   name). Use it if you know what you're doing. This macro needs exactly three
+%   steps of expansion in the no-errors case.
 % \end{function}
 %
 % \begin{function}{\ekvcValueSplit}
@@ -537,13 +615,34 @@
 %   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. Hence the macro \cs{ekvcValueSplit} will extract one
-%   specific \key's value from the list and forward the remainder of the list
-%   as the first and the \key's value as the second argument to \meta{next}, so
-%   the result of this will be \meta{next}\marg{key list'}\marg{value} with
-%   \meta{key list'} the remaining list. This is almost as fast as |\ekvcValue|
-%   and runs the same tests. Keep in mind that you can't fetch for the same
-%   \key\ again from \meta{key list'} as it got removed.
+%   specific \key's value 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
+%   |\ekvcValue| and runs the same tests.
 % \end{function}
+% \example 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{minipage}{.75\linewidth}
+% \begin{lstlisting}
+% \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{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \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{exresult}
 %
 % \begin{function}{\ekvcValueSplitFast}
 %   \begin{syntax}
@@ -555,7 +654,7 @@
 % \end{function}
 %
 %
-% \subsection{Secondary Keys}
+% \subsection{Secondary Keys}\label{sec:secondaries}
 %
 % To remove some of the limitations with the approach that each primary key
 % matches an argument or hash entry, you can define secondary keys. Those have
@@ -641,8 +740,8 @@
 %   If \key\ is a defined value taking key, you can define a |NoVal| version
 %   with this that 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 in |\ekvcSplit| and friends. \key\ can be a primary or
-%   secondary key.
+%   at definition time in |\ekvcSplit| and friends (see |\ekvcChange| in
+%   \autoref{sec:change} for this). \key\ can be a primary or secondary key.
 % \end{function}
 %
 % \begin{function}{flag-bool}
@@ -681,6 +780,167 @@
 % \end{function}
 %
 %
+% \subsection{Changing the Initial Values}\label{sec:change}
+%
+% \begin{function}{\ekvcChange}
+%   \begin{syntax}
+%     \cs{ekvcChange}\meta{cs}\{\kv,\ldots\}
+%   \end{syntax}
+%   This processes the \kv\ list for the macro \meta{cs} to set new defaults for
+%   it (meaning the values used if you don't provide anything at use time, not
+%   those specified with the |default| secondary key). \meta{cs} should be
+%   defined with \expkvc\ (so with any of the methods in \autoref{sec:define}).
+%   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 defaults were). If there
+%   was an unknown key forwarding added to \meta{cs} (see \autoref{sec:unknown})
+%   any unknown key will be stored inside the list of unknown keys as well.
+%   |\ekvcChange| is not expandable!
+% \end{function}
+%
+% Consider the following example:\\
+% \begin{minipage}[c]{.75\linewidth}
+% \begin{lstlisting}
+% \ekvcSplit\foo{a=a,b=b}{a is #1.\par b is #2.\par}
+% \begingroup
+%   \ekvcChange\foo{b=B}
+%   \foo{} % new defaults
+%   \ekvcSecondaryKeys\foo{meta c={a={#1},b={#1}}}
+%   \ekvcChange\foo{c=c}
+%   \foo{} % newer defaults
+% \endgroup
+% \foo{} % initial defaults
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \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{exresult}
+%
+% As a result with this the typical setup macro could be implemented:
+% \begin{lstlisting}
+% \ekvcHashAndUse\foo{key=a,key=b}
+% \newcommand*\foosetup{\ekvcChange\foo}
+% \end{lstlisting}
+% Of course the usage is limited to a single macro |\foo|, 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.
+%
+%
+% \subsection{Handling Unknown Keys}\label{sec: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 name will be the result of one |\detokenize|, the value
+% will be forwarded as \verb*| {|\meta{value}\verb*|} |, so with spaces around
+% one set of braces (this way, most other \kv\ implementations should parse the
+% correct input).
+%
+% The exact behaviour differs slightly between the two variants (as all 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.
+%
+% \example The following will forward any unknown key to |\includegraphics| to
+% control the appearance while processing its own keys:\\
+% \begin{minipage}{.6\linewidth}
+% \begin{lstlisting}
+% \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{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.4\linewidth}
+%   \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{exresult}
+%
+% Inside the hash variants the unknown keys list will be put inside the hash
+% named |...| (we have to use some name, so why not this). 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.
+%
+% \example The following is more or less equivalent to the example above, 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{minipage}{.76\linewidth}
+% \begin{lstlisting}
+% \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
+%     \expanded{\noexpand\includegraphics
+%                          [{\ekvcValue{...}{#1}}]}
+%                          {#2}\par
+%   }
+% \foo[width=\linewidth, b=c]
+%     {example-image-duck-portrait}
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.24\linewidth}
+%   \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
+%       \expanded{\noexpand\includegraphics
+%                            [{\ekvcValue{...}{#1}}]}
+%                            {#2}\par
+%     }
+%   \foo[width=\linewidth, b=c]
+%       {example-image-duck-portrait}
+% \end{exresult}
+%
+%
 % \subsection{Flags}\label{sec:flags}
 %
 % The idea of flags is taken from \pkg{expl3}. They provide a way to store
@@ -693,7 +953,8 @@
 %
 % 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 |t|-types involving flags
-% bear in mind that they can affect other macros at the current group level!
+% bear in mind that they can affect other macros using the same flags at the
+% current group level!
 %
 % \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}.
@@ -706,7 +967,7 @@
 %   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 |\ifnum| for example and it will terminate the number scanning
-%   itself).
+%   on its own).
 % \end{function}
 %
 %  All other macros dealing with flags take as a parameter a macro defined as a
@@ -791,26 +1052,26 @@
 % \end{function}
 %
 %
-% \subsection{Example}
+% \subsection{Further Examples}\label{sec:examples}
 %
-% How could a documentation be a good documentation without some basic examples?
-% Say we want to define a small macro expanding to some character description
-% (who knows why this has to be expandable?). A character description will not
-% have too many items to it, so we use |\ekvcSplit|.
+% How could a documentation be a good documentation without enough basic
+% examples?  Say we want to define a small macro expanding to some character
+% description (who knows why this has to be expandable?). A character
+% description will not have too many items to it, so we use |\ekvcSplit| (the
+% comments with the parameter numbers are of course not necessary and just ease
+% reading the example).
 % \begin{lstlisting}
 % \ekvcSplit\character
 %   {
-%     name=John Doe,
-%     age=any,
-%     nationality=the Universe,
-%     hobby=to exist,
-%     type=Mister,
-%     pronoun=He,
-%     possessive=his,
+%     name=John Doe,            % #1
+%     age=any,                  % #2
+%     nationality=the Universe, % #3
+%     hobby=to exist,           % #4
+%     type=Mister,              % #5
+%     pronoun=He,               % #6
+%     possessive=his,           % #7
 %   }
-%   {%
-%     #1 is a #5 from #3. #6 is of #2 age and #7 hobby is #4.\par
-%   }
+%   {#1 is a #5 from #3. #6 is of #2 age and #7 hobby is #4.\par}
 % \end{lstlisting}
 % Also we want to give some short cuts so that it's easier to describe several
 % persons.
@@ -854,7 +1115,7 @@
 % As one might see, the |lady| key could actually have been an |nmeta| key as
 % well, as all that is done with the argument is using it as a \kv\ list.
 %
-% The result of all the first two usages would be:
+% The result of only the first two usages would be:
 % \begin{exresult}{\linewidth}
 %   \ekvcSplit\character
 %     {
@@ -898,7 +1159,9 @@
 % and mandatory arguments as well. A small nonsense example (which should
 % perhaps use |\ekvcSplitAndForward| instead of |\ekvcHashAndForward| since it
 % only uses four keys and one other argument -- and isn't expandable since it
-% uses a \env{tabular} environment):
+% uses a \env{tabular} environment, so it would've been better to use a more
+% feature rich \kv\ interface most likely, \emph{e.g.}, the one provided by
+% \expkvd):
 % \begin{lstlisting}
 % \makeatletter
 % \newcommand*\nonsense{\ekvoptarg\nonsense at a{}}
@@ -957,6 +1220,70 @@
 % \end{exresult}
 %
 %
+% \subsection{Freedom for Keys!}
+%
+% If this was the \TeX book this subsection would have 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 types listed in \autoref{sec:secondaries} 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
+% |\string|\meta{cs} is used. This can be exploited to define additional keys
+% with arbitrary code. Consider the following \emph{bad} example:
+% \begin{lstlisting}
+% \ekvcSplit\foo{a=A,b=B}{a is #1.\par b is #2\par}
+% \protected\ekvdef{\string\foo}{c}{\def\fooC{#1}}
+% \end{lstlisting}
+% This would define a key named |c| that will store its value 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
+% create a key that pre-parses the input and after that passes the parsed value
+% on. This parsing would have to be completely expandable though. 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 \meta{value} on to \meta{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}
+%
+% With this we could for example split the value of a key at a hyphen and pass
+% the parts to different keys:\\
+% \begin{minipage}[c]{.75\linewidth}
+% \begin{lstlisting}
+% \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{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \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{exresult}
+%
+%
 % \subsection{Speed Considerations}\label{sec:speed}
 %
 % As already mentioned in the introduction there are some speed considerations
@@ -965,13 +1292,13 @@
 % use case. The key-parsing is still faster than with most other \kv\ packages
 % (see the ``Comparisons'' subsection in the \expkv\ documentation).
 %
-% The speed considerations in this subsection use the first example in this
-% documentation as the benchmark. So we have seven keys and a short sentence
-% which should be typeset. For comparisons I use the following equivalent
-% \expkvd\ definitions. Each result is the average between changing no keys from
-% their initial values and altering four. Furthermore I'll compare three
-% variants of \expkvc\ with the \expkvd\ definitions, namely the split example
-% from above, a hash variant using |\ekvcValue| and a hash variant using
+% The speed considerations in this subsection use the first example of
+% \autoref{sec:examples} as the benchmark. So we have seven keys and a short
+% sentence which should be typeset. For comparisons I use the following
+% equivalent \expkvd\ definitions. Each result is the average between changing
+% no keys from their initial values and altering four. Furthermore I'll compare
+% three variants of \expkvc\ with the \expkvd\ definitions, namely the split
+% example from above, a hash variant using |\ekvcValue| and a hash variant using
 % |\ekvcValueFast|.
 % \begin{lstlisting}
 % \usepackage{expkv-def}
@@ -996,8 +1323,9 @@
 %   {%
 %     \begingroup
 %       \ekvset{keys}{#1}%
-%       \KEYSname\ is a \KEYStype\ from \KEYSnationality. \KEYSpronoun\ is
-%       of \KEYSage\ age and \KEYSpossessive\ hobby is \KEYShobby.%
+%       \KEYSname\ is a \KEYStype\ from \KEYSnationality.
+%       \KEYSpronoun\ is of \KEYSage\ age and
+%       \KEYSpossessive\ hobby is \KEYShobby.%
 %     \endgroup
 %   }
 % \end{lstlisting}
@@ -1021,14 +1349,16 @@
 % parsing part and only $1.5$ to $2.8$ times faster if the typesetting part is
 % factored in. So the real choke isn't the parsing.
 %
-% So to summarize this, if you have a reasonable use case for expandable \kv\
-% parsing macros you should go on and define them using \expkvc. If you have a
-% reasonable use case for \kv\ parsing macros but defining them expandable isn't
-% necessary for your use you should take advantage of the greater flexibility of
-% non-expandable \kv\ setups (but if you're after maximum speed there aren't
-% that many \kv\ parsers beating \expkvc). And if you are after maximum
-% performance maybe ditching the \kv\ interface altogether is a good idea, but
-% depending on the number of arguments your interface might get convoluted.
+% So to summarise this, if you have a use case for expandable \kv\
+% parsing macros you should go on and define them using \expkvc. If you just
+% want to define a simple macro with a few keys |\ekvcSplit| might be the
+% easiest interface there is. If you have a reasonable use case for \kv\ parsing
+% macros but defining them expandable isn't necessary for your use you should
+% take advantage of the greater flexibility of non-expandable \kv\ setups (but
+% if you're after maximum speed there aren't that many \kv\ parsers beating
+% \expkvc). And if you are after maximum performance maybe ditching the \kv\
+% interface altogether is a good idea, but depending on the number of arguments
+% your interface might get convoluted.
 %
 %
 % \subsection{Useless Macros}
@@ -1127,8 +1457,8 @@
 % \begin{macro}{\ekvcVersion,\ekvcDate}
 % We're on our first input, so lets store the version and date in a macro.
 %    \begin{macrocode}
-\def\ekvcVersion{0.10}
-\def\ekvcDate{2021-06-03}
+\def\ekvcVersion{1.0}
+\def\ekvcDate{2021-06-20}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1148,6 +1478,14 @@
 % |\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}
+\def\ekvc at tripledots{...}
+%    \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.
@@ -1334,7 +1672,8 @@
 % \begin{macro}[internal]
 %   {
 %     \ekvc at SetupSplitKeys, \ekvc at SetupSplitKeys@a, \ekvc at SetupSplitKeys@b,
-%     \ekvc at SetupSplitKeys@c
+%     \ekvc at SetupSplitKeys@c,
+%     \ekvc at SetupSplitKeys@check at unknown,\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 |\ekvparse|.
@@ -1344,7 +1683,7 @@
     \ekvc at keycount=0
     \let\ekvc at any@long\ekv at empty
     \let\ekvc at initials\ekv at empty
-    \ekvparse\ekvc at err@value at required\ekvc at SetupSplitKeys@a
+    \ekvparse\ekvc at SetupSplitKeys@check at unknown\ekvc at SetupSplitKeys@a
   }
 %    \end{macrocode}
 %   Then we need to step the key counter for each key. Also we have to check
@@ -1421,6 +1760,47 @@
       {}%
   }
 %    \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}
+\protected\long\def\ekvc at SetupSplitKeys@check at unknown#1%
+  {%
+    \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}
+%
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupSplitKeys@unknown#1%
+  {%
+    \long\expandafter\def\csname\ekv at name\ekvc at set{}u\endcsname##1##2##3#1##4%
+      {##3#1{##4,##2= {##1} }}%
+    \long\expandafter\def\csname\ekv at name\ekvc at set{}uN\endcsname##1##2#1##3%
+      {##2#1{##3,##1}}%
+    \edef\ekvc at initials{\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 split@p at long}
@@ -1436,6 +1816,14 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}[internal]{\ekvc at split@p at short}
+%   The |short| prefix does essentially nothing, it is only provided to allow
+%   key names starting with |long| that aren't |\long|.
+%    \begin{macrocode}
+\def\ekvc at split@p at short{\ekvc at SetupSplitKeys@c}
+%    \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.
@@ -1623,7 +2011,11 @@
 % \end{macro}
 %
 % \begin{macro}[internal]
-%   {\ekvc at SetupHashKeys,\ekvc at SetupHashKeys@a,\ekvc at SetupHashKeys@b}
+%   {%
+%     \ekvc at SetupHashKeys,\ekvc at SetupHashKeys@a,\ekvc at SetupHashKeys@b,
+%     \ekvc at SetupHashKeys@c,
+%     \ekvc at SetupHashKeys@check at unknown,\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}
@@ -1631,7 +2023,7 @@
   {%
     \let\ekvc at any@long\ekv at empty
     \let\ekvc at initials\ekv at empty
-    \ekvparse\ekvc at err@value at required\ekvc at SetupHashKeys@a{#1}%
+    \ekvparse\ekvc at SetupHashKeys@check at unknown\ekvc at SetupHashKeys@a{#1}%
   }
 \protected\def\ekvc at SetupHashKeys@a#1%
   {%
@@ -1685,6 +2077,39 @@
     \ekvc at setup@hashmacro{#1}%
   }
 %    \end{macrocode}
+%    \begin{macrocode}
+\protected\long\def\ekvc at SetupHashKeys@check at unknown#1%
+  {%
+    \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}
+%    \begin{macrocode}
+\def\ekvc at SetupHashKeys@unknown#1%
+  {%
+    \protected\def\ekvc at SetupHashKeys@unknown
+      {%
+        \expandafter
+        \let\csname\ekv at name\ekvc at set{}u\endcsname\ekvc at hash@unknown at kv
+        \expandafter
+        \let\csname\ekv at name\ekvc at set{}uN\endcsname\ekvc at hash@unknown at k
+        \edef\ekvc at initials{\unexpanded\expandafter{\ekvc at initials#1{}}}%
+        \ekvc at setup@hashmacro{...}%
+      }%
+    \long\def\ekvc at hash@unknown at kv##1##2##3#1##4{##3#1{##4,##2= {##1} }}%
+    \long\def\ekvc at hash@unknown at k##1##2#1##3{##2#1{##3,##1}}%
+  }
+\expandafter\ekvc at SetupHashKeys@unknown
+  \csname ekvc at hashmark@\ekvc at tripledots\endcsname
+%    \end{macrocode}
 % \end{macro}
 %
 % \begin{macro}[internal]{\ekvc at hash@p at long}
@@ -1699,6 +2124,14 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}[internal]{\ekvc at hash@p at short}
+%   The |short| prefix does essentially nothing, it is only provided to allow
+%   key names starting with |long| that aren't |\long|.
+%    \begin{macrocode}
+\def\ekvc at hash@p at short{\ekvc at SetupHashKeys@c}
+%    \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.
@@ -1748,7 +2181,7 @@
                   \unexpanded\expandafter{\csname ekvc at hashmark@#1\endcsname}%
                   ####2####3\unexpanded{\ekvc at stop}####4%
                 {%
-                  ####4{####1####3}{####2}%
+                  ####4{####2}%
                 }%
               \long\gdef\unexpanded\expandafter
                 {\csname ekvc at safesplithash@#1\endcsname}####1%
@@ -1755,11 +2188,12 @@
                 {%
                   \unexpanded\expandafter
                     {\csname ekvc@@safesplithash@#1\endcsname}%
-                  ####1\unexpanded{\ekvc at mark\ekvc at safe@found at hash}%
+                  ####1\unexpanded{\ekvc at mark\ekvc at safe@after at hash}%
                   \unexpanded\expandafter
                     {%
                       \csname ekvc at hashmark@#1\endcsname{}%
-                      \ekvc at mark{\ekvc at err@missing at hash{#1}\ekvc at safe@no at hash}%
+                      \ekvc at mark
+                      {\ekvc at err@missing at hash{#1}\ekvc at safe@after at hash}%
                       \ekvc at stop
                     }%
                 }%
@@ -1770,7 +2204,7 @@
                   ####2####3\unexpanded{\ekvc at mark}####4####5%
                   \unexpanded{\ekvc at stop}%
                 {%
-                  ####4{####2}####1####3\unexpanded{\ekvc at stop}%
+                  ####4{####2}%
                 }%
             }%
           \ekvc at tmp
@@ -1812,23 +2246,16 @@
       {\csname ekvc at safesplithash@#1\endcsname}%
       {\ekvc at err@unknown at hash{#1}\ekvcValueSplit at recover}%
   }
-\long\def\ekvcValueSplit at recover#1#2%
-  {%
-    #2{#1}{}%
-  }
+\long\def\ekvcValueSplit at recover#1#2{#2{}}
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[internal]{\ekvc at safe@found at hash, \ekvc at safe@no at hash}
+% \begin{macro}[internal]{\ekvc at safe@after at hash}
 %    \begin{macrocode}
-\long\def\ekvc at safe@found at hash#1#2\ekvc at stop#3%
+\long\def\ekvc at safe@after at hash#1#2%
   {%
-    #3{#2}{#1}%
+    #2{#1}%
   }
-\long\def\ekvc at safe@no at hash#1#2\ekvc at mark\ekvc at safe@found at hash\ekvc at stop#3%
-  {%
-    #3{#2}{}%
-  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1839,9 +2266,7 @@
 %   sequence.
 %    \begin{macrocode}
 \long\def\ekvcValueSplitFast#1#2%
-  {%
-    \csname ekvc at fastsplithash@#1\endcsname#2\ekvc at stop
-  }
+  {\csname ekvc at fastsplithash@#1\endcsname#2\ekvc at stop}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1858,8 +2283,8 @@
 %    \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{#1}{}}
-\long\def\ekvc at fastsplithash@#1\ekvc at stop#2{\ekvc at err@empty at hash#2{#1}{}}
+\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}
 %
@@ -1894,7 +2319,117 @@
 %    \end{macrocode}
 % \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}
+%   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). |#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{##1}}{#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\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 |\def|. We do
+%   that with the help of a temporary macro which stores everything necessary
+%   for |\def| and expand an |\iffalse}\fi| construct to leave a single
+%   opening brace. |#1| will be either empty or |\long| and |#2| is the macro.
+%   Each of the macros defined with \expkvc\ takes exactly one parameter, so we
+%   put that here as |####1|.
+%    \begin{macrocode}
+\protected\def\ekvc at change@d#1#2%
+  {%
+    \def\ekvc at tmp{#1\def#2####1}%
+    \expandafter\ekvc at tmp\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}
 %
 % \begin{macro}[internal]{\ekvc at p@long,\ekvc at after@ptype}
@@ -2287,7 +2822,7 @@
 % \begin{macro}[internal]
 %   {
 %     \ekvc at err@toomany,\ekvc at err@value at required,\ekvc at err@missing at type,
-%     \ekvc at err@already at defined
+%     \ekvc at err@already at defined,\ekvc at err@no at key@macro
 %   }
 %   Boring unexpandable error messages.
 %    \begin{macrocode}
@@ -2322,6 +2857,8 @@
     \errmessage
       {expkv-cs Error: Unknown key `\unexpanded{#1}' for macro `\ekvc at set'}%
   }
+\long\def\ekvc at err@no at key@macro#1%
+  {\errmessage{expkv-cs Error: \string#1 is no key=val macro}}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -2343,6 +2880,8 @@
 \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 macro #1}}
 %    \end{macrocode}
 % \end{macro}
 %

Modified: trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex	2021-06-20 19:56:11 UTC (rev 59654)
+++ trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex	2021-06-20 19:56:27 UTC (rev 59655)
@@ -35,11 +35,12 @@
 \else
   \expandafter\endinput
 \fi
-\def\ekvcVersion{0.10}
-\def\ekvcDate{2021-06-03}
+\def\ekvcVersion{1.0}
+\def\ekvcDate{2021-06-20}
 \csname ekvc at tmp\endcsname
 \expandafter\chardef\csname ekvc at tmp\endcsname=\catcode`\@
 \catcode`\@=11
+\def\ekvc at tripledots{...}
 \newcount\ekvc at keycount
 \let\ekvc at long\ekv at empty
 \let\ekvc at any@long\ekv at empty
@@ -150,7 +151,7 @@
     \ekvc at keycount=0
     \let\ekvc at any@long\ekv at empty
     \let\ekvc at initials\ekv at empty
-    \ekvparse\ekvc at err@value at required\ekvc at SetupSplitKeys@a
+    \ekvparse\ekvc at SetupSplitKeys@check at unknown\ekvc at SetupSplitKeys@a
   }
 \protected\def\ekvc at SetupSplitKeys@a#1%
   {%
@@ -202,6 +203,33 @@
       {\expandafter\ekvc at setup@splitmacro\expandafter{\the\ekvc at keycount}}%
       {}%
   }
+\protected\long\def\ekvc at SetupSplitKeys@check at unknown#1%
+  {%
+    \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@unknown#1%
+  {%
+    \long\expandafter\def\csname\ekv at name\ekvc at set{}u\endcsname##1##2##3#1##4%
+      {##3#1{##4,##2= {##1} }}%
+    \long\expandafter\def\csname\ekv at name\ekvc at set{}uN\endcsname##1##2#1##3%
+      {##2#1{##3,##1}}%
+    \edef\ekvc at initials{\unexpanded\expandafter{\ekvc at initials#1{}}}%
+    \ekvc at helpers@needed
+      {\expandafter\ekvc at setup@splitmacro\expandafter{\the\ekvc at keycount}}%
+      {}%
+  }
 \protected\def\ekvc at split@p at long
   {%
     \let\ekvc at long\long
@@ -208,6 +236,7 @@
     \let\ekvc at any@long\long
     \ekvc at SetupSplitKeys@c
   }
+\def\ekvc at split@p at short{\ekvc at SetupSplitKeys@c}
 \protected\def\ekvc at defarggobbler#1{\def\ekvc at tmp##1#1##2##{##1#1}}
 \begingroup
 \edef\ekvc at tmp
@@ -340,7 +369,7 @@
   {%
     \let\ekvc at any@long\ekv at empty
     \let\ekvc at initials\ekv at empty
-    \ekvparse\ekvc at err@value at required\ekvc at SetupHashKeys@a{#1}%
+    \ekvparse\ekvc at SetupHashKeys@check at unknown\ekvc at SetupHashKeys@a{#1}%
   }
 \protected\def\ekvc at SetupHashKeys@a#1%
   {%
@@ -386,6 +415,35 @@
     \ekvlet\ekvc at set{#1}\ekvc at tmp
     \ekvc at setup@hashmacro{#1}%
   }
+\protected\long\def\ekvc at SetupHashKeys@check at unknown#1%
+  {%
+    \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
+  }
+\def\ekvc at SetupHashKeys@unknown#1%
+  {%
+    \protected\def\ekvc at SetupHashKeys@unknown
+      {%
+        \expandafter
+        \let\csname\ekv at name\ekvc at set{}u\endcsname\ekvc at hash@unknown at kv
+        \expandafter
+        \let\csname\ekv at name\ekvc at set{}uN\endcsname\ekvc at hash@unknown at k
+        \edef\ekvc at initials{\unexpanded\expandafter{\ekvc at initials#1{}}}%
+        \ekvc at setup@hashmacro{...}%
+      }%
+    \long\def\ekvc at hash@unknown at kv##1##2##3#1##4{##3#1{##4,##2= {##1} }}%
+    \long\def\ekvc at hash@unknown at k##1##2#1##3{##2#1{##3,##1}}%
+  }
+\expandafter\ekvc at SetupHashKeys@unknown
+  \csname ekvc at hashmark@\ekvc at tripledots\endcsname
 \protected\def\ekvc at hash@p at long
   {%
     \let\ekvc at long\long
@@ -392,6 +450,7 @@
     \let\ekvc at any@long\long
     \ekvc at SetupHashKeys@c
   }
+\def\ekvc at hash@p at short{\ekvc at SetupHashKeys@c}
 \protected\def\ekvc at setup@hashmacro#1%
   {%
     \ekv at ifdefined{ekvc at fasthash@#1}{}%
@@ -432,7 +491,7 @@
                   \unexpanded\expandafter{\csname ekvc at hashmark@#1\endcsname}%
                   ####2####3\unexpanded{\ekvc at stop}####4%
                 {%
-                  ####4{####1####3}{####2}%
+                  ####4{####2}%
                 }%
               \long\gdef\unexpanded\expandafter
                 {\csname ekvc at safesplithash@#1\endcsname}####1%
@@ -439,11 +498,12 @@
                 {%
                   \unexpanded\expandafter
                     {\csname ekvc@@safesplithash@#1\endcsname}%
-                  ####1\unexpanded{\ekvc at mark\ekvc at safe@found at hash}%
+                  ####1\unexpanded{\ekvc at mark\ekvc at safe@after at hash}%
                   \unexpanded\expandafter
                     {%
                       \csname ekvc at hashmark@#1\endcsname{}%
-                      \ekvc at mark{\ekvc at err@missing at hash{#1}\ekvc at safe@no at hash}%
+                      \ekvc at mark
+                      {\ekvc at err@missing at hash{#1}\ekvc at safe@after at hash}%
                       \ekvc at stop
                     }%
                 }%
@@ -454,7 +514,7 @@
                   ####2####3\unexpanded{\ekvc at mark}####4####5%
                   \unexpanded{\ekvc at stop}%
                 {%
-                  ####4{####2}####1####3\unexpanded{\ekvc at stop}%
+                  ####4{####2}%
                 }%
             }%
           \ekvc at tmp
@@ -475,26 +535,17 @@
       {\csname ekvc at safesplithash@#1\endcsname}%
       {\ekvc at err@unknown at hash{#1}\ekvcValueSplit at recover}%
   }
-\long\def\ekvcValueSplit at recover#1#2%
+\long\def\ekvcValueSplit at recover#1#2{#2{}}
+\long\def\ekvc at safe@after at hash#1#2%
   {%
-    #2{#1}{}%
+    #2{#1}%
   }
-\long\def\ekvc at safe@found at hash#1#2\ekvc at stop#3%
-  {%
-    #3{#2}{#1}%
-  }
-\long\def\ekvc at safe@no at hash#1#2\ekvc at mark\ekvc at safe@found at hash\ekvc at stop#3%
-  {%
-    #3{#2}{}%
-  }
 \long\def\ekvcValueSplitFast#1#2%
-  {%
-    \csname ekvc at fastsplithash@#1\endcsname#2\ekvc at stop
-  }
+  {\csname ekvc at fastsplithash@#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{#1}{}}
-\long\def\ekvc at fastsplithash@#1\ekvc at stop#2{\ekvc at err@empty at hash#2{#1}{}}
+\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{}}
 \protected\long\def\ekvcSecondaryKeys#1#2%
   {%
     \edef\ekvc at set{\string#1}%
@@ -518,6 +569,56 @@
       }%
       {#2}%
   }
+\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{##1}}{#1}#2}
+\ekv at exparg{\protected\long\def\ekvc at change@c#1#2#3#4}%
+  {%
+    \expandafter\iffalse\expandafter{\expandafter\fi
+      \ekvset{\string#3}{#4}%
+      \ekvc at change@d{#2}{#3}%
+      #1%
+    }%
+  }
+\protected\def\ekvc at change@d#1#2%
+  {%
+    \def\ekvc at tmp{#1\def#2####1}%
+    \expandafter\ekvc at tmp\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}%
+  }
 \protected\def\ekvc at p@long#1%
   {%
     \ekvc at ifspace{#1}%
@@ -762,11 +863,15 @@
     \errmessage
       {expkv-cs Error: Unknown key `\unexpanded{#1}' for macro `\ekvc at set'}%
   }
+\long\def\ekvc at err@no at key@macro#1%
+  {\errmessage{expkv-cs Error: \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 macro #1}}
 \catcode`\@=\ekvc at tmp
 %% 
 %%



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