texlive[56634] Master/texmf-dist: expkv (11oct20)
commits+karl at tug.org
commits+karl at tug.org
Sun Oct 11 22:49:37 CEST 2020
Revision: 56634
http://tug.org/svn/texlive?view=revision&revision=56634
Author: karl
Date: 2020-10-11 22:49:36 +0200 (Sun, 11 Oct 2020)
Log Message:
-----------
expkv (11oct20)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/expkv/README.md
trunk/Master/texmf-dist/doc/latex/expkv/expkv.pdf
trunk/Master/texmf-dist/source/latex/expkv/expkv.dtx
trunk/Master/texmf-dist/tex/generic/expkv/expkv.tex
Modified: trunk/Master/texmf-dist/doc/latex/expkv/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv/README.md 2020-10-11 20:49:19 UTC (rev 56633)
+++ trunk/Master/texmf-dist/doc/latex/expkv/README.md 2020-10-11 20:49:36 UTC (rev 56634)
@@ -1,7 +1,7 @@
-------------------------------------------------------------------------------
# expkv -- an expandable key=val implementation
-Version 2020-07-04 v1.4
+Version 2020-10-10 v1.5
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/expkv.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/source/latex/expkv/expkv.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv/expkv.dtx 2020-10-11 20:49:19 UTC (rev 56633)
+++ trunk/Master/texmf-dist/source/latex/expkv/expkv.dtx 2020-10-11 20:49:36 UTC (rev 56634)
@@ -70,6 +70,7 @@
\RequirePackage{array}
\RequirePackage{collcell}
\RequirePackage{siunitx}
+\DeclareSIUnit\ops{ops}
\RequirePackage{xcolor}
\RequirePackage{caption}
\RequirePackage{microtype}
@@ -102,6 +103,19 @@
\definecolor{expkvred}{HTML}{9F393D}
\colorlet{expkvgrey}{black!75}
\makeatletter
+\newcommand*\expFormat
+ {^^A
+ {^^A
+ \rmfamily
+ \bfseries
+ {\color{expkvgrey}e\kern-.05em x\kern-.05em}^^A
+ \lower.493ex\hbox{{\color{expkvgrey}P}}^^A
+ }^^A
+ }
+\newcommand*\kvstyle
+ {^^A
+ \normalfont\rmfamily\bfseries\color{expkvred}^^A
+ }
\newcommand*\expkv
{^^A
\texorpdfstring
@@ -158,7 +172,7 @@
\DoNotIndex{\def,\edef,\,,\=,\begingroup,\catcode,\chardef,\csname,\endcsname}
\DoNotIndex{\endgroup,\endinput,\errmessage,\expandafter,\input,\let,\long}
\DoNotIndex{\protected,\ProvidesFile,\ProvidesPackage,\relax,\space}
-\DoNotIndex{\@,\unexpanded,\string,\expanded,\detokenize}
+\DoNotIndex{\@,\unexpanded,\string,\expanded,\detokenize,\meaning,\lastnamedcs}
\DoNotIndex{\ifcsname}
\DoNotIndex{\ifx}
\DoNotIndex{\else}
@@ -182,7 +196,10 @@
{^^A
\huge\expkv
\\[\medskipamount]
- \Large an expandable \kv\ implementation^^A
+ \Large an {\expFormat}andable
+ \meta{{\kvstyle k}\kern-.05em ey}=^^A
+ \meta{{\kvstyle v}\kern-.05em alue}
+ implementation^^A
}{expkv - an expandable <key>=<value> implementation}^^A
}
\date{\ekvDate\space v\ekvVersion}
@@ -198,10 +215,10 @@
% \begin{abstract}
% \noindent\parfillskip=0pt
% \expkv\ provides a small interface for \kv\ parsing. The parsing macro is
-% fully expandable, the \meta{code} of your keys might be not. \expkv\ is pretty
-% fast, but not the fastest available \kv\ solution (\pkg{keyval} is one and a
-% half times as fast, but not expandable and it might strip braces it shouldn't
-% have stripped).
+% \emph{fully expandable}, the \meta{code} of your keys might be not. \expkv\ is
+% \emph{swift}, close to the fastest \kv\ implementation. However it is the
+% fastest which copes with active commas and equal signs and doesn't strip
+% braces accidentally.
% \end{abstract}
%
% \tableofcontents
@@ -259,7 +276,7 @@
% prefixes allowed for |\let| can prefix those with ``|let|'' in their name,
% accordingly. Neither \set\ nor \key\ are allowed to be empty for new keys.
% \set\ will be used as is inside of |\csname ...\endcsname| and \key\ will get
-% \cs[no-index]{detokenize}d.
+% |\detokenize|d.
%
% \begin{function}{\ekvdef}
% \begin{syntax}
@@ -297,7 +314,8 @@
% \cs{ekvletkv}\marg{set}\marg{key}\marg{set2}\marg{key2}
% \end{syntax}
% Let the \key\ in \set\ to \meta{key2} in \meta{set2}, it is not checked
-% whether that second key exists.
+% whether that second key exists (but take a look at
+% \cs[no-index]{ekvifdefined}).
% \end{function}
%
% \begin{function}{\ekvletkvNoVal}
@@ -305,7 +323,8 @@
% \cs{ekvletkvNoVal}\marg{set}\marg{key}\marg{set2}\marg{key2}
% \end{syntax}
% Let the \key\ in \set\ to \meta{key2} in \meta{set2}, it is not checked
-% whether that second key exists.
+% whether that second key exists (but take a look at
+% \cs[no-index]{ekvifdefinedNoVal}).
% \end{function}
%
% \begin{function}{\ekvdefunknown}
@@ -349,6 +368,16 @@
% |\ekvset| should be nestable.
% \end{function}
%
+% \begin{function}{\ekvsetSneaked}
+% \begin{syntax}
+% \cs{ekvsetSneaked}\marg{set}\marg{sneak}\{\kv,\ldots\}
+% \end{syntax}
+% Just like \cs[no-index]{ekvset}, this macro parses the \kv\ pairs within the
+% given \set. But \cs[no-index]{ekvsetSneaked} will behave as if
+% \cs[no-index]{ekvsneak} has been called with \meta{sneak} as its argument as
+% the first action.
+% \end{function}
+%
% \begin{function}{\ekvsetdef}
% \begin{syntax}
% \cs{ekvsetdef}\meta{cs}\marg{set}
@@ -355,12 +384,43 @@
% \end{syntax}
% With this function you can define a shorthand macro \meta{cs} to parse keys
% of a specified \set. It is always defined |\long|, but if you need to you
-% can also prefix it with |\global|. The resulting macro is a bit faster than
-% the idiomatic definition:\par
+% can also prefix it with |\global|. The resulting macro is faster than but
+% else equivalent to the idiomatic definition:\par
% \texttt
% {\string\long\string\def\meta{cs}\#1\{\string\ekvset\marg{set}\{\#1\}\}}
% \end{function}
%
+% \begin{function}{\ekvsetSneakeddef}
+% \begin{syntax}
+% \cs{ekvsetSneakeddef}\meta{cs}\marg{set}
+% \end{syntax}
+% Just like \cs[no-index]{ekvsetdef} this defines a shorthand macro \meta{cs},
+% but this macro will make it a shorthand for \cs[no-index]{ekvsetSneaked},
+% meaning that \meta{cs} will take two arguments, the first being stuff that
+% should be given to \cs[no-index]{ekvsneak} and the second the \kv\ list. The
+% resulting macro is faster than but else equivalent to the idiomatic
+% definition:\par
+% \texttt
+% {%
+% \string\long\string\def\meta{cs}\#1\#2\{^^A
+% \string\ekvsetSneaked\marg{set}\{\#1\}\{\#2\}\}^^A
+% }
+% \end{function}
+%
+% \begin{function}{\ekvsetdefSneaked}
+% \begin{syntax}
+% \cs{ekvsetSneakeddef}\meta{cs}\marg{set}\marg{sneaked}
+% \end{syntax}
+% And this one behaves like \cs[no-index]{ekvsetSneakeddef} but with a fixed
+% \meta{sneaked} argument. So the resulting macro is faster than but else
+% equivalent to the idiomatic definition:\par
+% \texttt
+% {%
+% \string\long\string\def\meta{cs}\#1\{^^A
+% \string\ekvsetSneaked\marg{set}\marg{sneaked}\{\#1\}\}^^A
+% }
+% \end{function}
+%
% \begin{function}{\ekvparse}
% \begin{syntax}
% \cs{ekvparse}\meta{cs1}\meta{cs2}\{\kv,\ldots\}
@@ -457,8 +517,9 @@
% \meta{after} after any other tokens which might have been sneaked before,
% while |\ekvsneakPre| will put \meta{after} before other smuggled stuff.
% This reads and reinserts the remainder of the current |\ekvset| macro and
-% its argument list to do its job. A small usage example is shown in
-% \autoref{sec:sneakex}.
+% its argument list to do its job. After |\ekvset| has parsed the entire \kv\
+% list everything that has been |\ekvsneak|ed will be left in the input
+% stream. A small usage example is shown in \autoref{sec:sneakex}.
% \end{function}
%
% \begin{function}{\ekvchangeset}
@@ -481,20 +542,17 @@
% \cs{ekv at name@key}\marg{key}
% \end{syntax}
% The names of the macros that correspond to a key in a set are build with
-% these macros. The default definition of |\ekv at name@set| is
-% ``\texttt{\csname ekv at name@set\endcsname{\set}}'' and the default of
-% |\ekv at name@key| is ``\texttt{\csname ekv at name@key\endcsname{\key}}''.
-% The complete name is build using |\ekv at name| which is equivalent to
-% \texttt
-% {^^A
-% \cs[no-index]{ekv at name@set}\marg{set}\cs{ekv at name@key}^^A
-% \{\cs[no-index]{detokenize}\marg{key}\}^^A
-% }.
+% these macros. The name is built from two blocks, one that is formatting the
+% \set\ name (|\ekv at name@set|) and one for formatting the \key\ name
+% (|\ekv at name@key|). To get the actual name the argument to |\ekv at name@key|
+% must be |\detokenize|d. Both blocks are put together (with the necessary
+% |\detokenize|) by |\ekv at name|.
% For |NoVal| keys an additional |N| gets appended irrespective of these
% macros' definition, so their name is
-% \cs[no-index]{\csname ekv at name\endcsname{\set}{\key}N}. You might redefine
-% |\ekv at name@set| and |\ekv at name@key| locally but \emph{don't redefine}
-% |\ekv at name|!
+% \texttt{\cs[no-index]{ekv at name}\marg{set}\marg{key}N}.\par
+% You can use these macros to implement additional functionality or access key
+% macros outside of \expkv, but \emph{don't} change them! \expkv\ relies on
+% their exact definitions internally.
% \end{function}
%
% \subsubsection{Bugs}
@@ -510,7 +568,8 @@
% \pkg{l3benchmark} package. The key and its usage should be equivalent to
% \begin{lstlisting}
% \protected\ekvdef{test}{height}{\def\myheight{#1}}
-% \ekvset{test}{ height = 6 }
+% \ekvsetdef\expkvtest{test}
+% \expkvtest{ height = 6 }
% \end{lstlisting}
% and only the usage of the key, not its definition, is benchmarked. For the
% impatient, the essence of these comparisons regarding speed and buggy
@@ -527,14 +586,17 @@
% contained, as most other packages don't provide equivalent features to my
% knowledge. |\ekvparse| is slightly faster than |\ekvset|, but keep in mind
% that it does less. The same is true for |\keyval_parse:NNn| compared to
-% |\keys_set:nn| of \pkg{expl3} (where the difference is much bigger).
+% |\keys_set:nn| of \pkg{expl3} (where the difference is much bigger). Comparing
+% just the two, |\ekvparse| is a tad faster than |\keyval_parse:NNn| because of
+% the two tests (for empty key names and only a single equal sign) which are
+% omitted.
%
-% \paragraph{\pkg{keyval}} is about $1.6$ times faster and has a comparable
-% feature set just a slightly different way how it handles keys without values.
-% That might be considered a drawback, as it limits the versatility, but also as
-% an advantage, as it might reduce doubled code. Keep in mind that as soon as
-% someone loads \pkg{xkeyval} the performance of \pkg{keyval} gets replaced by
-% \pkg{xkeyval}'s.
+% \paragraph{\pkg{keyval}} is about \SIrange{30}{40}{\percent} faster and has a
+% comparable feature set just a slightly different way how it handles keys
+% without values. That might be considered a drawback, as it limits the
+% versatility, but also as an advantage, as it might reduce doubled code. Keep
+% in mind that as soon as someone loads \pkg{xkeyval} the performance of
+% \pkg{keyval} gets replaced by \pkg{xkeyval}'s.
%
% Also \pkg{keyval} has a bug, which unfortunately can't really be resolved
% without breaking backwards compatibility for \emph{many} documents, namely it
@@ -545,49 +607,58 @@
% \begin{lstlisting}[belowskip=0pt]
% \setkeys{foo}{bar=baz}
% \setkeys{foo}{bar= {baz}}
-% \setkeys{foo}{bar={ baz}}
-% \setkeys{foo}{bar={{baz}}}
+% \setkeys{foo}{bar={ baz}} % should be ` baz'
+% \setkeys{foo}{bar={{baz}}} % should be `{baz}'
% \end{lstlisting}
%
-% \paragraph{\pkg{xkeyval}} is roughly seventeen times slower, but it provides
-% more functionality, e.g., it has choice keys, boolean keys, and so on. It
-% contains the same bug as \pkg{keyval} as it has to be compatible with it by
-% design (it replaces \pkg{keyval}'s frontend), but also adds even more cases in
-% which braces are stripped that shouldn't be stripped, worsening the situation.
+% \paragraph{\pkg{xkeyval}} is roughly twenty times slower, but it provides more
+% functionality, e.g., it has choice keys, boolean keys, and so on. It contains
+% the same bug as \pkg{keyval} as it has to be compatible with it by design (it
+% replaces \pkg{keyval}'s frontend), but also adds even more cases in which
+% braces are stripped that shouldn't be stripped, worsening the situation.
%
-% \paragraph{\pkg{ltxkeys}} is over 370 times slower -- which is funny, because
-% it aims to be ``[\ldots] faster [\ldots] than these earlier packages
-% [referring to \pkg{keyval} and \pkg{xkeyval}].'' It needs more time to parse
-% zero keys than four of the packages in this comparison need to parse 100 keys.
-% Since it aims to have a bigger feature set than \pkg{xkeyval}, it most
-% definitely also has a bigger feature set than \expkv. Also, it can't parse
-% |\long| input, so as soon as your values contain a |\par|, it'll throw errors.
-% Furthermore, \pkg{ltxkeys} doesn't strip outer braces at all by design, which,
-% imho, is a weird design choice. In addition \pkg{ltxkeys} loads
+% \paragraph{\pkg{ltxkeys}} is no longer compatible with the \LaTeX\ kernel
+% starting with the release 2020-10-01. It is over 380 times slower -- which is
+% funny, because it aims to be ``[\ldots] faster [\ldots] than these earlier
+% packages [referring to \pkg{keyval} and \pkg{xkeyval}].'' It needs more time
+% to parse zero~keys than five of the packages in this comparison need to parse
+% 100~keys. Since it aims to have a bigger feature set than \pkg{xkeyval}, it
+% most definitely also has a bigger feature set than \expkv. Also, it can't
+% parse |\long| input, so as soon as your values contain a |\par|, it'll throw
+% errors. Furthermore, \pkg{ltxkeys} doesn't strip outer braces at all by
+% design, which, imho, is a weird design choice. In addition \pkg{ltxkeys} loads
% \pkg{catoptions} which is known to introduce bugs (e.g., see
-% \url{https://tex.stackexchange.com/questions/461783}).
+% \url{https://tex.stackexchange.com/questions/461783}). Because it is no longer
+% compatible with the kernel, I stop benchmarking it (so the numbers listed here
+% and in \autoref{tab:comp} regarding \pkg{ltxkeys} were last updated on
+% 2020-10-05).
%
-% \paragraph{\pkg{l3keys}} is around six times slower, but has an, imho, great
-% interface to define keys. It strips \emph{all} outer spaces, even if somehow
-% multiple spaces ended up on either end. It offers more features, but is pretty
-% much bound to \pkg{expl3} code. Whether that's a drawback is up to you. Note
-% that this comparison uses the version contained in \TeX Live 2019 (frozen)
-% which is a bit slower than versions starting with \TeX Live 2020.
+% \paragraph{\pkg{l3keys}} is around four and a half times slower, but has an,
+% imho, great interface to define keys. It strips \emph{all} outer spaces, even
+% if somehow multiple spaces ended up on either end. It offers more features,
+% but is pretty much bound to \pkg{expl3} code. Whether that's a drawback is up
+% to you.
%
-% \paragraph{\pkg{pgfkeys}} is around $2.7$ times slower for one key,
-% but has an \emph{enormous} feature set.
+% \paragraph{\pkg{pgfkeys}} is around \num{2.7} times slower for one key if one
+% uses the |/|\meta{path}|/.cd| syntax and almost \SI{20}{\percent} slower if
+% one uses |\pgfqkeys|, but has an \emph{enormous} feature set.
+% To get the best performance |\pgfqkeys| was used in the benchmark. This
+% reduces the overhead for setting the base directory of the benchmark keys by
+% about \SI{43}{\ops} (so both $p_0$ and $T_0$ would be about \SI{43}{\ops}
+% bigger if |\pgfkeys{|\meta{path}|/.cd,|\meta{keys}|}| was used instead).
% It has the same or a very similar bug \pkg{keyval} has. The brace bug (and
% also the category fragility) can be fixed by \pkg{pgfkeyx}, but this package
-% was last updated in 2012 and it slows down |\pgfkeys| by factor~$8$. Also I
-% don't know whether this might introduce new bugs.
+% was last updated in 2012 and it slows down |\pgfkeys| by factor~\num{8}. Also
+% \pkg{pgfkeyx} is no longer compatible with versions of \pkg{pgfkeys} newer
+% than 2020-05-25.
%
-% \paragraph{\pkg{kvsetkeys} with \pkg{kvdefinekeys}} is about $3.7$ times
+% \paragraph{\pkg{kvsetkeys} with \pkg{kvdefinekeys}} is about \num{4.4} times
% slower, but it works even if commas and equals have category codes different
% from 12 (just as some other packages in this list). Else the features of the
% keys are equal to those of \pkg{keyval}, the parser has more features, though.
%
-% \paragraph{\pkg{options}} is $1.5$ times slower for only a single value. It
-% has a much bigger feature set. Unfortunately it also suffers from the
+% \paragraph{\pkg{options}} is \num{1.7} times slower for only a single value.
+% It has a much bigger feature set. Unfortunately it also suffers from the
% premature unbracing bug \pkg{keyval} has.
%
% \paragraph{\pkg{simplekv}} is hard to compare because I don't speak French (so
@@ -597,10 +668,11 @@
% packages. It has problems with stripping braces and spaces in a hard to
% predict manner just like \pkg{keyval}. Also, while it tries to be robust
% against category code changes of commas and equal signs, the used mechanism
-% fails if the \kv\ list already got tokenized. Regarding unknown keys it got a
+% fails if the \kv\ list already got tokenised. Regarding unknown keys it got a
% very interesting behaviour. It doesn't throw an error, but stores the \val\ in
% a new entry accessible with \cs[no-index]{useKV}. Also if you omit \val\ it
-% stores |true| for that \key. It is around $10\,\%$ faster than \expkv.
+% stores |true| for that \key. For up to three keys, \expkv\ is a bit faster,
+% for more keys \pkg{simplekv} takes the lead.
%
% \paragraph{\pkg{yax}} is over twenty times slower. It has a pretty strange
% syntax, imho, and again a direct equivalent is hard to define. It has the
@@ -640,16 +712,16 @@
% \toprule
% \rmfamily Package & {$p_1$} & {$p_0$} & {$T_0$}& BB & CF & Date \\
% \midrule
-% keyval & 13.694 & 1.504 & 7.008 & \yes & \yes & 2014-10-28 \\
-% simplekv & 18.739 & 5.325 & 17.68 & \yes & \yes & 2020-04-27 \\
-% \expkv & 22.007 & 3.100 & 10.095 & \no & \no & 2020-06-21 \\
-% options & 24.351 & 12.010 & 20.38 & \yes & \yes & 2015-03-01 \\
-% pgfkeys & 24.621 & 45.474 & 53.25 & \yes & \yes & 2020-06-17 \\
-% kvsetkeys & {\fnsym} & {\fnsym} & 40.0 & \no & \no & 2019-12-15 \\
-% l3keys & 92.103 & 32.724 & 38.05 & \no & \no & 2020-06-18 \\
-% xkeyval & 257.125 & 173.704 & 164.5 & \yes & \yes & 2014-12-03 \\
-% yax & 440.234 & 76.276 & 113.9 & \yes & \yes & 2010-01-22 \\
-% ltxkeys & 3448.339 & 4470.031 & 5241.0 & \no & \no & 2012-11-17 \\
+% keyval & 13.742 & 1.486 & 7.254 & \yes & \yes & 2014-10-28 \\
+% \expkv & 19.701 & 2.169 & 6.592 & \no & \no & 2020-10-10 \\
+% simplekv & 18.334 & 6.971 & 17.710 & \yes & \yes & 2020-04-27 \\
+% pgfkeys & 24.274 & 1.725 & 10.650 & \yes & \yes & 2020-09-05 \\
+% options & 23.600 & 15.638 & 20.830 & \yes & \yes & 2015-03-01 \\
+% kvsetkeys & {\fnsym} & {\fnsym} & 40.290 & \no & \no & 2019-12-15 \\
+% l3keys & 71.309 & 33.131 & 31.590 & \no & \no & 2020-09-24 \\
+% xkeyval & 253.563 & 202.246 & 168.300 & \yes & \yes & 2014-12-03 \\
+% yax & 421.853 & 157.003 & 114.700 & \yes & \yes & 2010-01-22 \\
+% ltxkeys & 3400.142 & 4737.958 & 5368.000 & \no & \no & 2012-11-17 \\
% \bottomrule
% \end{tabular}
% \par
@@ -658,12 +730,12 @@
% \fnsym For \pkg{kvsetkeys} the linear model used for the other
% packages is a poor fit, \pkg{kvsetkeys} seems to have approximately
% quadratic run-time, the coefficients of the second degree polynomial fit are
-% $p_2=\num{8.811}$, $p_1=\num{36.015}$, and $p_0=\num{81.792}$. Of course the
+% $p_2=\num{8.240}$, $p_1=\num{44.862}$, and $p_0=\num{60.793}$. Of course the
% other packages might not really have linear run-time, but at least from 1~to
% 20~keys the fits don't seem too bad. If one extrapolates the fits for 100
% \kv\ pairs one finds that most of them match pretty well, the exception
% being \pkg{ltxkeys}, which behaves quadratic as well with
-% $p_2=\num{29.496}$, $p_1=\num{2828.933}$, and $p_0=\num{6741.189}$.
+% $p_2=\num{23.500}$, $p_1=\num{2906.634}$, and $p_0=\num{6547.489}$.
% \end{table}
%
% \subsection{Examples}
@@ -672,7 +744,7 @@
%
% Say we have a macro for which we want to create a \kv\ interface. The macro
% has a parameter, which is stored in the dimension |\ourdim| having a default
-% value from its initialization. Now we want to be able to change that dimension
+% value from its initialisation. Now we want to be able to change that dimension
% with the |width| key to some specified value. For that we'd do
% \begin{lstlisting}
% \newdimen\ourdim
@@ -1010,8 +1082,8 @@
% \begin{macro}{\ekvVersion,\ekvDate}
% We're on our first input, so lets store the version and date in a macro.
% \begin{macrocode}
-\def\ekvVersion{1.4}
-\def\ekvDate{2020-07-04}
+\def\ekvVersion{1.5}
+\def\ekvDate{2020-10-10}
% \end{macrocode}
% \end{macro}
%
@@ -1034,6 +1106,34 @@
% restore it at the end of the file, we never care for the actual definition of
% it.
%
+% \begin{macro}[internal]{\ekv at if@lastnamedcs}
+% If the primitive |\lastnamedcs| is available, we can be a bit faster than
+% without it. So we test for this and save the test's result in this macro.
+% \begin{macrocode}
+\begingroup
+ \edef\ekv at tmpa{\string \lastnamedcs}
+ \edef\ekv at tmpb{\meaning\lastnamedcs}
+ \ifx\ekv at tmpa\ekv at tmpb
+ \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##1}}
+ \else
+ \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##2}}
+ \fi
+ \expandafter
+\endgroup
+\ekv at if@lastnamedcs
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at empty}
+% Sometimes we have to introduce a token to prevent accidental brace stripping.
+% This token would then need to be removed by |\@gobble| or similar. Instead we
+% can use |\ekv at empty| which will just expand to nothing, that is faster than
+% gobbling an argument.
+% \begin{macrocode}
+\def\ekv at empty{}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[internal]
% {
% \@gobble,\@firstofone,\@firstoftwo,\@secondoftwo,
@@ -1112,28 +1212,89 @@
%
% \begin{macro}[internal]{\ekv at ifdefined}
% We'll need to check whether something is defined quite frequently, so why not
-% define a macro that does this. The following test is expandable, slower than
-% the typical expandable test for undefined control sequences, but faster for
-% defined ones. Since we want to be as fast as possible for correct input, this
-% is to be preferred.
+% define a macro that does this. The following test is expandable and pretty
+% fast. The version with |\lastnamedcs| is the fastest version to test for an
+% undefined macro I know of (that considers both undefined macros and those with
+% the meaning |\relax|).
% \begin{macrocode}
-\def\ekv at ifdefined#1%
+\ekv at if@lastnamedcs
{%
- \expandafter
- \ifx\csname\ifcsname #1\endcsname #1\else relax\fi\endcsname\relax
- \ekv at fi@secondoftwo
- \fi
- \@firstoftwo
+ \def\ekv at ifdefined#1{\ifcsname#1\endcsname\ekv at ifdef@\fi\@secondoftwo}
+ \def\ekv at ifdef@\fi\@secondoftwo
+ {%
+ \fi
+ \expandafter\ifx\lastnamedcs\relax
+ \ekv at fi@secondoftwo
+ \fi
+ \@firstoftwo
+ }
}
+ {%
+ \def\ekv at ifdefined#1%
+ {%
+ \ifcsname#1\endcsname\ekv at ifdef@\fi\ekv at ifdef@false#1\endcsname\relax
+ \ekv at fi@secondoftwo
+ \fi
+ \@firstoftwo
+ }
+ \def\ekv at ifdef@\fi\ekv at ifdef@false{\fi\expandafter\ifx\csname}
+ \long\def\ekv at ifdef@false
+ #1\endcsname\relax\ekv at fi@secondoftwo\fi\@firstoftwo#2#3%
+ {#3}
+ }
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[internal]{\ekv at strip,\ekv at strip@a,\ekv at strip@b,\ekv at strip@c}
+% We borrow some ideas of \pkg{expl3}'s \pkg{l3tl} to strip spaces
+% from keys and values. This |\ekv at strip| also strips one level of outer braces
+% \emph{after} stripping spaces, so an input of | {abc} | becomes |abc| after
+% stripping. It should be used with |#1| prefixed by |\ekv at mark|. Also this
+% implementation at most strips \emph{one} space from both sides (which should
+% be fine most of the time, since \TeX\ reads consecutive spaces as a single one
+% during tokenisation).
+% \begin{macrocode}
+\def\ekv at strip#1%
+ {%
+ \long\def\ekv at strip##1%
+ {%
+ \ekv at strip@a
+ ##1\ekv at nil
+ \ekv at mark#1%
+ #1\ekv at nil
+ \ekv at stop
+ }%
+ \long\def\ekv at strip@a##1\ekv at mark#1{\ekv at strip@b##1\ekv at mark}%
+ \long\def\ekv at strip@b##1#1\ekv at nil {\ekv at strip@c##1\ekv at nil}%
+ }
+\ekv at strip{ }
+\long\def\ekv at strip@c\ekv at mark#1\ekv at nil\ekv at mark#2\ekv at nil\ekv at stop#3{#3{#1}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekv at expB@unbraceA,\ekv at expB@unbraceA@}
+% To reduce some code doublets while gaining some speed, it is often useful to
+% expand the first token in a definition once. Let's define a wrapper for this.
+% \begin{macrocode}
+\long\def\ekv at expB@unbraceA#1#2%
+ {%
+ \expandafter\ekv at expB@unbraceA@\expandafter{#2}{#1}%
+ }
+\long\def\ekv at expB@unbraceA@#1#2{#2{#1}}%
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\ekv at name,\ekv at name@set,\ekv at name@key}
% The keys will all follow the same naming scheme, so we define it here.
% \begin{macrocode}
-\def\ekv at name#1#2{\ekv at name@set{#1}\ekv at name@key{\detokenize{#2}}}
\def\ekv at name@set#1{ekv#1(}
\def\ekv at name@key#1{#1)}
+\edef\ekv at name
+ {%
+ \unexpanded\expandafter{\ekv at name@set{#1}}%
+ \unexpanded\expandafter{\ekv at name@key{\detokenize{#2}}}%
+ }
+\ekv at expB@unbraceA{\def\ekv at name#1#2}{\ekv at name}
% \end{macrocode}
% \end{macro}
%
@@ -1158,23 +1319,28 @@
% package if an |\outer| has been gobbled this way. I consider that good,
% because keys shouldn't be defined |\outer| anyways.
% \begin{macrocode}
-\protected\def\ekv at checkvalid#1#2%
+\edef\ekv at checkvalid
{%
- \ekv at ifempty{#1}%
- {%
+ \unexpanded\expandafter{\ekv at ifempty{#1}}%
+ \unexpanded
+ {{%
\def\ekv at tmp{}%
\errmessage{expkv Error: empty set name not allowed}%
- }%
+ }}%
{%
- \ekv at ifempty{#2}%
+ \unexpanded\expandafter{\ekv at ifempty{#2}}%
+ \unexpanded
{%
- \def\ekv at tmp{}%
- \errmessage{expkv Error: empty key name not allowed}%
+ {%
+ \def\ekv at tmp{}%
+ \errmessage{expkv Error: empty key name not allowed}%
+ }%
+ \@secondoftwo
}%
- \@secondoftwo
}%
- \@gobble
+ \unexpanded{\@gobble}%
}
+\ekv at expB@unbraceA{\protected\def\ekv at checkvalid#1#2}{\ekv at checkvalid}%
% \end{macrocode}
% \end{macro}
%
@@ -1181,8 +1347,10 @@
% \begin{macro}{\ekvifdefined,\ekvifdefinedNoVal}
% And provide user-level macros to test whether a key is defined.
% \begin{macrocode}
-\def\ekvifdefined#1#2{\ekv at ifdefined{\ekv at name{#1}{#2}}}
-\def\ekvifdefinedNoVal#1#2{\ekv at ifdefined{\ekv at name{#1}{#2}N}}
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\def\ekvifdefined#1#2}}%
+ {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}}}
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\def\ekvifdefinedNoVal#1#2}}%
+ {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}N}}
% \end{macrocode}
% \end{macro}
%
@@ -1191,74 +1359,71 @@
% \ekvdef,\ekvdefNoVal,\ekvlet,\ekvletNoVal,\ekvletkv,\ekvletkvNoVal,
% \ekvdefunknown,\ekvdefunknownNoVal
% }
-% Set up the key defining macros |\ekvdef| etc.
+% Set up the key defining macros |\ekvdef| etc. We use temporary macros to set
+% these up with a few expansions already done.
% \begin{macrocode}
-\protected\long\def\ekvdef#1#2#3%
+\def\ekvdef#1#2#3#4%
{%
- \ekv at checkvalid{#1}{#2}%
+ \protected\long\def\ekvdef##1##2##3%
+ {#1{\expandafter\def\csname#2\endcsname####1{##3}#3}}%
+ \protected\long\def\ekvdefNoVal##1##2##3%
+ {#1{\expandafter\def\csname#2N\endcsname{##3}#3}}%
+ \protected\def\ekvlet##1##2##3%
+ {#1{\expandafter\let\csname#2\endcsname##3#3}}%
+ \protected\def\ekvletNoVal##1##2##3%
+ {#1{\expandafter\let\csname#2N\endcsname##3#3}}%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+ \protected\long\def\ekvdefunknown##1##2}}}%
{%
- \expandafter\def\csname\ekv at name{#1}{#2}\endcsname##1{#3}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ \expandafter\ekv at expB@unbraceA@\expandafter
+ {%
+ \expandafter\expandafter\expandafter
+ \def\expandafter\csname\ekv at name{##1}{}u\endcsname####1####2{##2}%
+ #3%
+ }%
+ {\ekv at checkvalid{##1}.}%
}%
- }
-\protected\long\def\ekvdefNoVal#1#2#3%
- {%
- \ekv at checkvalid{#1}{#2}%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+ \protected\long\def\ekvdefunknownNoVal##1##2}}}%
{%
- \expandafter\def\csname\ekv at name{#1}{#2}N\endcsname{#3}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ \expandafter\ekv at expB@unbraceA@\expandafter
+ {%
+ \expandafter\expandafter\expandafter
+ \def\expandafter\csname\ekv at name{##1}{}uN\endcsname####1{##2}%
+ #3%
+ }%
+ {\ekv at checkvalid{##1}.}%
}%
- }
-\protected\def\ekvlet#1#2#3%
- {%
- \ekv at checkvalid{#1}{#2}%
+ \protected\def\ekvletkv##1##2##3##4%
{%
- \expandafter\let\csname\ekv at name{#1}{#2}\endcsname#3%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ #1%
+ {%
+ \expandafter\let\csname#2\expandafter\endcsname
+ \csname#4\endcsname
+ #3%
+ }%
}%
- }
-\protected\def\ekvletNoVal#1#2#3%
- {%
- \ekv at checkvalid{#1}{#2}%
+ \protected\def\ekvletkvNoVal##1##2##3##4%
{%
- \expandafter\let\csname\ekv at name{#1}{#2}N\endcsname#3%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ #1%
+ {%
+ \expandafter\let\csname#2N\expandafter\endcsname
+ \csname#4N\endcsname
+ #3%
+ }%
}%
}
-\protected\def\ekvletkv#1#2#3#4%
+\edef\ekvdefNoVal
{%
- \ekv at checkvalid{#1}{#2}%
- {%
- \expandafter\let\csname\ekv at name{#1}{#2}\expandafter\endcsname
- \csname\ekv at name{#3}{#4}\endcsname
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
- }%
- }
-\protected\def\ekvletkvNoVal#1#2#3#4%
- {%
- \ekv at checkvalid{#1}{#2}%
- {%
- \expandafter\let\csname\ekv at name{#1}{#2}N\expandafter\endcsname
- \csname\ekv at name{#3}{#4}N\endcsname
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
- }%
- }
-\protected\def\ekvdefunknown#1#2%
- {%
- \ekv at checkvalid{#1}{.}%
- {%
- \expandafter\def\csname\ekv at name{#1}{}u\endcsname##1##2{#2}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
- }%
- }
-\protected\def\ekvdefunknownNoVal#1#2%
- {%
- \ekv at checkvalid{#1}{.}%
- {%
- \expandafter\def\csname\ekv at name{#1}{}uN\endcsname##1{#2}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
- }%
- }
+ {\unexpanded\expandafter{\ekv at checkvalid{#1}{#2}}}%
+ {\unexpanded\expandafter{\ekv at name{#1}{#2}}}%
+ {%
+ \unexpanded{\expandafter\ekv at defsetmacro\csname}%
+ \unexpanded\expandafter{\ekv at undefined@set{#1}\endcsname{#1}}%
+ }%
+ {\unexpanded\expandafter{\ekv at name{#3}{#4}}}%
+ }%
+\expandafter\ekvdef\ekvdefNoVal
% \end{macrocode}
% \end{macro}
%
@@ -1267,20 +1432,24 @@
% into a control sequence pretty early, so we have to define that control
% sequence.
% \begin{macrocode}
-\protected\def\ekv at defsetmacro#1#2%
+\edef\ekv at defsetmacro
{%
- \ifx#1\relax
- \edef#1##1{\ekv at name@set{#2}\ekv at name@key{\noexpand\detokenize{##1}}}%
- \fi
+ \unexpanded{\ifx#1\relax\edef#1##1}%
+ {%
+ \unexpanded\expandafter{\ekv at name@set{#2}}%
+ \unexpanded\expandafter{\ekv at name@key{##1}}%
+ }%
+ \unexpanded{\fi}%
}
+\ekv at expB@unbraceA{\protected\def\ekv at defsetmacro#1#2}{\ekv at defsetmacro}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvifdefinedset}
% \begin{macrocode}
-\def\ekvifdefinedset#1%
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\def\ekvifdefinedset#1}}%
{%
- \ekv at ifdefined{\ekv at undefined@set{#1}}%
+ \expandafter\ekv at ifdefined\expandafter{\ekv at undefined@set{#1}}%
}
% \end{macrocode}
% \end{macro}
@@ -1294,11 +1463,13 @@
% |#1| will be a \texttt{,\textsubscript{13}} and |#2| will be a
% \texttt{=\textsubscript{13}}.
% \begin{macrocode}
+\begingroup
\def\ekvset#1#2{%
\endgroup
-\long\def\ekvset##1##2%
+\ekv at expB@unbraceA{\long\def\ekvset##1##2}%
{%
- \expandafter\ekv at set\csname\ekv at undefined@set{##1}\endcsname
+ \expandafter\expandafter\expandafter
+ \ekv at set\expandafter\csname\ekv at undefined@set{##1}\endcsname
\ekv at mark##2#1\ekv at stop#1{}%
}
% \end{macrocode}
@@ -1315,13 +1486,9 @@
% \begin{macrocode}
\ekv at gobble@from at mark@to at stop##2\ekv at endset\ekv at stop
% \end{macrocode}
-% else go on with other commas,
+% else go on with other commas.
% \begin{macrocode}
\ekv at set@other##1##2,\ekv at stop,%
-% \end{macrocode}
-% and get the next active comma delimited \kv\ pair.
-% \begin{macrocode}
- \ekv at set##1\ekv at mark
}
% \end{macrocode}
% \end{macro}
@@ -1331,9 +1498,8 @@
% of |\ekv at set| and unbrace the sneaked stuff.
% \begin{macrocode}
\long\def\ekv at endset
- \ekv at stop\ekv at set@other##1,\ekv at stop,\ekv at set##2\ekv at mark
- ##3%
- {##3}
+ \ekv at stop\ekv at set@other##1\ekv at mark\ekv at stop,\ekv at stop,##2%
+ {##2}
% \end{macrocode}
% \end{macro}
%
@@ -1349,11 +1515,11 @@
% fast branching based on \TeX's argument grabbing rules and we don't have to
% split after the branching if the equal sign was there.
% \begin{macrocode}
-\long\def\ekv at eq@other##1=##2\ekv at mark##3##4\ekv at stop
+\long\def\ekv at eq@other##1=##2\ekv at mark##3%
{%
##3##1\ekv at stop\ekv at mark##2%
}
-\long\def\ekv at eq@active##1#2##2\ekv at mark##3##4\ekv at stop
+\long\def\ekv at eq@active##1#2##2\ekv at mark##3%
{%
##3##1\ekv at stop\ekv at mark##2%
}
@@ -1373,12 +1539,12 @@
% If not we split at the equal sign of category other.
% \begin{macrocode}
\ekv at eq@other##2\ekv at nil\ekv at mark\ekv at set@eq at other@a
- =\ekv at mark\ekv at set@eq at active\ekv at stop
+ =\ekv at mark\ekv at set@eq at active
% \end{macrocode}
-% And insert the set name and the next recursion step of |\ekv at set@other|.
+% And insert the set name for the next recursion step of |\ekv at set@other|.
% \begin{macrocode}
##1%
- \ekv at set@other##1\ekv at mark
+ \ekv at mark
}
% \end{macrocode}
% \end{macro}
@@ -1391,39 +1557,41 @@
% \begin{macrocode}
\long\def\ekv at set@eq at other@a##1\ekv at stop
{%
- \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at other@active at a
- #2\ekv at mark\ekv at set@eq at other@b\ekv at stop
+ \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at other@active
+ #2\ekv at mark\ekv at set@eq at other@b
}
% \end{macrocode}
% The second macro will have been called by |\ekv at eq@active| if no active
% equal sign was found. All it does is remove the excess tokens of that
-% test and forward the \kv\ pair to |\ekv at set@pair|.
+% test and forward the \kv\ pair to |\ekv at set@pair|. Normally we would have to
+% also gobble an additional |\ekv at mark| after |\ekv at stop|, but this mark is
+% needed to delimit |\ekv at set@pair|'s argument anyway, so we just leave it
+% there.
% \begin{macrocode}
-\long\def\ekv at set@eq at other@b
- ##1\ekv at nil\ekv at mark\ekv at set@eq at other@active at a\ekv at stop\ekv at mark
+\ekv at expB@unbraceA
{%
- \ekv at strip{##1}\ekv at set@pair
- }
+ \long\def\ekv at set@eq at other@b
+ ##1\ekv at nil\ekv at mark\ekv at set@eq at other@active\ekv at stop\ekv at mark
+ ##2\ekv at nil=\ekv at mark\ekv at set@eq at active
+ }%
+ {\ekv at strip{##1}{\expandafter\ekv at set@pair\detokenize}\ekv at mark##2\ekv at nil}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekv at set@eq at other@active at a,\ekv at set@eq at other@active at b}
-% |\ekv at set@eq at other@active at a| will be called if the \kv\ pair was wrongly
+% \begin{macro}[internal]{\ekv at set@eq at other@active}
+% |\ekv at set@eq at other@active| will be called if the \kv\ pair was wrongly
% split on an equal sign of category other but has an earlier equal sign of
% category active. |##1| will be the contents up to the active equal sign and
% |##2| everything that remains until the first found other equal sign. It has
-% to reinsert the equal sign and passes things on to
-% |\ekv at set@eq at other@active at b| which calls |\ekv at set@pair| on the then
-% correctly split \kv\ pair.
+% to reinsert the equal sign and forward things to |\ekv at set@pair|.
% \begin{macrocode}
-\long\def\ekv at set@eq at other@active at a##1\ekv at stop##2\ekv at nil\ekv at mark
+\ekv at expB@unbraceA
{%
- \ekv at set@eq at other@active at b{##1}##2=%
- }
-\long\def\ekv at set@eq at other@active at b##1%
- {%
- \ekv at strip{##1}\ekv at set@pair
- }
+ \long\def\ekv at set@eq at other@active
+ ##1\ekv at stop##2\ekv at nil#2\ekv at mark
+ \ekv at set@eq at other@b\ekv at mark##3=\ekv at mark\ekv at set@eq at active
+ }%
+ {\ekv at strip{##1}{\expandafter\ekv at set@pair\detokenize}\ekv at mark##2=##3}
% \end{macrocode}
% \end{macro}
%
@@ -1436,15 +1604,16 @@
##1\ekv at nil\ekv at mark\ekv at set@eq at other@a\ekv at stop\ekv at mark
{%
\ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at active@
- #2\ekv at mark\ekv at set@noeq\ekv at stop
+ #2\ekv at mark\ekv at set@noeq
}
% \end{macrocode}
% If an active equal sign was found in |\ekv at set@eq at active| we'll have to pass
% the now split \kv\ pair on to |\ekv at set@pair|.
% \begin{macrocode}
-\long\def\ekv at set@eq at active@##1\ekv at stop
+\ekv at expB@unbraceA
+ {\long\def\ekv at set@eq at active@##1\ekv at stop##2\ekv at nil#2\ekv at mark\ekv at set@noeq}%
{%
- \ekv at strip{##1}\ekv at set@pair
+ \ekv at strip{##1}{\expandafter\ekv at set@pair\detokenize}\ekv at mark##2\ekv at nil
}
% \end{macrocode}
% \end{macro}
@@ -1456,12 +1625,31 @@
% to gobble the set-name which was put after these tests by |\ekv at set@other|).
% Else this is a |NoVal| key and the entry is passed on to |\ekv at set@key|.
% \begin{macrocode}
-\long\def\ekv at set@noeq##1\ekv at nil\ekv at mark\ekv at set@eq at active@\ekv at stop\ekv at mark
+\edef\ekv at set@noeq
{%
- \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at ifempty@true at F@gobble
- \ekv at ifempty@A\ekv at ifempty@B\@firstofone
- {\ekv at strip{##1}\ekv at set@key}%
+ \unexpanded
+ {%
+ \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at set@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ }%
+ \unexpanded\expandafter
+ {\ekv at strip{##1}{\expandafter\ekv at set@key\detokenize}\ekv at mark}%
}
+\ekv at expB@unbraceA
+ {%
+ \long\def\ekv at set@noeq
+ ##1\ekv at nil\ekv at mark\ekv at set@eq at active@\ekv at stop\ekv at mark
+ }%
+ {\ekv at set@noeq}
+\def\ekv at set@was at blank##1%
+ {%
+ \def\ekv at set@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ \ekv at strip@a\ekv at mark####1\ekv at nil\ekv at mark##1##1\ekv at nil\ekv at stop
+ ####2\ekv at mark
+ {\ekv at set@other}%
+ }
+\ekv at set@was at blank{ }
% \end{macrocode}
% \end{macro}
%
@@ -1471,11 +1659,9 @@
% \begin{macrocode}
\long\def\ekv at endset@other
\ekv at stop
- \ekv at eq@other##1\ekv at nil\ekv at mark\ekv at set@eq at other@a
- =\ekv at mark\ekv at set@eq at active\ekv at stop
- ##2%
- \ekv at set@other##3\ekv at mark
- {}
+ \ekv at eq@other\ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at set@eq at other@a
+ =\ekv at mark\ekv at set@eq at active
+ {\ekv at set}
% \end{macrocode}
% \end{macro}
%
@@ -1524,7 +1710,6 @@
{%
\ekv at gobble@from at mark@to at stop##3\ekv at endparse\ekv at stop
\ekv at parse@other##1##2##3,\ekv at stop,%
- \ekv at parse##1##2\ekv at mark
}
% \end{macrocode}
% \end{macro}
@@ -1532,7 +1717,7 @@
% \begin{macro}[internal]{\ekv at endparse}
% \begin{macrocode}
\long\def\ekv at endparse
- \ekv at stop\ekv at parse@other##1,\ekv at stop,\ekv at parse##2\ekv at mark
+ \ekv at stop\ekv at parse@other##1\ekv at mark\ekv at stop,\ekv at stop,%
{}
% \end{macrocode}
% \end{macro}
@@ -1543,9 +1728,9 @@
{%
\ekv at gobble@from at mark@to at stop##3\ekv at endparse@other\ekv at stop
\ekv at eq@other##3\ekv at nil\ekv at mark\ekv at parse@eq at other@a
- =\ekv at mark\ekv at parse@eq at active\ekv at stop
+ =\ekv at mark\ekv at parse@eq at active
##1##2%
- \ekv at parse@other##1##2\ekv at mark
+ \ekv at mark
}
% \end{macrocode}
% \end{macro}
@@ -1554,28 +1739,28 @@
% \begin{macrocode}
\long\def\ekv at parse@eq at other@a##1\ekv at stop
{%
- \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active at a
- #2\ekv at mark\ekv at parse@eq at other@b\ekv at stop
+ \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active
+ #2\ekv at mark\ekv at parse@eq at other@b
}
-\long\def\ekv at parse@eq at other@b
- ##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active at a\ekv at stop\ekv at mark
+\ekv at expB@unbraceA
{%
- \ekv at strip{##1}\ekv at parse@pair
- }
+ \long\def\ekv at parse@eq at other@b
+ ##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active\ekv at stop\ekv at mark
+ ##2\ekv at nil=\ekv at mark\ekv at parse@eq at active
+ }%
+ {\ekv at strip{##1}\ekv at parse@pair##2\ekv at nil}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]
-% {\ekv at parse@eq at other@active at a,\ekv at parse@eq at other@active at b}
+% \begin{macro}[internal]{\ekv at parse@eq at other@active}
% \begin{macrocode}
-\long\def\ekv at parse@eq at other@active at a##1\ekv at stop##2\ekv at nil\ekv at mark
+\ekv at expB@unbraceA
{%
- \ekv at parse@eq at other@active at b{##1}##2=%
- }
-\long\def\ekv at parse@eq at other@active at b##1%
- {%
- \ekv at strip{##1}\ekv at parse@pair
- }
+ \long\def\ekv at parse@eq at other@active
+ ##1\ekv at stop##2\ekv at nil#2\ekv at mark
+ \ekv at parse@eq at other@b\ekv at mark##3=\ekv at mark\ekv at parse@eq at active
+ }%
+ {\ekv at strip{##1}\ekv at parse@pair##2=##3}
% \end{macrocode}
% \end{macro}
%
@@ -1585,11 +1770,12 @@
##1\ekv at nil\ekv at mark\ekv at parse@eq at other@a\ekv at stop\ekv at mark
{%
\ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at active@
- #2\ekv at mark\ekv at parse@noeq\ekv at stop
+ #2\ekv at mark\ekv at parse@noeq
}
-\long\def\ekv at parse@eq at active@##1\ekv at stop
+\ekv at expB@unbraceA
+ {\long\def\ekv at parse@eq at active@##1\ekv at stop##2#2\ekv at mark\ekv at parse@noeq}%
{%
- \ekv at strip{##1}\ekv at parse@pair
+ \ekv at strip{##1}\ekv at parse@pair##2%
}
% \end{macrocode}
% \end{macro}
@@ -1596,13 +1782,30 @@
%
% \begin{macro}[internal]{\ekv at parse@noeq}
% \begin{macrocode}
-\long\def\ekv at parse@noeq
- ##1\ekv at nil\ekv at mark\ekv at parse@eq at active@\ekv at stop\ekv at mark
+\edef\ekv at parse@noeq
{%
- \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at ifempty@true at F@gobbletwo
- \ekv at ifempty@A\ekv at ifempty@B\@firstofone
- {\ekv at strip{##1}\ekv at parse@key}%
+ \unexpanded
+ {%
+ \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at parse@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ }%
+ \unexpanded\expandafter{\ekv at strip{##1}\ekv at parse@key}%
}
+\ekv at expB@unbraceA
+ {%
+ \long\def\ekv at parse@noeq
+ ##1\ekv at nil\ekv at mark\ekv at parse@eq at active@\ekv at stop\ekv at mark
+ }%
+ {\ekv at parse@noeq}
+\def\ekv at parse@was at blank##1%
+ {%
+ \def\ekv at parse@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ \ekv at strip@a\ekv at mark####1\ekv at nil\ekv at mark##1##1\ekv at nil\ekv at stop
+ \ekv at parse@key
+ {\ekv at parse@other}%
+ }
+\ekv at parse@was at blank{ }
% \end{macrocode}
% \end{macro}
%
@@ -1610,17 +1813,15 @@
% \begin{macrocode}
\long\def\ekv at endparse@other
\ekv at stop
- \ekv at eq@other##1\ekv at nil\ekv at mark\ekv at parse@eq at other@a
- =\ekv at mark\ekv at parse@eq at active\ekv at stop
- ##2%
- \ekv at parse@other##3\ekv at mark
- {}
+ \ekv at eq@other\ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at parse@eq at other@a
+ =\ekv at mark\ekv at parse@eq at active
+ {\ekv at parse}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekv at parse@pair,\ekv at parse@pair@}
% \begin{macrocode}
-\long\def\ekv at parse@pair##1##2\ekv at nil
+\ekv at expB@unbraceA{\long\def\ekv at parse@pair##1##2\ekv at nil}%
{%
\ekv at strip{##2}\ekv at parse@pair@{##1}%
}
@@ -1627,6 +1828,7 @@
\long\def\ekv at parse@pair@##1##2##3##4%
{%
\unexpanded{##4{##2}{##1}}%
+ \ekv at parse@other##3##4%
}
% \end{macrocode}
% \end{macro}
@@ -1636,6 +1838,7 @@
\long\def\ekv at parse@key##1##2##3%
{%
\unexpanded{##2{##1}}%
+ \ekv at parse@other##2##3%
}
% \end{macrocode}
% \end{macro}
@@ -1643,12 +1846,26 @@
% Finally really setting things up with |\ekvset|'s temporary meaning:
% \begin{macrocode}
}
-\begingroup
\catcode`\,=13
\catcode`\==13
\ekvset,=
% \end{macrocode}
%
+% \begin{macro}{\ekvsetSneaked}
+% This macro can be defined just by expanding |\ekvsneak| once after expanding
+% |\ekvset|. To expand everything as much as possible early on we use a
+% temporary definition.
+% \begin{macrocode}
+\edef\ekvsetSneaked
+ {%
+ \unexpanded{\ekvsneak{#2}}%
+ \unexpanded\expandafter{\ekvset{#1}{#3}}%
+ }
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def\ekvsetSneaked#1#2#3}}%
+ {\ekvsetSneaked}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\ekvchangeset}
% Provide a macro that is able to switch out the current \set\ in |\ekvset|.
% This operation is slow (by comparison, it should be slightly faster than
@@ -1658,112 +1875,148 @@
% switch out the set expandably, so this works similar to the |\ekvsneak| macros
% reading and reinserting the remainder of the \kv\ list.
% \begin{macrocode}
-\def\ekvchangeset#1%
+\ekv at expB@unbraceA{\def\ekvchangeset#1}%
{%
- \expandafter\ekv at changeset\csname\ekv at undefined@set{#1}\endcsname\ekv at mark
+ \expandafter\expandafter\expandafter
+ \ekv at changeset\expandafter\csname\ekv at undefined@set{#1}\endcsname\ekv at empty
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekv at changeset}
-% This macro does the real change-out of |\ekvchangeset|. We introduced an
-% |\ekv at mark| to not accidentally remove some braces which we have to remove
-% again.
+% This macro does the real change-out of |\ekvchangeset|. |#2| will have a
+% leading |\ekv at empty| so that braces aren't stripped accidentally, but that
+% will not hurt and just expand to nothing in one step.
% \begin{macrocode}
-\long\def\ekv at changeset#1#2\ekv at set@other#3#4\ekv at set#5%
+\long\def\ekv at changeset#1#2\ekv at set@other#3%
{%
- \ekv at gobble@mark#2\ekv at set@other#1#4\ekv at set#1%
+ #2\ekv at set@other#1%
}
% \end{macrocode}
% \end{macro}
%
%
-% \begin{macro}[internal]{\ekv at set@pair}
-% |\ekv at set@pair| gets invoked with the space and brace stripped key-name as
-% its first argument, the value as the second argument, and the set name as
-% the third argument. It builds the key-macro name and provides everything to
-% be able to throw meaningful error messages if it isn't defined.
-% |\ekv at set@pair@| will space and brace strip the value if the macro is
-% defined and call the key-macro. Else it'll branch into the check whether an
-% unknown key handler is defined for this set and that one will branch into
-% the error messages provided by |\ekv at set@pair| if it isn't.
+% \begin{macro}[internal]
+% {
+% \ekv at set@pair,\ekv at set@pair at a,\ekv at set@pair at b,\ekv at set@pair at c,
+% \ekv at set@pair at d,\ekv at set@pair at e
+% }
+% |\ekv at set@pair| gets invoked with the space and brace stripped and
+% |\detokenize|d key-name as its first, the value as the second, and the set
+% name as the third argument. It provides tests for the key-macros and
+% everything to be able to throw meaningful error messages if it isn't
+% defined. We have two routes here, one if |\lastnamedcs| is defined and one
+% if it isn't. The big difference is that if it is we can omit a |\csname| and
+% instead just expand |\lastnamedcs| once to get the control sequence.
+% If the macro is defined the value will be space and brace stripped and the
+% key-macro called. Else branch into the error handling provided by
+% |\ekv at set@pair|.
% \begin{macrocode}
-\long\def\ekv at set@pair#1#2\ekv at nil#3%
+\ekv at if@lastnamedcs
{%
- \expandafter\ekv at set@pair@
- \csname
- \ifcsname #3{#1}\endcsname
- #3{#1}%
- \else
- relax%
- \fi
- \endcsname
- {#2}%
+ \long\def\ekv at set@pair#1\ekv at mark#2\ekv at nil#3%
{%
- \expandafter\ekv at set@pair@
- \csname
- \ifcsname #3{}u\endcsname
- #3{}u%
- \else
- relax%
- \fi
- \endcsname
+ \ifcsname #3{#1}\endcsname\ekv at set@pair at a\fi\@secondoftwo
{#2}%
{%
- \ekv at ifdefined{#3{#1}N}%
- \ekv at err@noarg
- \ekv at err@unknown
- #3%
+ \ifcsname #3{}u\endcsname\ekv at set@pair at a\fi\@secondoftwo
+ {#2}%
+ {%
+ \ekv at ifdefined{#3{#1}N}%
+ \ekv at err@noarg
+ \ekv at err@unknown
+ #3%
+ }%
+ {#1}%
}%
- {#1}%
- }%
+ \ekv at set@other#3%
+ }
+ \def\ekv at set@pair at a\fi\@secondoftwo
+ {\fi\expandafter\ekv at set@pair at b\lastnamedcs}
}
-\long\def\ekv at set@pair@#1#2%
{%
+ \long\def\ekv at set@pair#1\ekv at mark#2\ekv at nil#3%
+ {%
+ \ifcsname #3{#1}\endcsname
+ \ekv at set@pair at a\fi\ekv at set@pair at c#3{#1}\endcsname
+ {#2}%
+ {%
+ \ifcsname #3{}u\endcsname
+ \ekv at set@pair at a\fi\ekv at set@pair at c#3{}u\endcsname
+ {#2}%
+ {%
+ \ekv at ifdefined{#3{#1}N}%
+ \ekv at err@noarg
+ \ekv at err@unknown
+ #3%
+ }%
+ {#1}%
+ }%
+ \ekv at set@other#3%
+ }
+ \def\ekv at set@pair at a\fi\ekv at set@pair at c{\fi\expandafter\ekv at set@pair at b\csname}
+ \long\def\ekv at set@pair at c#1\endcsname#2#3{#3}
+ }
+\long\def\ekv at set@pair at b#1%
+ {%
\ifx#1\relax
- \ekv at fi@secondoftwo
+ \ekv at set@pair at e
\fi
- \@firstoftwo
- {\ekv at strip{#2}#1}%
+ \ekv at set@pair at d#1%
}
+\ekv at expB@unbraceA{\long\def\ekv at set@pair at d#1#2#3}{\ekv at strip{#2}#1}
+\long\def\ekv at set@pair at e\fi\ekv at set@pair at d#1#2#3{\fi#3}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekv at set@key}
+% \begin{macro}[internal]
+% {\ekv at set@key,\ekv at set@key at a,\ekv at set@key at b,\ekv at set@key at c}
% Analogous to |\ekv at set@pair|, |\ekv at set@key| builds the |NoVal| key-macro and
% provides an error-branch. |\ekv at set@key@| will test whether the key-macro is
% defined and if so call it, else the errors are thrown.
% \begin{macrocode}
-\long\def\ekv at set@key#1#2%
+\ekv at if@lastnamedcs
{%
- \expandafter\ekv at set@key@
- \csname
- \ifcsname #2{#1}N\endcsname
- #2{#1}N%
- \else
- relax%
- \fi
- \endcsname
+ \long\def\ekv at set@key#1\ekv at mark#2%
{%
- \expandafter\ekv at set@key@
- \csname
- \ifcsname #2{}uN\endcsname
- #2{}uN%
- \else
- relax%
- \fi
- \endcsname
+ \ifcsname #2{#1}N\endcsname\ekv at set@key at a\fi\@firstofone
{%
- \ekv at ifdefined{#2{#1}}%
- \ekv at err@reqval
- \ekv at err@unknown
- #2%
+ \ifcsname #2{}uN\endcsname\ekv at set@key at a\fi\@firstofone
+ {%
+ \ekv at ifdefined{#2{#1}}%
+ \ekv at err@reqval
+ \ekv at err@unknown
+ #2%
+ }%
+ {#1}%
}%
- {#1}%
- }%
+ \ekv at set@other#2%
+ }
+ \def\ekv at set@key at a\fi\@firstofone{\fi\expandafter\ekv at set@key at b\lastnamedcs}
}
-\def\ekv at set@key@#1%
{%
+ \long\def\ekv at set@key#1\ekv at mark#2%
+ {%
+ \ifcsname #2{#1}N\endcsname
+ \ekv at set@key at a\fi\ekv at set@key at c#2{#1}N\endcsname
+ {%
+ \ifcsname #2{}uN\endcsname
+ \ekv at set@key at a\fi\ekv at set@key at c#2{}uN\endcsname
+ {%
+ \ekv at ifdefined{#2{#1}}%
+ \ekv at err@reqval
+ \ekv at err@unknown
+ #2%
+ }%
+ {#1}%
+ }%
+ \ekv at set@other#2%
+ }
+ \def\ekv at set@key at a\fi\ekv at set@key at c{\fi\expandafter\ekv at set@key at b\csname}
+ \long\def\ekv at set@key at c#1N\endcsname#2{#2}
+ }
+\long\def\ekv at set@key at b#1%
+ {%
\ifx#1\relax
\ekv at fi@secondoftwo
\fi
@@ -1774,25 +2027,35 @@
%
% \begin{macro}{\ekvsetdef}
% Provide a macro to define a shorthand to use |\ekvset| on a specified \set.
-% The first macro expands |\ekvset| twice, such that everything which can be
-% done up to this point is done.
+% To gain the maximum speed |\ekvset| is expanded twice by
+% |\ekv at expB@unbraceA| so that during runtime the macro storing the set name
+% is already built and one |\expandafter| doesn't have to be used.
% \begin{macrocode}
-\protected\def\ekvsetdef#1#2%
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+\protected\def\ekvsetdef#1#2}}}}%
{%
- \expandafter\expandafter\expandafter
- \ekv at setdef\expandafter\expandafter\expandafter{\ekvset{#2}{##1}}#1%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def#1##1}}%
+ {\ekvset{#2}{##1}}%
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekv at setdef}
-% This auxiliary macro defines the shorthand macro after |\ekvset| got
-% expanded as far as possible.
+% \begin{macro}{\ekvsetSneakeddef,\ekvsetdefSneaked}
+% And do the same for |\ekvsetSneaked| in the two possible ways, with a fixed
+% sneaked argument and with a flexible one.
% \begin{macrocode}
-\protected\def\ekv at setdef#1#2%
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+\protected\def\ekvsetSneakeddef#1#2}}}}%
{%
- \long\def#2##1{#1}%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def#1##1##2}}%
+ {\ekvsetSneaked{#2}{##1}{##2}}%
}
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+\protected\def\ekvsetdefSneaked#1#2#3}}}}%
+ {%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def#1##1}}%
+ {\ekvsetSneaked{#2}{#3}{##1}}%
+ }
% \end{macrocode}
% \end{macro}
%
@@ -1827,47 +2090,15 @@
% \begin{macrocode}
\long\def\ekv at err@common #1#2{\expandafter\ekv at err@common@\string#2{#1}}
\long\def\ekv at err@common@#1`#2' #3.#4#5{\ekv at err{#4 (`#5', set `#2')}}
-\long\def\ekv at err@unknown#1#2{\ekv at err@common{unknown key}#1{#2}}
-\long\def\ekv at err@noarg #1#2{\ekv at err@common{value forbidden}#1{#2}}
-\long\def\ekv at err@reqval #1#2{\ekv at err@common{value required}#1{#2}}
+\ekv at expB@unbraceA{\long\def\ekv at err@unknown#1}%
+ {\ekv at err@common{unknown key}{#1}}
+\ekv at expB@unbraceA{\long\def\ekv at err@noarg #1}%
+ {\ekv at err@common{value forbidden}{#1}}
+\ekv at expB@unbraceA{\long\def\ekv at err@reqval #1}%
+ {\ekv at err@common{value required}{#1}}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekv at strip,\ekv at strip@a,\ekv at strip@b,\ekv at strip@c}
-% Finally we borrow some ideas of \pkg{expl3}'s \pkg{l3tl} to strip spaces
-% from keys and values. This |\ekv at strip| also strips one level of outer braces
-% \emph{after} stripping spaces, so an input of | {abc} | becomes |abc| after
-% stripping. It should be used with |#1| prefixed by |\ekv at mark|. Also this
-% implementation at most strips \emph{one} space from both sides.
-% \begin{macrocode}
-\def\ekv at strip#1%
- {%
- \long\def\ekv at strip##1%
- {%
- \ekv at strip@a
- ##1%
- \ekv at nil
- \ekv at mark#1%
- #1\ekv at nil{}%
- \ekv at stop
- }%
- \long\def\ekv at strip@a##1\ekv at mark#1##2\ekv at nil##3%
- {%
- \ekv at strip@b##3##1##2\ekv at nil
- }%
- \long\def\ekv at strip@b##1#1\ekv at nil
- {%
- \ekv at strip@c##1\ekv at nil
- }%
- \long\def\ekv at strip@c\ekv at mark##1\ekv at nil##2\ekv at stop##3%
- {%
- ##3{##1}%
- }%
- }
-\ekv at strip{ }
-% \end{macrocode}
-% \end{macro}
-%
% Now everything that's left is to reset the category code of |@|.
% \begin{macrocode}
\catcode`\@=\ekv at tmp
Modified: trunk/Master/texmf-dist/tex/generic/expkv/expkv.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv/expkv.tex 2020-10-11 20:49:19 UTC (rev 56633)
+++ trunk/Master/texmf-dist/tex/generic/expkv/expkv.tex 2020-10-11 20:49:36 UTC (rev 56634)
@@ -39,11 +39,23 @@
\errmessage{expkv requires e-TeX}
\expandafter\endinput
\fi
-\def\ekvVersion{1.4}
-\def\ekvDate{2020-07-04}
+\def\ekvVersion{1.5}
+\def\ekvDate{2020-10-10}
\csname ekv at tmp\endcsname
\expandafter\chardef\csname ekv at tmp\endcsname=\catcode`\@
\catcode`\@=11
+\begingroup
+ \edef\ekv at tmpa{\string \lastnamedcs}
+ \edef\ekv at tmpb{\meaning\lastnamedcs}
+ \ifx\ekv at tmpa\ekv at tmpb
+ \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##1}}
+ \else
+ \def\ekv at if@lastnamedcs{\long\def\ekv at if@lastnamedcs##1##2{##2}}
+ \fi
+ \expandafter
+\endgroup
+\ekv at if@lastnamedcs
+\def\ekv at empty{}
\long\def\@gobble#1{}
\long\def\@firstofone#1{#1}
\long\def\@firstoftwo#1#2{#1}
@@ -74,118 +86,169 @@
\ekv at ifempty@A\ekv at ifempty@B\@secondoftwo
}
\long\def\ekv at ifblank@\ekv at mark#1{\ekv at ifempty@\ekv at ifempty@A}
-\def\ekv at ifdefined#1%
+\ekv at if@lastnamedcs
{%
- \expandafter
- \ifx\csname\ifcsname #1\endcsname #1\else relax\fi\endcsname\relax
- \ekv at fi@secondoftwo
- \fi
- \@firstoftwo
+ \def\ekv at ifdefined#1{\ifcsname#1\endcsname\ekv at ifdef@\fi\@secondoftwo}
+ \def\ekv at ifdef@\fi\@secondoftwo
+ {%
+ \fi
+ \expandafter\ifx\lastnamedcs\relax
+ \ekv at fi@secondoftwo
+ \fi
+ \@firstoftwo
+ }
}
-\def\ekv at name#1#2{\ekv at name@set{#1}\ekv at name@key{\detokenize{#2}}}
-\def\ekv at name@set#1{ekv#1(}
-\def\ekv at name@key#1{#1)}
-\def\ekv at undefined@set#1{! expkv Error: Set `#1' undefined.}
-\protected\def\ekv at checkvalid#1#2%
{%
- \ekv at ifempty{#1}%
+ \def\ekv at ifdefined#1%
{%
- \def\ekv at tmp{}%
- \errmessage{expkv Error: empty set name not allowed}%
- }%
- {%
- \ekv at ifempty{#2}%
- {%
- \def\ekv at tmp{}%
- \errmessage{expkv Error: empty key name not allowed}%
- }%
- \@secondoftwo
- }%
- \@gobble
+ \ifcsname#1\endcsname\ekv at ifdef@\fi\ekv at ifdef@false#1\endcsname\relax
+ \ekv at fi@secondoftwo
+ \fi
+ \@firstoftwo
+ }
+ \def\ekv at ifdef@\fi\ekv at ifdef@false{\fi\expandafter\ifx\csname}
+ \long\def\ekv at ifdef@false
+ #1\endcsname\relax\ekv at fi@secondoftwo\fi\@firstoftwo#2#3%
+ {#3}
}
-\def\ekvifdefined#1#2{\ekv at ifdefined{\ekv at name{#1}{#2}}}
-\def\ekvifdefinedNoVal#1#2{\ekv at ifdefined{\ekv at name{#1}{#2}N}}
-\protected\long\def\ekvdef#1#2#3%
+\def\ekv at strip#1%
{%
- \ekv at checkvalid{#1}{#2}%
+ \long\def\ekv at strip##1%
{%
- \expandafter\def\csname\ekv at name{#1}{#2}\endcsname##1{#3}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ \ekv at strip@a
+ ##1\ekv at nil
+ \ekv at mark#1%
+ #1\ekv at nil
+ \ekv at stop
}%
+ \long\def\ekv at strip@a##1\ekv at mark#1{\ekv at strip@b##1\ekv at mark}%
+ \long\def\ekv at strip@b##1#1\ekv at nil {\ekv at strip@c##1\ekv at nil}%
}
-\protected\long\def\ekvdefNoVal#1#2#3%
+\ekv at strip{ }
+\long\def\ekv at strip@c\ekv at mark#1\ekv at nil\ekv at mark#2\ekv at nil\ekv at stop#3{#3{#1}}
+\long\def\ekv at expB@unbraceA#1#2%
{%
- \ekv at checkvalid{#1}{#2}%
- {%
- \expandafter\def\csname\ekv at name{#1}{#2}N\endcsname{#3}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
- }%
+ \expandafter\ekv at expB@unbraceA@\expandafter{#2}{#1}%
}
-\protected\def\ekvlet#1#2#3%
+\long\def\ekv at expB@unbraceA@#1#2{#2{#1}}%
+\def\ekv at name@set#1{ekv#1(}
+\def\ekv at name@key#1{#1)}
+\edef\ekv at name
{%
- \ekv at checkvalid{#1}{#2}%
- {%
- \expandafter\let\csname\ekv at name{#1}{#2}\endcsname#3%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
- }%
+ \unexpanded\expandafter{\ekv at name@set{#1}}%
+ \unexpanded\expandafter{\ekv at name@key{\detokenize{#2}}}%
}
-\protected\def\ekvletNoVal#1#2#3%
+\ekv at expB@unbraceA{\def\ekv at name#1#2}{\ekv at name}
+\def\ekv at undefined@set#1{! expkv Error: Set `#1' undefined.}
+\edef\ekv at checkvalid
{%
- \ekv at checkvalid{#1}{#2}%
+ \unexpanded\expandafter{\ekv at ifempty{#1}}%
+ \unexpanded
+ {{%
+ \def\ekv at tmp{}%
+ \errmessage{expkv Error: empty set name not allowed}%
+ }}%
{%
- \expandafter\let\csname\ekv at name{#1}{#2}N\endcsname#3%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ \unexpanded\expandafter{\ekv at ifempty{#2}}%
+ \unexpanded
+ {%
+ {%
+ \def\ekv at tmp{}%
+ \errmessage{expkv Error: empty key name not allowed}%
+ }%
+ \@secondoftwo
+ }%
}%
+ \unexpanded{\@gobble}%
}
-\protected\def\ekvletkv#1#2#3#4%
+\ekv at expB@unbraceA{\protected\def\ekv at checkvalid#1#2}{\ekv at checkvalid}%
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\def\ekvifdefined#1#2}}%
+ {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}}}
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\def\ekvifdefinedNoVal#1#2}}%
+ {\expandafter\ekv at ifdefined\expandafter{\ekv at name{#1}{#2}N}}
+\def\ekvdef#1#2#3#4%
{%
- \ekv at checkvalid{#1}{#2}%
+ \protected\long\def\ekvdef##1##2##3%
+ {#1{\expandafter\def\csname#2\endcsname####1{##3}#3}}%
+ \protected\long\def\ekvdefNoVal##1##2##3%
+ {#1{\expandafter\def\csname#2N\endcsname{##3}#3}}%
+ \protected\def\ekvlet##1##2##3%
+ {#1{\expandafter\let\csname#2\endcsname##3#3}}%
+ \protected\def\ekvletNoVal##1##2##3%
+ {#1{\expandafter\let\csname#2N\endcsname##3#3}}%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+ \protected\long\def\ekvdefunknown##1##2}}}%
{%
- \expandafter\let\csname\ekv at name{#1}{#2}\expandafter\endcsname
- \csname\ekv at name{#3}{#4}\endcsname
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ \expandafter\ekv at expB@unbraceA@\expandafter
+ {%
+ \expandafter\expandafter\expandafter
+ \def\expandafter\csname\ekv at name{##1}{}u\endcsname####1####2{##2}%
+ #3%
+ }%
+ {\ekv at checkvalid{##1}.}%
}%
- }
-\protected\def\ekvletkvNoVal#1#2#3#4%
- {%
- \ekv at checkvalid{#1}{#2}%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+ \protected\long\def\ekvdefunknownNoVal##1##2}}}%
{%
- \expandafter\let\csname\ekv at name{#1}{#2}N\expandafter\endcsname
- \csname\ekv at name{#3}{#4}N\endcsname
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ \expandafter\ekv at expB@unbraceA@\expandafter
+ {%
+ \expandafter\expandafter\expandafter
+ \def\expandafter\csname\ekv at name{##1}{}uN\endcsname####1{##2}%
+ #3%
+ }%
+ {\ekv at checkvalid{##1}.}%
}%
- }
-\protected\def\ekvdefunknown#1#2%
- {%
- \ekv at checkvalid{#1}{.}%
+ \protected\def\ekvletkv##1##2##3##4%
{%
- \expandafter\def\csname\ekv at name{#1}{}u\endcsname##1##2{#2}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ #1%
+ {%
+ \expandafter\let\csname#2\expandafter\endcsname
+ \csname#4\endcsname
+ #3%
+ }%
}%
+ \protected\def\ekvletkvNoVal##1##2##3##4%
+ {%
+ #1%
+ {%
+ \expandafter\let\csname#2N\expandafter\endcsname
+ \csname#4N\endcsname
+ #3%
+ }%
+ }%
}
-\protected\def\ekvdefunknownNoVal#1#2%
+\edef\ekvdefNoVal
{%
- \ekv at checkvalid{#1}{.}%
+ {\unexpanded\expandafter{\ekv at checkvalid{#1}{#2}}}%
+ {\unexpanded\expandafter{\ekv at name{#1}{#2}}}%
+ {%
+ \unexpanded{\expandafter\ekv at defsetmacro\csname}%
+ \unexpanded\expandafter{\ekv at undefined@set{#1}\endcsname{#1}}%
+ }%
+ {\unexpanded\expandafter{\ekv at name{#3}{#4}}}%
+ }%
+\expandafter\ekvdef\ekvdefNoVal
+\edef\ekv at defsetmacro
+ {%
+ \unexpanded{\ifx#1\relax\edef#1##1}%
{%
- \expandafter\def\csname\ekv at name{#1}{}uN\endcsname##1{#2}%
- \expandafter\ekv at defsetmacro\csname\ekv at undefined@set{#1}\endcsname{#1}%
+ \unexpanded\expandafter{\ekv at name@set{#2}}%
+ \unexpanded\expandafter{\ekv at name@key{##1}}%
}%
+ \unexpanded{\fi}%
}
-\protected\def\ekv at defsetmacro#1#2%
+\ekv at expB@unbraceA{\protected\def\ekv at defsetmacro#1#2}{\ekv at defsetmacro}
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\def\ekvifdefinedset#1}}%
{%
- \ifx#1\relax
- \edef#1##1{\ekv at name@set{#2}\ekv at name@key{\noexpand\detokenize{##1}}}%
- \fi
+ \expandafter\ekv at ifdefined\expandafter{\ekv at undefined@set{#1}}%
}
-\def\ekvifdefinedset#1%
- {%
- \ekv at ifdefined{\ekv at undefined@set{#1}}%
- }
+\begingroup
\def\ekvset#1#2{%
\endgroup
-\long\def\ekvset##1##2%
+\ekv at expB@unbraceA{\long\def\ekvset##1##2}%
{%
- \expandafter\ekv at set\csname\ekv at undefined@set{##1}\endcsname
+ \expandafter\expandafter\expandafter
+ \ekv at set\expandafter\csname\ekv at undefined@set{##1}\endcsname
\ekv at mark##2#1\ekv at stop#1{}%
}
\long\def\ekv at set##1##2#1%
@@ -192,17 +255,15 @@
{%
\ekv at gobble@from at mark@to at stop##2\ekv at endset\ekv at stop
\ekv at set@other##1##2,\ekv at stop,%
- \ekv at set##1\ekv at mark
}
\long\def\ekv at endset
- \ekv at stop\ekv at set@other##1,\ekv at stop,\ekv at set##2\ekv at mark
- ##3%
- {##3}
-\long\def\ekv at eq@other##1=##2\ekv at mark##3##4\ekv at stop
+ \ekv at stop\ekv at set@other##1\ekv at mark\ekv at stop,\ekv at stop,##2%
+ {##2}
+\long\def\ekv at eq@other##1=##2\ekv at mark##3%
{%
##3##1\ekv at stop\ekv at mark##2%
}
-\long\def\ekv at eq@active##1#2##2\ekv at mark##3##4\ekv at stop
+\long\def\ekv at eq@active##1#2##2\ekv at mark##3%
{%
##3##1\ekv at stop\ekv at mark##2%
}
@@ -210,51 +271,70 @@
{%
\ekv at gobble@from at mark@to at stop##2\ekv at endset@other\ekv at stop
\ekv at eq@other##2\ekv at nil\ekv at mark\ekv at set@eq at other@a
- =\ekv at mark\ekv at set@eq at active\ekv at stop
+ =\ekv at mark\ekv at set@eq at active
##1%
- \ekv at set@other##1\ekv at mark
+ \ekv at mark
}
\long\def\ekv at set@eq at other@a##1\ekv at stop
{%
- \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at other@active at a
- #2\ekv at mark\ekv at set@eq at other@b\ekv at stop
+ \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at other@active
+ #2\ekv at mark\ekv at set@eq at other@b
}
-\long\def\ekv at set@eq at other@b
- ##1\ekv at nil\ekv at mark\ekv at set@eq at other@active at a\ekv at stop\ekv at mark
+\ekv at expB@unbraceA
{%
- \ekv at strip{##1}\ekv at set@pair
- }
-\long\def\ekv at set@eq at other@active at a##1\ekv at stop##2\ekv at nil\ekv at mark
+ \long\def\ekv at set@eq at other@b
+ ##1\ekv at nil\ekv at mark\ekv at set@eq at other@active\ekv at stop\ekv at mark
+ ##2\ekv at nil=\ekv at mark\ekv at set@eq at active
+ }%
+ {\ekv at strip{##1}{\expandafter\ekv at set@pair\detokenize}\ekv at mark##2\ekv at nil}
+\ekv at expB@unbraceA
{%
- \ekv at set@eq at other@active at b{##1}##2=%
- }
-\long\def\ekv at set@eq at other@active at b##1%
- {%
- \ekv at strip{##1}\ekv at set@pair
- }
+ \long\def\ekv at set@eq at other@active
+ ##1\ekv at stop##2\ekv at nil#2\ekv at mark
+ \ekv at set@eq at other@b\ekv at mark##3=\ekv at mark\ekv at set@eq at active
+ }%
+ {\ekv at strip{##1}{\expandafter\ekv at set@pair\detokenize}\ekv at mark##2=##3}
\long\def\ekv at set@eq at active
##1\ekv at nil\ekv at mark\ekv at set@eq at other@a\ekv at stop\ekv at mark
{%
\ekv at eq@active##1\ekv at nil\ekv at mark\ekv at set@eq at active@
- #2\ekv at mark\ekv at set@noeq\ekv at stop
+ #2\ekv at mark\ekv at set@noeq
}
-\long\def\ekv at set@eq at active@##1\ekv at stop
+\ekv at expB@unbraceA
+ {\long\def\ekv at set@eq at active@##1\ekv at stop##2\ekv at nil#2\ekv at mark\ekv at set@noeq}%
{%
- \ekv at strip{##1}\ekv at set@pair
+ \ekv at strip{##1}{\expandafter\ekv at set@pair\detokenize}\ekv at mark##2\ekv at nil
}
-\long\def\ekv at set@noeq##1\ekv at nil\ekv at mark\ekv at set@eq at active@\ekv at stop\ekv at mark
+\edef\ekv at set@noeq
{%
- \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at ifempty@true at F@gobble
- \ekv at ifempty@A\ekv at ifempty@B\@firstofone
- {\ekv at strip{##1}\ekv at set@key}%
+ \unexpanded
+ {%
+ \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at set@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ }%
+ \unexpanded\expandafter
+ {\ekv at strip{##1}{\expandafter\ekv at set@key\detokenize}\ekv at mark}%
}
+\ekv at expB@unbraceA
+ {%
+ \long\def\ekv at set@noeq
+ ##1\ekv at nil\ekv at mark\ekv at set@eq at active@\ekv at stop\ekv at mark
+ }%
+ {\ekv at set@noeq}
+\def\ekv at set@was at blank##1%
+ {%
+ \def\ekv at set@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ \ekv at strip@a\ekv at mark####1\ekv at nil\ekv at mark##1##1\ekv at nil\ekv at stop
+ ####2\ekv at mark
+ {\ekv at set@other}%
+ }
+\ekv at set@was at blank{ }
\long\def\ekv at endset@other
\ekv at stop
- \ekv at eq@other##1\ekv at nil\ekv at mark\ekv at set@eq at other@a
- =\ekv at mark\ekv at set@eq at active\ekv at stop
- ##2%
- \ekv at set@other##3\ekv at mark
- {}
+ \ekv at eq@other\ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at set@eq at other@a
+ =\ekv at mark\ekv at set@eq at active
+ {\ekv at set}
\long\def\ekvbreak##1##2\ekv at stop#1##3{##1}
\long\def\ekvbreakPreSneak ##1##2\ekv at stop#1##3{##1##3}
\long\def\ekvbreakPostSneak##1##2\ekv at stop#1##3{##3##1}
@@ -274,62 +354,78 @@
{%
\ekv at gobble@from at mark@to at stop##3\ekv at endparse\ekv at stop
\ekv at parse@other##1##2##3,\ekv at stop,%
- \ekv at parse##1##2\ekv at mark
}
\long\def\ekv at endparse
- \ekv at stop\ekv at parse@other##1,\ekv at stop,\ekv at parse##2\ekv at mark
+ \ekv at stop\ekv at parse@other##1\ekv at mark\ekv at stop,\ekv at stop,%
{}
\long\def\ekv at parse@other##1##2##3,%
{%
\ekv at gobble@from at mark@to at stop##3\ekv at endparse@other\ekv at stop
\ekv at eq@other##3\ekv at nil\ekv at mark\ekv at parse@eq at other@a
- =\ekv at mark\ekv at parse@eq at active\ekv at stop
+ =\ekv at mark\ekv at parse@eq at active
##1##2%
- \ekv at parse@other##1##2\ekv at mark
+ \ekv at mark
}
\long\def\ekv at parse@eq at other@a##1\ekv at stop
{%
- \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active at a
- #2\ekv at mark\ekv at parse@eq at other@b\ekv at stop
+ \ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active
+ #2\ekv at mark\ekv at parse@eq at other@b
}
-\long\def\ekv at parse@eq at other@b
- ##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active at a\ekv at stop\ekv at mark
+\ekv at expB@unbraceA
{%
- \ekv at strip{##1}\ekv at parse@pair
- }
-\long\def\ekv at parse@eq at other@active at a##1\ekv at stop##2\ekv at nil\ekv at mark
+ \long\def\ekv at parse@eq at other@b
+ ##1\ekv at nil\ekv at mark\ekv at parse@eq at other@active\ekv at stop\ekv at mark
+ ##2\ekv at nil=\ekv at mark\ekv at parse@eq at active
+ }%
+ {\ekv at strip{##1}\ekv at parse@pair##2\ekv at nil}
+\ekv at expB@unbraceA
{%
- \ekv at parse@eq at other@active at b{##1}##2=%
- }
-\long\def\ekv at parse@eq at other@active at b##1%
- {%
- \ekv at strip{##1}\ekv at parse@pair
- }
+ \long\def\ekv at parse@eq at other@active
+ ##1\ekv at stop##2\ekv at nil#2\ekv at mark
+ \ekv at parse@eq at other@b\ekv at mark##3=\ekv at mark\ekv at parse@eq at active
+ }%
+ {\ekv at strip{##1}\ekv at parse@pair##2=##3}
\long\def\ekv at parse@eq at active
##1\ekv at nil\ekv at mark\ekv at parse@eq at other@a\ekv at stop\ekv at mark
{%
\ekv at eq@active##1\ekv at nil\ekv at mark\ekv at parse@eq at active@
- #2\ekv at mark\ekv at parse@noeq\ekv at stop
+ #2\ekv at mark\ekv at parse@noeq
}
-\long\def\ekv at parse@eq at active@##1\ekv at stop
+\ekv at expB@unbraceA
+ {\long\def\ekv at parse@eq at active@##1\ekv at stop##2#2\ekv at mark\ekv at parse@noeq}%
{%
- \ekv at strip{##1}\ekv at parse@pair
+ \ekv at strip{##1}\ekv at parse@pair##2%
}
-\long\def\ekv at parse@noeq
- ##1\ekv at nil\ekv at mark\ekv at parse@eq at active@\ekv at stop\ekv at mark
+\edef\ekv at parse@noeq
{%
- \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at ifempty@true at F@gobbletwo
- \ekv at ifempty@A\ekv at ifempty@B\@firstofone
- {\ekv at strip{##1}\ekv at parse@key}%
+ \unexpanded
+ {%
+ \ekv at ifblank@##1\ekv at nil\ekv at ifempty@B\ekv at parse@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ }%
+ \unexpanded\expandafter{\ekv at strip{##1}\ekv at parse@key}%
}
+\ekv at expB@unbraceA
+ {%
+ \long\def\ekv at parse@noeq
+ ##1\ekv at nil\ekv at mark\ekv at parse@eq at active@\ekv at stop\ekv at mark
+ }%
+ {\ekv at parse@noeq}
+\def\ekv at parse@was at blank##1%
+ {%
+ \def\ekv at parse@was at blank
+ \ekv at ifempty@A\ekv at ifempty@B
+ \ekv at strip@a\ekv at mark####1\ekv at nil\ekv at mark##1##1\ekv at nil\ekv at stop
+ \ekv at parse@key
+ {\ekv at parse@other}%
+ }
+\ekv at parse@was at blank{ }
\long\def\ekv at endparse@other
\ekv at stop
- \ekv at eq@other##1\ekv at nil\ekv at mark\ekv at parse@eq at other@a
- =\ekv at mark\ekv at parse@eq at active\ekv at stop
- ##2%
- \ekv at parse@other##3\ekv at mark
- {}
-\long\def\ekv at parse@pair##1##2\ekv at nil
+ \ekv at eq@other\ekv at mark\ekv at stop\ekv at nil\ekv at mark\ekv at parse@eq at other@a
+ =\ekv at mark\ekv at parse@eq at active
+ {\ekv at parse}
+\ekv at expB@unbraceA{\long\def\ekv at parse@pair##1##2\ekv at nil}%
{%
\ekv at strip{##2}\ekv at parse@pair@{##1}%
}
@@ -336,106 +432,152 @@
\long\def\ekv at parse@pair@##1##2##3##4%
{%
\unexpanded{##4{##2}{##1}}%
+ \ekv at parse@other##3##4%
}
\long\def\ekv at parse@key##1##2##3%
{%
\unexpanded{##2{##1}}%
+ \ekv at parse@other##2##3%
}
}
-\begingroup
\catcode`\,=13
\catcode`\==13
\ekvset,=
-\def\ekvchangeset#1%
+\edef\ekvsetSneaked
{%
- \expandafter\ekv at changeset\csname\ekv at undefined@set{#1}\endcsname\ekv at mark
+ \unexpanded{\ekvsneak{#2}}%
+ \unexpanded\expandafter{\ekvset{#1}{#3}}%
}
-\long\def\ekv at changeset#1#2\ekv at set@other#3#4\ekv at set#5%
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def\ekvsetSneaked#1#2#3}}%
+ {\ekvsetSneaked}
+\ekv at expB@unbraceA{\def\ekvchangeset#1}%
{%
- \ekv at gobble@mark#2\ekv at set@other#1#4\ekv at set#1%
+ \expandafter\expandafter\expandafter
+ \ekv at changeset\expandafter\csname\ekv at undefined@set{#1}\endcsname\ekv at empty
}
-\long\def\ekv at set@pair#1#2\ekv at nil#3%
+\long\def\ekv at changeset#1#2\ekv at set@other#3%
{%
- \expandafter\ekv at set@pair@
- \csname
- \ifcsname #3{#1}\endcsname
- #3{#1}%
- \else
- relax%
- \fi
- \endcsname
- {#2}%
+ #2\ekv at set@other#1%
+ }
+\ekv at if@lastnamedcs
+ {%
+ \long\def\ekv at set@pair#1\ekv at mark#2\ekv at nil#3%
{%
- \expandafter\ekv at set@pair@
- \csname
- \ifcsname #3{}u\endcsname
- #3{}u%
- \else
- relax%
- \fi
- \endcsname
+ \ifcsname #3{#1}\endcsname\ekv at set@pair at a\fi\@secondoftwo
{#2}%
{%
- \ekv at ifdefined{#3{#1}N}%
- \ekv at err@noarg
- \ekv at err@unknown
- #3%
+ \ifcsname #3{}u\endcsname\ekv at set@pair at a\fi\@secondoftwo
+ {#2}%
+ {%
+ \ekv at ifdefined{#3{#1}N}%
+ \ekv at err@noarg
+ \ekv at err@unknown
+ #3%
+ }%
+ {#1}%
}%
- {#1}%
- }%
+ \ekv at set@other#3%
+ }
+ \def\ekv at set@pair at a\fi\@secondoftwo
+ {\fi\expandafter\ekv at set@pair at b\lastnamedcs}
}
-\long\def\ekv at set@pair@#1#2%
{%
+ \long\def\ekv at set@pair#1\ekv at mark#2\ekv at nil#3%
+ {%
+ \ifcsname #3{#1}\endcsname
+ \ekv at set@pair at a\fi\ekv at set@pair at c#3{#1}\endcsname
+ {#2}%
+ {%
+ \ifcsname #3{}u\endcsname
+ \ekv at set@pair at a\fi\ekv at set@pair at c#3{}u\endcsname
+ {#2}%
+ {%
+ \ekv at ifdefined{#3{#1}N}%
+ \ekv at err@noarg
+ \ekv at err@unknown
+ #3%
+ }%
+ {#1}%
+ }%
+ \ekv at set@other#3%
+ }
+ \def\ekv at set@pair at a\fi\ekv at set@pair at c{\fi\expandafter\ekv at set@pair at b\csname}
+ \long\def\ekv at set@pair at c#1\endcsname#2#3{#3}
+ }
+\long\def\ekv at set@pair at b#1%
+ {%
\ifx#1\relax
- \ekv at fi@secondoftwo
+ \ekv at set@pair at e
\fi
- \@firstoftwo
- {\ekv at strip{#2}#1}%
+ \ekv at set@pair at d#1%
}
-\long\def\ekv at set@key#1#2%
+\ekv at expB@unbraceA{\long\def\ekv at set@pair at d#1#2#3}{\ekv at strip{#2}#1}
+\long\def\ekv at set@pair at e\fi\ekv at set@pair at d#1#2#3{\fi#3}
+\ekv at if@lastnamedcs
{%
- \expandafter\ekv at set@key@
- \csname
- \ifcsname #2{#1}N\endcsname
- #2{#1}N%
- \else
- relax%
- \fi
- \endcsname
+ \long\def\ekv at set@key#1\ekv at mark#2%
{%
- \expandafter\ekv at set@key@
- \csname
- \ifcsname #2{}uN\endcsname
- #2{}uN%
- \else
- relax%
- \fi
- \endcsname
+ \ifcsname #2{#1}N\endcsname\ekv at set@key at a\fi\@firstofone
{%
- \ekv at ifdefined{#2{#1}}%
- \ekv at err@reqval
- \ekv at err@unknown
- #2%
+ \ifcsname #2{}uN\endcsname\ekv at set@key at a\fi\@firstofone
+ {%
+ \ekv at ifdefined{#2{#1}}%
+ \ekv at err@reqval
+ \ekv at err@unknown
+ #2%
+ }%
+ {#1}%
}%
- {#1}%
- }%
+ \ekv at set@other#2%
+ }
+ \def\ekv at set@key at a\fi\@firstofone{\fi\expandafter\ekv at set@key at b\lastnamedcs}
}
-\def\ekv at set@key@#1%
{%
+ \long\def\ekv at set@key#1\ekv at mark#2%
+ {%
+ \ifcsname #2{#1}N\endcsname
+ \ekv at set@key at a\fi\ekv at set@key at c#2{#1}N\endcsname
+ {%
+ \ifcsname #2{}uN\endcsname
+ \ekv at set@key at a\fi\ekv at set@key at c#2{}uN\endcsname
+ {%
+ \ekv at ifdefined{#2{#1}}%
+ \ekv at err@reqval
+ \ekv at err@unknown
+ #2%
+ }%
+ {#1}%
+ }%
+ \ekv at set@other#2%
+ }
+ \def\ekv at set@key at a\fi\ekv at set@key at c{\fi\expandafter\ekv at set@key at b\csname}
+ \long\def\ekv at set@key at c#1N\endcsname#2{#2}
+ }
+\long\def\ekv at set@key at b#1%
+ {%
\ifx#1\relax
\ekv at fi@secondoftwo
\fi
\@firstoftwo#1%
}
-\protected\def\ekvsetdef#1#2%
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+\protected\def\ekvsetdef#1#2}}}}%
{%
- \expandafter\expandafter\expandafter
- \ekv at setdef\expandafter\expandafter\expandafter{\ekvset{#2}{##1}}#1%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def#1##1}}%
+ {\ekvset{#2}{##1}}%
}
-\protected\def\ekv at setdef#1#2%
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+\protected\def\ekvsetSneakeddef#1#2}}}}%
{%
- \long\def#2##1{#1}%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def#1##1##2}}%
+ {\ekvsetSneaked{#2}{##1}{##2}}%
}
+\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{\ekv at expB@unbraceA{%
+\protected\def\ekvsetdefSneaked#1#2#3}}}}%
+ {%
+ \ekv at expB@unbraceA{\ekv at expB@unbraceA{\long\def#1##1}}%
+ {\ekvsetSneaked{#2}{#3}{##1}}%
+ }
\begingroup
\edef\ekv at err
{%
@@ -451,34 +593,12 @@
\def\ekv at err@{\expandafter\ekv at gobbleto@stop}
\long\def\ekv at err@common #1#2{\expandafter\ekv at err@common@\string#2{#1}}
\long\def\ekv at err@common@#1`#2' #3.#4#5{\ekv at err{#4 (`#5', set `#2')}}
-\long\def\ekv at err@unknown#1#2{\ekv at err@common{unknown key}#1{#2}}
-\long\def\ekv at err@noarg #1#2{\ekv at err@common{value forbidden}#1{#2}}
-\long\def\ekv at err@reqval #1#2{\ekv at err@common{value required}#1{#2}}
-\def\ekv at strip#1%
- {%
- \long\def\ekv at strip##1%
- {%
- \ekv at strip@a
- ##1%
- \ekv at nil
- \ekv at mark#1%
- #1\ekv at nil{}%
- \ekv at stop
- }%
- \long\def\ekv at strip@a##1\ekv at mark#1##2\ekv at nil##3%
- {%
- \ekv at strip@b##3##1##2\ekv at nil
- }%
- \long\def\ekv at strip@b##1#1\ekv at nil
- {%
- \ekv at strip@c##1\ekv at nil
- }%
- \long\def\ekv at strip@c\ekv at mark##1\ekv at nil##2\ekv at stop##3%
- {%
- ##3{##1}%
- }%
- }
-\ekv at strip{ }
+\ekv at expB@unbraceA{\long\def\ekv at err@unknown#1}%
+ {\ekv at err@common{unknown key}{#1}}
+\ekv at expB@unbraceA{\long\def\ekv at err@noarg #1}%
+ {\ekv at err@common{value forbidden}{#1}}
+\ekv at expB@unbraceA{\long\def\ekv at err@reqval #1}%
+ {\ekv at err@common{value required}{#1}}
\catcode`\@=\ekv at tmp
%%
%%
More information about the tex-live-commits
mailing list.