summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-06-20 19:56:27 +0000
committerKarl Berry <karl@freefriends.org>2021-06-20 19:56:27 +0000
commit2347cb3e8bc2c9276574d14461f4429c6b3c1bd4 (patch)
treeeb091127516eb112f601cab0c919848e8b6beb2e /Master/texmf-dist/source
parent0e008fd431955e2802ab0abb5220e3bfb78256e6 (diff)
expkv-cs (20jun21)
git-svn-id: svn://tug.org/texlive/trunk@59655 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r--Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx753
1 files changed, 646 insertions, 107 deletions
diff --git a/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx b/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
index 55a6a134aa4..599750404a6 100644
--- a/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
+++ b/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
@@ -86,7 +86,7 @@ and the derived files expkv-cs.pdf
\RequirePackage{caption}
\RequirePackage{microtype}
\RequirePackage{accsupp}
-\lstdefinelanguage{expkvd}[primitive]{TeX}
+\lstdefinelanguage{expkvc}[primitive]{TeX}
{
,moretexcs=[4]^^A e-TeX
{
@@ -124,13 +124,15 @@ and the derived files expkv-cs.pdf
ekvcHash,ekvcHashAndForward,ekvcHashAndUse,
ekvcValue,ekvcValueFast,ekvcValueSplit,ekvcValueSplitFast,
ekvcSecondaryKeys,
+ ekvcChange,
ekvcFlagNew,
ekvcFlagHeight,
ekvcFlagRaise,
ekvcFlagSetTrue,ekvcFlagSetFalse,
ekvcFlagIf,ekvcFlagIfRaised,
ekvcFlagReset,
- ekvcFlagGetHeight,ekvcFlagGetHeights
+ ekvcFlagGetHeight,ekvcFlagGetHeights,
+ ekvcPass
}
,moretexcs=[3]^^A expkv-pkg macros
{
@@ -157,7 +159,7 @@ and the derived files expkv-cs.pdf
\def\mylstwd{.55em}
\lstset
{
- ,language=expkvd
+ ,language=expkvc
,flexiblecolumns=false
,basewidth=\mylstwd
,gobble=2
@@ -214,6 +216,7 @@ and the derived files expkv-cs.pdf
\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 @@ and the derived files expkv-cs.pdf
\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 @@ and the derived files expkv-cs.pdf
\@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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% \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,11 +398,36 @@ and the derived files expkv-cs.pdf
% 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
@@ -420,6 +454,20 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% \ekvcSplitAndForward\foo{\foo@aux{more args}}{keyA = A, keyB = B}
% \end{lstlisting}
% \end{function}
+% \noindent
+% In the first case |\foo@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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% \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,18 +559,26 @@ and the derived files expkv-cs.pdf
% \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}
% \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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% \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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% \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 @@ and the derived files expkv-cs.pdf
%
% 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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% \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,
-% }
-% {%
-% #1 is a #5 from #3. #6 is of #2 age and #7 hobby is #4.\par
+% 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}
% \end{lstlisting}
% Also we want to give some short cuts so that it's easier to describe several
% persons.
@@ -854,7 +1115,7 @@ and the derived files expkv-cs.pdf
% 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 the derived files expkv-cs.pdf
% 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@a{}}
@@ -957,6 +1220,70 @@ and the derived files expkv-cs.pdf
% \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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% {%
% \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 @@ and the derived files expkv-cs.pdf
% 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 @@ and the derived files expkv-cs.pdf
% \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 @@ and the derived files expkv-cs.pdf
% |\ekvc@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@tripledots}
+% This macro just serves as a marker for a comparison to allow the syntax
+% for the unknown key handlers.
+% \begin{macrocode}
+\def\ekvc@tripledots{...}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[internal]{\ekvc@keycount}
% We'll need to keep count how many keys must be defined for each macro in the
% |split| variants.
@@ -1334,7 +1672,8 @@ and the derived files expkv-cs.pdf
% \begin{macro}[internal]
% {
% \ekvc@SetupSplitKeys, \ekvc@SetupSplitKeys@a, \ekvc@SetupSplitKeys@b,
-% \ekvc@SetupSplitKeys@c
+% \ekvc@SetupSplitKeys@c,
+% \ekvc@SetupSplitKeys@check@unknown,\ekvc@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 @@ and the derived files expkv-cs.pdf
\ekvc@keycount=0
\let\ekvc@any@long\ekv@empty
\let\ekvc@initials\ekv@empty
- \ekvparse\ekvc@err@value@required\ekvc@SetupSplitKeys@a
+ \ekvparse\ekvc@SetupSplitKeys@check@unknown\ekvc@SetupSplitKeys@a
}
% \end{macrocode}
% Then we need to step the key counter for each key. Also we have to check
@@ -1421,6 +1760,47 @@ and the derived files expkv-cs.pdf
{}%
}
% \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@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@SetupSplitKeys@check@unknown#1%
+ {%
+ \begingroup
+ \edef\ekvc@tmp{\detokenize{#1}}%
+ \expandafter
+ \endgroup
+ \ifx\ekvc@tripledots\ekvc@tmp
+ \advance\ekvc@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@SetupSplitKeys@unknown
+ \csname ekvc@splitmark@\the\ekvc@keycount\endcsname
+ \let\ekvc@any@long\long
+ \else
+ \ekvc@err@value@required{#1}%
+ \fi
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\protected\long\def\ekvc@SetupSplitKeys@unknown#1%
+ {%
+ \long\expandafter\def\csname\ekv@name\ekvc@set{}u\endcsname##1##2##3#1##4%
+ {##3#1{##4,##2= {##1} }}%
+ \long\expandafter\def\csname\ekv@name\ekvc@set{}uN\endcsname##1##2#1##3%
+ {##2#1{##3,##1}}%
+ \edef\ekvc@initials{\unexpanded\expandafter{\ekvc@initials#1{}}}%
+ \ekvc@helpers@needed
+ {\expandafter\ekvc@setup@splitmacro\expandafter{\the\ekvc@keycount}}%
+ {}%
+ }
+% \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@split@p@long}
@@ -1436,6 +1816,14 @@ and the derived files expkv-cs.pdf
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[internal]{\ekvc@split@p@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@split@p@short{\ekvc@SetupSplitKeys@c}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[internal]{\ekvc@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 @@ and the derived files expkv-cs.pdf
% \end{macro}
%
% \begin{macro}[internal]
-% {\ekvc@SetupHashKeys,\ekvc@SetupHashKeys@a,\ekvc@SetupHashKeys@b}
+% {%
+% \ekvc@SetupHashKeys,\ekvc@SetupHashKeys@a,\ekvc@SetupHashKeys@b,
+% \ekvc@SetupHashKeys@c,
+% \ekvc@SetupHashKeys@check@unknown,\ekvc@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 @@ and the derived files expkv-cs.pdf
{%
\let\ekvc@any@long\ekv@empty
\let\ekvc@initials\ekv@empty
- \ekvparse\ekvc@err@value@required\ekvc@SetupHashKeys@a{#1}%
+ \ekvparse\ekvc@SetupHashKeys@check@unknown\ekvc@SetupHashKeys@a{#1}%
}
\protected\def\ekvc@SetupHashKeys@a#1%
{%
@@ -1685,6 +2077,39 @@ and the derived files expkv-cs.pdf
\ekvc@setup@hashmacro{#1}%
}
% \end{macrocode}
+% \begin{macrocode}
+\protected\long\def\ekvc@SetupHashKeys@check@unknown#1%
+ {%
+ \begingroup
+ \edef\ekvc@tmp{\detokenize{#1}}%
+ \expandafter
+ \endgroup
+ \ifx\ekvc@tripledots\ekvc@tmp
+ \ekvc@SetupHashKeys@unknown
+ \let\ekvc@any@long\long
+ \else
+ \ekvc@err@value@required{#1}%
+ \fi
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\def\ekvc@SetupHashKeys@unknown#1%
+ {%
+ \protected\def\ekvc@SetupHashKeys@unknown
+ {%
+ \expandafter
+ \let\csname\ekv@name\ekvc@set{}u\endcsname\ekvc@hash@unknown@kv
+ \expandafter
+ \let\csname\ekv@name\ekvc@set{}uN\endcsname\ekvc@hash@unknown@k
+ \edef\ekvc@initials{\unexpanded\expandafter{\ekvc@initials#1{}}}%
+ \ekvc@setup@hashmacro{...}%
+ }%
+ \long\def\ekvc@hash@unknown@kv##1##2##3#1##4{##3#1{##4,##2= {##1} }}%
+ \long\def\ekvc@hash@unknown@k##1##2#1##3{##2#1{##3,##1}}%
+ }
+\expandafter\ekvc@SetupHashKeys@unknown
+ \csname ekvc@hashmark@\ekvc@tripledots\endcsname
+% \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@hash@p@long}
@@ -1699,6 +2124,14 @@ and the derived files expkv-cs.pdf
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[internal]{\ekvc@hash@p@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@hash@p@short{\ekvc@SetupHashKeys@c}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[internal]{\ekvc@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,18 +2181,19 @@ and the derived files expkv-cs.pdf
\unexpanded\expandafter{\csname ekvc@hashmark@#1\endcsname}%
####2####3\unexpanded{\ekvc@stop}####4%
{%
- ####4{####1####3}{####2}%
+ ####4{####2}%
}%
\long\gdef\unexpanded\expandafter
{\csname ekvc@safesplithash@#1\endcsname}####1%
{%
\unexpanded\expandafter
{\csname ekvc@@safesplithash@#1\endcsname}%
- ####1\unexpanded{\ekvc@mark\ekvc@safe@found@hash}%
+ ####1\unexpanded{\ekvc@mark\ekvc@safe@after@hash}%
\unexpanded\expandafter
{%
\csname ekvc@hashmark@#1\endcsname{}%
- \ekvc@mark{\ekvc@err@missing@hash{#1}\ekvc@safe@no@hash}%
+ \ekvc@mark
+ {\ekvc@err@missing@hash{#1}\ekvc@safe@after@hash}%
\ekvc@stop
}%
}%
@@ -1770,7 +2204,7 @@ and the derived files expkv-cs.pdf
####2####3\unexpanded{\ekvc@mark}####4####5%
\unexpanded{\ekvc@stop}%
{%
- ####4{####2}####1####3\unexpanded{\ekvc@stop}%
+ ####4{####2}%
}%
}%
\ekvc@tmp
@@ -1812,22 +2246,15 @@ and the derived files expkv-cs.pdf
{\csname ekvc@safesplithash@#1\endcsname}%
{\ekvc@err@unknown@hash{#1}\ekvcValueSplit@recover}%
}
-\long\def\ekvcValueSplit@recover#1#2%
- {%
- #2{#1}{}%
- }
+\long\def\ekvcValueSplit@recover#1#2{#2{}}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekvc@safe@found@hash, \ekvc@safe@no@hash}
+% \begin{macro}[internal]{\ekvc@safe@after@hash}
% \begin{macrocode}
-\long\def\ekvc@safe@found@hash#1#2\ekvc@stop#3%
+\long\def\ekvc@safe@after@hash#1#2%
{%
- #3{#2}{#1}%
- }
-\long\def\ekvc@safe@no@hash#1#2\ekvc@mark\ekvc@safe@found@hash\ekvc@stop#3%
- {%
- #3{#2}{}%
+ #2{#1}%
}
% \end{macrocode}
% \end{macro}
@@ -1839,9 +2266,7 @@ and the derived files expkv-cs.pdf
% sequence.
% \begin{macrocode}
\long\def\ekvcValueSplitFast#1#2%
- {%
- \csname ekvc@fastsplithash@#1\endcsname#2\ekvc@stop
- }
+ {\csname ekvc@fastsplithash@#1\endcsname#2\ekvc@stop}
% \end{macrocode}
% \end{macro}
%
@@ -1858,8 +2283,8 @@ and the derived files expkv-cs.pdf
% \begin{macrocode}
\long\def\ekvc@safehash@#1{\ekvc@err@empty@hash{}}
\long\def\ekvc@fasthash@#1\ekvc@stop{\ekvc@err@empty@hash}
-\long\def\ekvc@safesplithash@#1#2{\ekvc@err@empty@hash#2{#1}{}}
-\long\def\ekvc@fastsplithash@#1\ekvc@stop#2{\ekvc@err@empty@hash#2{#1}{}}
+\long\def\ekvc@safesplithash@#1#2{\ekvc@err@empty@hash#2{}}
+\long\def\ekvc@fastsplithash@#1\ekvc@stop#2{\ekvc@err@empty@hash#2{}}
% \end{macrocode}
% \end{macro}
%
@@ -1894,6 +2319,116 @@ and the derived files expkv-cs.pdf
% \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@change|.
+% \begin{macrocode}
+\protected\long\def\ekvcChange#1%
+ {%
+ \ekvifdefinedset{\string#1}%
+ {%
+ \ekvc@ifdefined#1%
+ {\ekvc@change#1}%
+ {\ekvc@err@no@key@macro#1\@gobble}%
+ }%
+ {\ekvc@err@no@key@macro#1\@gobble}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvc@change,\ekvc@change@a,\ekvc@change@b,\ekvc@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@change#1%
+ {\expandafter\ekvc@change@a\meaning#1\ekv@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@change@a#1%
+ {%
+ \protected\def\ekvc@change@a##1#1##2->##3\ekv@stop
+ {%
+ \ekvc@change@iflong{##1}%
+ {\ekvc@change@b{}}%
+ {\ekvc@change@b{\long}}%
+ }%
+ }
+\expandafter\ekvc@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@change@b#1#2%
+ {\expandafter\ekvc@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@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@exparg{\protected\long\def\ekvc@change@c#1#2#3#4}%
+ {%
+ \expandafter\iffalse\expandafter{\expandafter\fi
+ \ekvset{\string#3}{#4}%
+ \ekvc@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@change@d#1#2%
+ {%
+ \def\ekvc@tmp{#1\def#2####1}%
+ \expandafter\ekvc@tmp\expandafter{\iffalse}\fi
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc@change@iflong,\ekvc@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@change@iflong#1%
+ {%
+ \protected\def\ekvc@change@iflong##1%
+ {\expandafter\ekv@ifempty\expandafter{\ekvc@change@iflong@##1#1}}%
+ \def\ekvc@change@iflong@##1#1{}
+ }
+\expandafter\ekvc@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@name{\string#1}{#2}\endcsname}%
+ {\ekvc@err@unknown@key@or@macro{#1}{#2}\@gobble}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
%
% \subsubsection{Secondary Key Types}
%
@@ -2287,7 +2822,7 @@ and the derived files expkv-cs.pdf
% \begin{macro}[internal]
% {
% \ekvc@err@toomany,\ekvc@err@value@required,\ekvc@err@missing@type,
-% \ekvc@err@already@defined
+% \ekvc@err@already@defined,\ekvc@err@no@key@macro
% }
% Boring unexpandable error messages.
% \begin{macrocode}
@@ -2322,6 +2857,8 @@ and the derived files expkv-cs.pdf
\errmessage
{expkv-cs Error: Unknown key `\unexpanded{#1}' for macro `\ekvc@set'}%
}
+\long\def\ekvc@err@no@key@macro#1%
+ {\errmessage{expkv-cs Error: \string#1 is no key=val macro}}
% \end{macrocode}
% \end{macro}
%
@@ -2343,6 +2880,8 @@ and the derived files expkv-cs.pdf
\long\def\ekvc@err@missing@hash#1{\ekvc@err{hash `#1' not found}}
\long\def\ekvc@err@empty@hash{\ekvc@err{empty hash}}
\def\ekvc@err@invalid@bool#1{\ekvc@err{invalid boolean value `#1'}}
+\long\def\ekvc@err@unknown@key@or@macro#1#2%
+ {\ekvc@err{unknown key `#2' for macro #1}}
% \end{macrocode}
% \end{macro}
%