summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-02-23 00:29:27 +0000
committerKarl Berry <karl@freefriends.org>2020-02-23 00:29:27 +0000
commiteeb016cd74e00dfc5f4efc6c9924c03a6313826e (patch)
tree2138a5a9bf5241a7885703fd683e139902b34039
parentd8e4c7219af6d5dc7adb3defbcc0503f3f35dfe8 (diff)
expkv (22feb20)
git-svn-id: svn://tug.org/texlive/trunk@53872 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/expkv/README.md2
-rw-r--r--Master/texmf-dist/doc/latex/expkv/expkv.pdfbin333595 -> 340584 bytes
-rw-r--r--Master/texmf-dist/source/latex/expkv/expkv.dtx316
-rw-r--r--Master/texmf-dist/tex/generic/expkv/expkv.tex75
4 files changed, 240 insertions, 153 deletions
diff --git a/Master/texmf-dist/doc/latex/expkv/README.md b/Master/texmf-dist/doc/latex/expkv/README.md
index 4401986b557..854846ee33b 100644
--- a/Master/texmf-dist/doc/latex/expkv/README.md
+++ b/Master/texmf-dist/doc/latex/expkv/README.md
@@ -1,7 +1,7 @@
-------------------------------------------------------------------------------
# expkv -- an expandable key=val implementation
-Version 2020-01-22 v0.3
+Version 2020-02-22 v0.4
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
diff --git a/Master/texmf-dist/doc/latex/expkv/expkv.pdf b/Master/texmf-dist/doc/latex/expkv/expkv.pdf
index d3bf8d0cac0..2a26383dffa 100644
--- a/Master/texmf-dist/doc/latex/expkv/expkv.pdf
+++ b/Master/texmf-dist/doc/latex/expkv/expkv.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/latex/expkv/expkv.dtx b/Master/texmf-dist/source/latex/expkv/expkv.dtx
index 58f8c192dbd..fc889e7d429 100644
--- a/Master/texmf-dist/source/latex/expkv/expkv.dtx
+++ b/Master/texmf-dist/source/latex/expkv/expkv.dtx
@@ -67,6 +67,8 @@ and the derived files expkv.pdf
\RequirePackage{xfp} ^^A required for an example
\RequirePackage{listings}
\RequirePackage{booktabs}
+\RequirePackage{array}
+\RequirePackage{collcell}
\RequirePackage{siunitx}
\RequirePackage{xcolor}
\RequirePackage{caption}
@@ -106,6 +108,7 @@ and the derived files expkv.pdf
\mbox
{^^A
\BeginAccSupp{ActualText=expkv}^^A
+ \rmfamily
\bfseries
{\color{expkvgrey}e\kern-.05em x\kern-.05em}^^A
\lower.493ex
@@ -161,6 +164,7 @@ and the derived files expkv.pdf
% \fi
%
% \maketitle
+% \renewcommand*\thefootnote{\arabic{footnote}}
%
% \begin{abstract}
% \noindent\parfillskip=0pt
@@ -282,23 +286,48 @@ and the derived files expkv.pdf
% \end{syntax}
% This macro parses the \kv\ pairs and provides those list elements which are
% only keys as the argument to \meta{cs1}, and those which are a \kv\ pair to
-% \meta{cs2} as two arguments. It expands in exactly two steps of expansion.
+% \meta{cs2} as two arguments. It is fully expandable as well and returns the
+% parsed list in |\unexpanded|, which has no effect outside of an |\expanded|
+% or |\edef| context\footnotemark.
+% If you need control over the necessary steps of expansion you
+% can use |\expanded| around it.
+%
% |\ekvbreak| and |\ekvsneak| and their relatives don't work in |\ekvparse|.
-% It is analogue to \pkg{expl3}'s |\keyval_parse:NNn|.
+% It is analogue to \pkg{expl3}'s |\keyval_parse:NNn|, but not with the same
+% parsing rules -- |\keyval_parse:NNn| throws an error on multiple equal
+% signs per \kv\ pair and on empty \key\ names in a \kv\ pair, both of which
+% |\ekvparse| doesn't deal with.
%
% As a small example:
% \begin{lstlisting}
% \ekvparse\handlekey\handlekeyval{foo = bar, key, baz={zzz}}
% \end{lstlisting}
-% would expand in exactly two steps to
+% would expand to
% \begin{lstlisting}
% \handlekeyval{foo}{bar}\handlekey{key}\handlekeyval{baz}{zzz}
% \end{lstlisting}
% and afterwards |\handlekey| and |\handlekeyval| would have to further handle
% the \key. There are no macros like these two contained in \expkv, you have
% to set them up yourself if you want to use |\ekvparse| (of course the names
-% might differ).
+% might differ). If you need the results of |\ekvparse| as the argument for
+% another macro, you should use |\expanded| as only then the input stream will
+% contain the output above:
+% \begin{lstlisting}
+% \expandafter\handle\expanded{\ekvparse\k\kv{foo = bar, key, baz={zzz}}}
+% \end{lstlisting}
+% would expand to
+% \begin{lstlisting}
+% \handle\kv{foo}{bar}\k{key}\kv{baz}{zzz}
+% \end{lstlisting}
% \end{function}
+% \footnotetext
+% {^^A
+% This is a change in behaviour, previously (v0.3 and before) \cs{ekvparse}
+% would expand in exactly two steps. This isn't always necessary, but makes
+% the parsing considerably slower. If this is necessary for your application
+% you can put an \cs[no-index]{expanded} around it and will still be faster
+% since you need only a single \cs[no-index]{expandafter} this way.^^A
+% }.
%
% \subsection{Miscellaneous}
%
@@ -379,15 +408,16 @@ and the derived files expkv.pdf
% \protected\ekvdef{test}{height}{\def\myheight{#1}}
% \ekvset{test}{ height = 6 }
% \end{lstlisting}
-% and only the usage of the key, not its definition, is benchmarked.
+% and only the usage of the key, not its definition, is benchmarked. For the
+% impatient, the essence of these comparisons regarding speed and buggy
+% behaviour is contained in \autoref{tab:comp}.
%
% As far as I know \expkv\ is the only fully expandable \kv\ parser. I tried to
% compare \expkv\ to every \kv\ package listed on
% \href{https://ctan.org/topic/keyval}{CTAN}, however, one might notice that
% some of those are missing from this list. That's because I didn't get the
% others to work due to bugs, or because they just provide wrappers around other
-% packages in this list. For the impatient, the essence of these comparisons
-% regarding speed and buggy behaviour is contained in \autoref{tab:comp}.
+% packages in this list.
%
% In this subsubsection is no benchmark of |\ekvparse| and |\keyval_parse:NNn|
% contained, as most other packages don't provide equivalent features to my
@@ -395,12 +425,12 @@ and the derived files expkv.pdf
% 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).
%
-% \paragraph{\pkg{keyval}} is between two and three 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 two 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.
%
% Also \pkg{keyval} has a bug, which unfortunately can't really be resolved
% without breaking backwards compatibility for \emph{many} documents, namely it
@@ -415,13 +445,13 @@ and the derived files expkv.pdf
% \setkeys{foo}{bar={{baz}}}
% \end{lstlisting}
%
-% \paragraph{\pkg{xkeyval}} is more than ten 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 fourteen 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 200 times slower -- which is funny, because
+% \paragraph{\pkg{ltxkeys}} is over 300 times slower -- which is funny, because
% it aims to be ``[\ldots] faster than these earlier packages [referring to
% \pkg{keyval} and \pkg{xkeyval}].'' Since it aims to have a bigger feature set
% than \pkg{xkeyval}, it most definitely also has a bigger feature set than
@@ -431,13 +461,12 @@ and the derived files expkv.pdf
% \pkg{ltxkeys} loads \pkg{catoptions} which is known to introduce bugs (e.g.,
% see \url{https://tex.stackexchange.com/questions/461783}).
%
-% \paragraph{\pkg{l3keys}} is at least three 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{l3keys}} is almost five 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 about one and a half times slower for one key,
+% \paragraph{\pkg{pgfkeys}} is a bit more than two times slower for one key,
% but has an \emph{enormous} feature set. However, since adding additional keys
% doesn't add as much needed time for \pkg{pgfkeys} compared to \expkv, it gets
% faster than \expkv\ at around eight \kv\ pairs.
@@ -446,21 +475,22 @@ and the derived files expkv.pdf
% was last updated in 2012 and it slows down |\pgfkeys| by factor~$8$. Also I
% don't know whether this might introduce new bugs.
%
-% \paragraph{\pkg{kvsetkeys} with \pkg{kvdefinekeys}} is about two times slower,
-% but it works even if commas and equals have category codes different from 12.
-% Else the features of the keys are equal to those of \pkg{keyval}, the parser
-% has more features, though.
+% \paragraph{\pkg{kvsetkeys} with \pkg{kvdefinekeys}} is about three 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 a bit faster than \expkv\ (almost
-% \SI{10}{\percent}) and has a much bigger feature set. Unfortunately it also
-% suffers from the premature unbracing bug \pkg{keyval} has.
+% \paragraph{\pkg{options}} is a bit slower for only a single value, but gets a
+% tad faster than \expkv\ at around 10 \kv\ pairs. 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
% I don't understand the documentation) and from what I can see, there is no
% direct way to define the equivalent test key. Nevertheless, I tested the
% closest possible equivalent of my test key while siding for \pkg{simplekv}'s
% design not forcing something into it it doesn't seem to be designed for. It is
-% more than four times slower and has hard to predict behaviour regarding brace
+% more than five times slower and has hard to predict behaviour regarding brace
% and space stripping, similar to \pkg{keyval}. The tested definition was:
% \begin{lstlisting}[belowskip=0pt]
% \usepackage{simplekv}
@@ -468,7 +498,7 @@ and the derived files expkv.pdf
% \setKV[simplekv]{ height = 6 } % benchmarked
% \end{lstlisting}
%
-% \paragraph{\pkg{yax}} is about 13 times slower. It has a pretty strange
+% \paragraph{\pkg{yax}} is over eighteen times slower. It has a pretty strange
% syntax, imho, and again a direct equivalent is hard to define. It has the
% premature unbracing bug, too. Also somehow loading \pkg{yax} broke
% \pkg{options} for me. The tested definition was:
@@ -479,7 +509,8 @@ and the derived files expkv.pdf
% \end{lstlisting}
%
% \begin{table}
-% \def\fnsym{\textcolor{red!80!black}{*}}
+% \def\fnsym{\textcolor{red!80!black}{*}}%
+% \sisetup{round-precision=1, round-mode=places}%
% \begingroup
% \centering
% \newcommand*\yes{\textcolor{red!80!black} {yes}}^^A
@@ -492,24 +523,29 @@ and the derived files expkv.pdf
% of the \href{https://github.com/Skillmon/tex_expkv}{git repository}.
% The columns $p_i$ are the polynomial coefficients of a linear fit to the
% run-time, $p_0$ can be interpreted as the overhead for initialisation
-% and $p_1$ the cost per key. The column ``Category Fragile'' lists
-% whether the parsing breaks with active commas or equal signs.^^A
+% and $p_1$ the cost per key. The $T_0$ column is the actual mean ops
+% needed for an empty list argument, as the linear fit doesn't match that
+% point well in general. The column ``BB'' lists whether the
+% parsing is affected by some sort of brace bug, ``CF'' stands for
+% category code fragile and lists whether the parsing breaks with active
+% commas or equal signs.^^A
% \label{tab:comp}^^A
% }
-% \begin{tabular}{l*2{S[table-format=4.3]}ccc}
+% \begin{tabular}
+% {>{\collectcell\pkg}l<{\endcollectcell}*3{S[table-format=4.1]}ccc}
% \toprule
-% Package & {$p_1$} & {$p_0$} & Brace-Bug & Category Fragile & Date \\
+% \rmfamily Package & {$p_1$} & {$p_0$} & {$T_0$}& BB & CF & Date \\
% \midrule
-% \pkg{keyval} & 13.415 & 2.229 & \yes & \yes & 2014-10-28 \\
-% \pkg{options} & 25.254 & 12.160 & \yes & \yes & 2015-03-01 \\
-% \expkv & 31.711 & 5.124 & \no & \no & 2020-01-15 \\
-% \pkg{pgfkeys} & 26.215 & 43.141 & \yes & \yes & 2020-01-08 \\
-% \pkg{kvsetkeys} & {\fnsym} & {\fnsym} & \no & \no & 2019-12-15 \\
-% \pkg{l3keys} & 107.434 & 23.372 & \no & \no & 2020-01-12 \\
-% \pkg{simplekv} & 162.046 & 1.014 & \yes & \yes & 2017-08-08 \\
-% \pkg{xkeyval} & 258.505 & 168.761 & \yes & \yes & 2014-12-03 \\
-% \pkg{yax} & 510.662 & 37.961 & \yes & \yes & 2010-01-22 \\
-% \pkg{ltxkeys} & 3937.979 & 4512.835 & \no & \no & 2012-11-17 \\
+% keyval & 13.539 & 1.844 & 6.969 & \yes & \yes & 2014-10-28 \\
+% \expkv & 26.411 & 2.391 & 12.610 & \no & \no & 2020-02-22 \\
+% options & 25.532 & 10.518 & 21.393 & \yes & \yes & 2015-03-01 \\
+% pgfkeys & 26.444 & 40.939 & 55.790 & \yes & \yes & 2020-01-08 \\
+% kvsetkeys & {\fnsym} & {\fnsym} & 41.620 & \no & \no & 2019-12-15 \\
+% l3keys & 114.456 & 35.357 & 52.667 & \no & \no & 2020-02-14 \\
+% simplekv & 160.523 & 10.809 & 8.698 & \yes & \yes & 2017-08-08 \\
+% xkeyval & 260.872 & 180.435 & 164.167 & \yes & \yes & 2014-12-03 \\
+% yax & 507.643 & 62.863 & 123.533 & \yes & \yes & 2010-01-22 \\
+% ltxkeys & 3932.759 & 4737.818 & 5883.000 & \no & \no & 2012-11-17 \\
% \bottomrule
% \end{tabular}
% \par
@@ -518,13 +554,13 @@ and the derived files expkv.pdf
% \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{9.653}$, $p_1=\num{40.896}$, and $p_0=\num{67.268}$. Of course the
+% $p_2=\num{9.911}$, $p_1=\num{40.523}$, and $p_0=\num{61.500}$. 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 (the maximum ratio $p_2/p_1$
-% for the other packages is \num{8.987e-3}). If one extrapolates the fits
+% for the other packages is \num{9.697e-3}). 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.773}$, $p_1=\num{3312.744}$, and $p_0=\num{6805.363}$.
+% $p_2=\num{31.685}$, $p_1=\num{3267.368}$, and $p_0=\num{7177.582}$.
% \end{table}
%
% \subsection{Examples}
@@ -541,7 +577,7 @@ and the derived files expkv.pdf
% \protected\ekvdef{our}{width}{\ourdim=#1\relax}
% \end{lstlisting}
% as you can see, we use the set |our| here. We want the key to behave different
-% if no value is specified. In that case the key should not use the its initial
+% if no value is specified. In that case the key should not use its initial
% value, but be smart and determine the available space from
% \cs[no-index]{hsize}, so we also define
% \begin{lstlisting}
@@ -830,8 +866,8 @@ and the derived files expkv.pdf
% \begin{macro}{\ekvVersion,\ekvDate}
% We're on our first input, so lets store the version and date in a macro.
% \begin{macrocode}
-\def\ekvVersion{0.3}
-\def\ekvDate{2020-01-22}
+\def\ekvVersion{0.4}
+\def\ekvDate{2020-02-22}
% \end{macrocode}
% \end{macro}
%
@@ -843,7 +879,7 @@ and the derived files expkv.pdf
% \end{macrocode}
%
% Store the category code of |@| to later be able to reset it and change it to
-% 11.
+% 11 for now.
% \begin{macrocode}
\expandafter\chardef\csname ekv@tmp\endcsname=\catcode`\@
\catcode`\@=11
@@ -854,7 +890,7 @@ and the derived files expkv.pdf
% restore it at the end of the file, we never care for the actual definition of
% it.
%
-% \begin{macro}
+% \begin{macro}[internal]
% {
% \@gobble,\@firstofone,\@firstoftwo,\@secondoftwo,
% \ekv@gobbletostop,\ekv@fi@gobble,\ekv@fi@secondoftwo
@@ -880,7 +916,7 @@ and the derived files expkv.pdf
% the advantage that if they somehow get expanded -- which should never happen
% if things work out -- they'll throw an error directly.
%
-% \begin{macro}
+% \begin{macro}[internal]
% {
% \ekv@ifempty,\ekv@ifempty@,\ekv@ifempty@true,\ekv@ifempty@false,
% \ekv@ifempty@true@F
@@ -901,7 +937,7 @@ and the derived files expkv.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ekv@ifblank@}
+% \begin{macro}[internal]{\ekv@ifblank@}
% The obvious test that can be based on an if-empty is if-blank, meaning a test
% checking whether the argument is empty or consists only of spaces. Our version
% here will be tweaked a bit, as we want to check this, but with one leading
@@ -911,7 +947,7 @@ and the derived files expkv.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ekv@ifdefined}
+% \begin{macro}[internal]{\ekv@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
@@ -928,7 +964,7 @@ and the derived files expkv.pdf
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}
+ % \begin{macro}[internal]
% {
% \ekv@ifdefined@pair,\ekv@ifdefined@pair@,\ekv@ifdefined@key,
% \ekv@ifdefined@key@
@@ -985,7 +1021,7 @@ and the derived files expkv.pdf
\def\ekv@name@key#1{#1)}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@checkvalid}
+% \begin{macro}[internal]{\ekv@checkvalid}
% We place some restrictions on the allowed names, though, namely sets and
% keys are not allowed to be empty -- blanks are fine (meaning \mbox{set-
% or} key-names consisting of spaces).
@@ -1018,10 +1054,7 @@ and the derived files expkv.pdf
% \end{macro}
%
% \begin{macro}
-% {
-% \ekvdef,\ekvdefNoVal,\ekvlet,\ekvletNoVal,\ekvletkv,\ekvletkvNoVal,
-% \ekv@defset
-% }
+% {\ekvdef,\ekvdefNoVal,\ekvlet,\ekvletNoVal,\ekvletkv,\ekvletkvNoVal}
% Set up the key defining macros |\ekvdef| etc.
% \begin{macrocode}
\protected\long\def\ekvdef#1#2#3%
@@ -1074,6 +1107,13 @@ and the derived files expkv.pdf
\ekv@defset{#1}%
}%
}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]{\ekv@defset}
+% In order to enhance the speed the set name given to |\ekvset| will be turned
+% into a control sequence pretty early, so we have to define that control
+% sequence.
+% \begin{macrocode}
\protected\def\ekv@defset#1%
{%
\expandafter\edef\csname\ekv@name@set{#1}\endcsname##1%
@@ -1099,7 +1139,7 @@ and the derived files expkv.pdf
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@set}
+% \begin{macro}[internal]{\ekv@set}
% |\ekv@set| will split the \kv\ list at active commas. Then it has to check
% whether there were unprotected other commas and resplit there.
% \begin{macrocode}
@@ -1120,7 +1160,7 @@ and the derived files expkv.pdf
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@endset}
+% \begin{macro}[internal]{\ekv@endset}
% |\ekv@endset| is a hungry little macro. It will eat everything that remains
% of |\ekv@set| and unbrace the sneaked stuff.
% \begin{macrocode}
@@ -1130,36 +1170,38 @@ and the derived files expkv.pdf
{##3}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@set@other}
+% \begin{macro}[internal]{\ekv@set@other}
% The macro |\ekv@set@other| is guaranteed to get only single \kv\ pairs.
-% So here we need to split at equal signs. If there is no equal sign, we need to
-% test whether we're done and if not this is a |NoVal| key.
+% First we test whether we're done, if not split at equal signs. It is faster to
+% first split at category 12 equal signs and only after that on actives.
+% If there is no equal sign, we need to test whether we got a blank argument and
+% if not this is a |NoVal| key.
% \begin{macrocode}
\long\def\ekv@set@other##1##2,%
{%
- \ekv@ifblank@##2\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
- \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ \ekv@ifstop##2\ekv@endset@other\ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##2=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ {\ekv@set@eq@other##1##2\ekv@stop}%
{%
- \ekv@ifhas@eq@other##2=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifhas@eq@active##2#2\ekv@ifempty@B\ekv@ifempty@false
\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\ekv@set@eq@other##1##2\ekv@stop}%
+ {\ekv@set@eq@active##1##2\ekv@stop}%
{%
- \ekv@ifhas@eq@active##2#2\ekv@ifempty@B\ekv@ifempty@false
- \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\ekv@set@eq@active##1##2\ekv@stop}%
- {%
- \ekv@ifstop##2\ekv@endset@other\ekv@mark\ekv@stop
- \ekv@strip{##2}\ekv@set@key##1%
- }%
+ \ekv@ifblank@##2\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
+ \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ {\ekv@strip{##2}\ekv@set@key##1}%
}%
}%
\ekv@set@other##1\ekv@mark%
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@set@eq@other}
+% \begin{macro}[internal]{\ekv@set@eq@other}
% |\ekv@set@eq@other| might not be the correct break point, there might be an
% active equal sign in the currently parsed key-name. If so, we have to resplit.
+% If the split is correct strip the key-name of outer spaces and braces and feed
+% it to |\ekv@set@pair|.
% \begin{macrocode}
\long\def\ekv@set@eq@other##1##2=%
{%
@@ -1170,7 +1212,7 @@ and the derived files expkv.pdf
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@set@eq@active}
+% \begin{macro}[internal]{\ekv@set@eq@active}
% We need to handle the active equal signs.
% \begin{macrocode}
\long\def\ekv@set@eq@active##1##2#2%
@@ -1179,14 +1221,18 @@ and the derived files expkv.pdf
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@ifhas@eq@other,\ekv@ifhas@eq@active,\ekv@endset@other}
+% \begin{macro}[internal]
+% {\ekv@ifhas@eq@other,\ekv@ifhas@eq@active,\ekv@endset@other}
% And we have to set up the testing macros for our equal signs and
% |\ekv@endset@other|.
% \begin{macrocode}
\long\def\ekv@ifhas@eq@other\ekv@mark##1={\ekv@ifempty@\ekv@ifempty@A}
\long\def\ekv@ifhas@eq@active\ekv@mark##1#2{\ekv@ifempty@\ekv@ifempty@A}
\long\def\ekv@endset@other
- \ekv@mark\ekv@stop\ekv@strip##1\ekv@set@key##2%
+ \ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##1=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ ##2%
\ekv@set@other##3\ekv@mark
{}
% \end{macrocode}
@@ -1224,11 +1270,11 @@ and the derived files expkv.pdf
% \begin{macrocode}
\long\def\ekvparse##1##2##3%
{%
- \expanded{\ekv@parse##1##2\ekv@mark##3#1\ekv@stop#1}%
+ \ekv@parse##1##2\ekv@mark##3#1\ekv@stop#1%
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@parse}
+% \begin{macro}[internal]{\ekv@parse}
% \begin{macrocode}
\long\def\ekv@parse##1##2##3#1%
{%
@@ -1238,69 +1284,82 @@ and the derived files expkv.pdf
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@endparse}
+% \begin{macro}[internal]{\ekv@endparse}
% \begin{macrocode}
\long\def\ekv@endparse
\ekv@mark\ekv@stop\ekv@parse@other##1,\ekv@stop,\ekv@parse##2\ekv@mark
{}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@parse@other}
+% \begin{macro}[internal]{\ekv@parse@other}
% \begin{macrocode}
\long\def\ekv@parse@other##1##2##3,%
{%
- \ekv@ifblank@##3\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
- \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ \ekv@ifstop##3\ekv@endparse@other\ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##3=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ {\ekv@parse@eq@other##3\ekv@stop##2}%
{%
- \ekv@ifhas@eq@other##3=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifhas@eq@active##3#2\ekv@ifempty@B\ekv@ifempty@false
\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\unexpanded{##2}\ekv@parse@eq@other##3\ekv@stop}%
+ {\ekv@parse@eq@active##3\ekv@stop##2}%
{%
- \ekv@ifhas@eq@active##3#2\ekv@ifempty@B\ekv@ifempty@false
- \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\unexpanded{##2}\ekv@parse@eq@active##3\ekv@stop}%
- {%
- \ekv@ifstop##3\ekv@endparse@other\ekv@mark\ekv@stop
- \unexpanded{##1}{\ekv@strip{##3}\unexpanded}%
- }%
+ \ekv@ifblank@##3\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
+ \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ {\ekv@strip{##3}\ekv@parse@key##1}%
}%
}%
\ekv@parse@other##1##2\ekv@mark
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@parse@eq@other}
+% \begin{macro}[internal]{\ekv@parse@eq@other}
% \begin{macrocode}
\long\def\ekv@parse@eq@other##1=%
{%
\ekv@ifhas@eq@active##1#2\ekv@ifempty@B\ekv@ifempty@false
\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
{\ekv@parse@eq@active##1=}%
- {{\ekv@strip{##1}\unexpanded}\ekv@parse@pair\ekv@mark}%
+ {\ekv@strip{##1}\ekv@parse@pair\ekv@mark}%
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@parse@eq@active}
+% \begin{macro}[internal]{\ekv@parse@eq@active}
% \begin{macrocode}
\long\def\ekv@parse@eq@active##1#2%
{%
- {\ekv@strip{##1}\unexpanded}\ekv@parse@pair\ekv@mark
+ \ekv@strip{##1}\ekv@parse@pair\ekv@mark
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@endparse@other}
+% \begin{macro}[internal]{\ekv@endparse@other}
% \begin{macrocode}
\long\def\ekv@endparse@other
- \ekv@mark\ekv@stop\unexpanded##1%
- \ekv@parse@other##2\ekv@mark
+ \ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##1=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ ##2%
+ \ekv@parse@other##3\ekv@mark
{}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\ekv@parse@pair}
+% \begin{macro}[internal]{\ekv@parse@pair,\ekv@parse@pair@}
+% \begin{macrocode}
+\long\def\ekv@parse@pair##1##2\ekv@stop
+ {%
+ \ekv@strip{##2}\ekv@parse@pair@{##1}%
+ }
+\long\def\ekv@parse@pair@##1##2##3%
+ {%
+ \unexpanded{##3{##2}{##1}}%
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]{\ekv@parse@key}
% \begin{macrocode}
-\long\def\ekv@parse@pair##1\ekv@stop
+\long\def\ekv@parse@key##1##2%
{%
- {\ekv@strip{##1}\unexpanded}%
+ \unexpanded{##2{##1}}%
}
% \end{macrocode}
% \end{macro}
@@ -1314,7 +1373,7 @@ and the derived files expkv.pdf
\ekvset,=
% \end{macrocode}
%
-% \begin{macro}{\ekv@ifstop}
+% \begin{macro}[internal]{\ekv@ifstop}
% The |\ekv@ifstop| test works similar to our if-empty test, but instead of
% using tokens which are used nowhere else (|\ekv@ifempty@A| and
% |\ekv@ifempty@B|) we use |\ekv@mark| and |\ekv@stop|.
@@ -1323,14 +1382,20 @@ and the derived files expkv.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ekv@set@pair,\ekv@set@pair@}
-% |\ekv@set@pair| needs to split the argument at the |=| sign and check
-% whether the key is defined.
+% \begin{macro}[internal]{\ekv@set@pair,\ekv@set@pair@}
+% |\ekv@set@pair| gets invoked with the space and brace stripped key-name as its
+% first argument, the set-macro as the second argument, and following that is
+% the key-value right delimited by an |\ekv@stop|.
% \begin{macrocode}
\long\def\ekv@set@pair#1#2%
{%
\ekv@ifdefined@pair#2{#1}%
{%
+% \end{macrocode}
+% This branch will be executed if the key is not defined as an argument grabbing
+% one. If so test whether there is a |NoVal| key of the same name or whether the
+% key is unknown. Throw a meaningful error message and gobble the value.
+% \begin{macrocode}
\ekv@ifdefined{#2{#1}N}%
\ekv@err@noarg
\ekv@err@unknown
@@ -1338,6 +1403,12 @@ and the derived files expkv.pdf
\ekv@gobbletostop
}%
}
+% \end{macrocode}
+% |\ekv@ifdefined@pair| will call |\ekv@set@pair@| if the key is correctly
+% defined. This will then grab the value, strip outer spaces and braces from it
+% and feed it to the key-macro. Afterwards |\ekv@set@other| will take control
+% again.
+% \begin{macrocode}
\long\def\ekv@set@pair@#1#2\ekv@stop
{%
\ekv@strip{#2}#1%
@@ -1345,7 +1416,11 @@ and the derived files expkv.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ekv@set@key}
+% \begin{macro}[internal]{\ekv@set@key}
+% Analogous to |\ekv@set@pair|, |\ekv@set@key| lets |\ekv@ifdefined@key| test
+% whether a |NoVal| key is defined, else it'll throw a meaningful error message.
+% Since we don't have to grab any value |\ekv@ifdefined@key| will invoke the
+% key-macro and we're done here, |\ekv@set@other| will take over again.
% \begin{macrocode}
\long\def\ekv@set@key#1#2%
{%
@@ -1360,7 +1435,7 @@ and the derived files expkv.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ekv@err,\ekv@err@}
+% \begin{macro}[internal]{\ekv@err,\ekv@err@}
% Since |\ekvset| is fully expandable as long as the code of the keys is (which
% is unlikely) we want to somehow throw expandable errors, in our case via
% undefined control sequences.
@@ -1380,7 +1455,7 @@ and the derived files expkv.pdf
\def\ekv@err@{\expandafter\ekv@gobbletostop}
% \end{macrocode}
% \end{macro}
-% \begin{macro}
+% \begin{macro}[internal]
% {
% \ekv@err@common,\ekv@err@common@,
% \ekv@err@unknown,\ekv@err@noarg,\ekv@err@reqval
@@ -1396,11 +1471,12 @@ and the derived files expkv.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ekv@strip,\ekv@strip@a,\ekv@strip@b,\ekv@strip@c}
+% \begin{macro}[internal]{\ekv@strip,\ekv@strip@a,\ekv@strip@b,\ekv@strip@c}
% Finally we borrow some ideas of \pkg{expl3}'s \pkg{l3tl} to strip spaces
% from keys and values. This |\ekv@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@mark|.
+% stripping. It should be used with |#1| prefixed by |\ekv@mark|. Also this
+% implementation at most strips \emph{one} space from both sides.
% \begin{macrocode}
\def\ekv@strip#1%
{%
diff --git a/Master/texmf-dist/tex/generic/expkv/expkv.tex b/Master/texmf-dist/tex/generic/expkv/expkv.tex
index ca05bd10ae3..aed5e127177 100644
--- a/Master/texmf-dist/tex/generic/expkv/expkv.tex
+++ b/Master/texmf-dist/tex/generic/expkv/expkv.tex
@@ -39,8 +39,8 @@
\else
\expandafter\endinput
\fi
-\def\ekvVersion{0.3}
-\def\ekvDate{2020-01-22}
+\def\ekvVersion{0.4}
+\def\ekvDate{2020-02-22}
\csname ekv@tmp\endcsname
\expandafter\chardef\csname ekv@tmp\endcsname=\catcode`\@
\catcode`\@=11
@@ -69,6 +69,7 @@
\fi
\@firstoftwo
}
+ % \begin{macro}[internal]
\def\ekv@ifdefined@pair#1#2%
{%
\expandafter\ekv@ifdefined@pair@
@@ -202,20 +203,18 @@
{##3}
\long\def\ekv@set@other##1##2,%
{%
- \ekv@ifblank@##2\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
- \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ \ekv@ifstop##2\ekv@endset@other\ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##2=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ {\ekv@set@eq@other##1##2\ekv@stop}%
{%
- \ekv@ifhas@eq@other##2=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifhas@eq@active##2#2\ekv@ifempty@B\ekv@ifempty@false
\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\ekv@set@eq@other##1##2\ekv@stop}%
+ {\ekv@set@eq@active##1##2\ekv@stop}%
{%
- \ekv@ifhas@eq@active##2#2\ekv@ifempty@B\ekv@ifempty@false
- \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\ekv@set@eq@active##1##2\ekv@stop}%
- {%
- \ekv@ifstop##2\ekv@endset@other\ekv@mark\ekv@stop
- \ekv@strip{##2}\ekv@set@key##1%
- }%
+ \ekv@ifblank@##2\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
+ \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ {\ekv@strip{##2}\ekv@set@key##1}%
}%
}%
\ekv@set@other##1\ekv@mark%
@@ -234,7 +233,10 @@
\long\def\ekv@ifhas@eq@other\ekv@mark##1={\ekv@ifempty@\ekv@ifempty@A}
\long\def\ekv@ifhas@eq@active\ekv@mark##1#2{\ekv@ifempty@\ekv@ifempty@A}
\long\def\ekv@endset@other
- \ekv@mark\ekv@stop\ekv@strip##1\ekv@set@key##2%
+ \ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##1=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ ##2%
\ekv@set@other##3\ekv@mark
{}
\long\def\ekvbreak##1##2\ekv@stop#1##3{##1}
@@ -250,7 +252,7 @@
}
\long\def\ekvparse##1##2##3%
{%
- \expanded{\ekv@parse##1##2\ekv@mark##3#1\ekv@stop#1}%
+ \ekv@parse##1##2\ekv@mark##3#1\ekv@stop#1%
}
\long\def\ekv@parse##1##2##3#1%
{%
@@ -263,20 +265,18 @@
{}
\long\def\ekv@parse@other##1##2##3,%
{%
- \ekv@ifblank@##3\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
- \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ \ekv@ifstop##3\ekv@endparse@other\ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##3=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ {\ekv@parse@eq@other##3\ekv@stop##2}%
{%
- \ekv@ifhas@eq@other##3=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifhas@eq@active##3#2\ekv@ifempty@B\ekv@ifempty@false
\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\unexpanded{##2}\ekv@parse@eq@other##3\ekv@stop}%
+ {\ekv@parse@eq@active##3\ekv@stop##2}%
{%
- \ekv@ifhas@eq@active##3#2\ekv@ifempty@B\ekv@ifempty@false
- \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
- {\unexpanded{##2}\ekv@parse@eq@active##3\ekv@stop}%
- {%
- \ekv@ifstop##3\ekv@endparse@other\ekv@mark\ekv@stop
- \unexpanded{##1}{\ekv@strip{##3}\unexpanded}%
- }%
+ \ekv@ifblank@##3\ekv@nil\ekv@ifempty@B\ekv@ifempty@true@F
+ \ekv@ifempty@A\ekv@ifempty@B\@firstofone
+ {\ekv@strip{##3}\ekv@parse@key##1}%
}%
}%
\ekv@parse@other##1##2\ekv@mark
@@ -286,19 +286,30 @@
\ekv@ifhas@eq@active##1#2\ekv@ifempty@B\ekv@ifempty@false
\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
{\ekv@parse@eq@active##1=}%
- {{\ekv@strip{##1}\unexpanded}\ekv@parse@pair\ekv@mark}%
+ {\ekv@strip{##1}\ekv@parse@pair\ekv@mark}%
}
\long\def\ekv@parse@eq@active##1#2%
{%
- {\ekv@strip{##1}\unexpanded}\ekv@parse@pair\ekv@mark
+ \ekv@strip{##1}\ekv@parse@pair\ekv@mark
}
\long\def\ekv@endparse@other
- \ekv@mark\ekv@stop\unexpanded##1%
- \ekv@parse@other##2\ekv@mark
+ \ekv@mark\ekv@stop
+ \ekv@ifhas@eq@other##1=\ekv@ifempty@B\ekv@ifempty@false
+ \ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ ##2%
+ \ekv@parse@other##3\ekv@mark
{}
-\long\def\ekv@parse@pair##1\ekv@stop
+\long\def\ekv@parse@pair##1##2\ekv@stop
+ {%
+ \ekv@strip{##2}\ekv@parse@pair@{##1}%
+ }
+\long\def\ekv@parse@pair@##1##2##3%
+ {%
+ \unexpanded{##3{##2}{##1}}%
+ }
+\long\def\ekv@parse@key##1##2%
{%
- {\ekv@strip{##1}\unexpanded}%
+ \unexpanded{##2{##1}}%
}
}
\begingroup