texlive[59864] Master/texmf-dist: expkv-cs (7jul21)
commits+karl at tug.org
commits+karl at tug.org
Wed Jul 7 22:54:42 CEST 2021
Revision: 59864
http://tug.org/svn/texlive?view=revision&revision=59864
Author: karl
Date: 2021-07-07 22:54:41 +0200 (Wed, 07 Jul 2021)
Log Message:
-----------
expkv-cs (7jul21)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md
trunk/Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdf
trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex
Modified: trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md 2021-07-07 20:54:00 UTC (rev 59863)
+++ trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md 2021-07-07 20:54:41 UTC (rev 59864)
@@ -1,7 +1,7 @@
-------------------------------------------------------------------------------
# expkv-cs -- define expandable key=val macros using expkv
-Version 2021-06-20 v1.0
+Version 2021-07-07 v1.1
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
Modified: trunk/Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx 2021-07-07 20:54:00 UTC (rev 59863)
+++ trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx 2021-07-07 20:54:41 UTC (rev 59864)
@@ -658,9 +658,10 @@
%
% To remove some of the limitations with the approach that each primary key
% matches an argument or hash entry, you can define secondary keys. Those have
-% to be defined for each macro but it doesn't matter whether that macro was a
-% split or a hash variant. If a secondary key references another key it doesn't
-% matter whether that other key is primary or secondary.
+% to be defined for each macro individually but it doesn't matter whether that
+% macro was a split or a hash variant. If a secondary key references another key
+% it doesn't matter whether that other key is primary or secondary unless
+% otherwise specified.
%
% Secondary keys can have a prefix (like |long|) which are called |p|-type
% prefix and must have a type (like |meta|) which are called |t|-type prefix.
@@ -744,6 +745,53 @@
% \autoref{sec:change} for this). \key\ can be a primary or secondary key.
% \end{function}
%
+% \begin{function}{aggregate}
+% \begin{syntax}
+% aggregate \key\ = \marg{primary}\marg{definition} \prefixes3
+% \end{syntax}
+% While all other key types replace the current value of the associated
+% \meta{primary} key, with |aggregate| you can create keys that append or
+% prepend (or whatever you like) the new value to the current one. The
+% value must be exactly two \TeX\ arguments, where \meta{primary} should
+% be the name of a \meta{primary} key, and \meta{definition} the way you want
+% to store the current and the new value. Inside \meta{definition} you
+% can use |#1| for the current, and |#2| for the new value. The
+% \meta{definition} will not expand any further during the entire parsing (so
+% this doesn't allow general processing of current and new values). The
+% resulting \key\ will inherit being either |short| or |long| from the
+% \meta{primary} key.
+% \end{function}
+% \example The following defines an internal key (|k-internal|), which is used
+% to build a comma separated list from each call of the user facing key (|k|):\\
+% \begin{minipage}[c]{.75\linewidth}
+% \begin{lstlisting}
+% \ekvcSplit\foo
+% {k-internal=0,color=red}
+% {\textcolor{#2}{#1}}
+% \ekvcSecondaryKeys\foo
+% {aggregate k = {k-internal}{#1,#2}}
+% \foo{}\par
+% \foo{k=1,k=2,k=3,k=4}
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+% \ekvcSplit\foo
+% {k-internal=0,color=red}
+% {\textcolor{#2}{#1}}
+% \ekvcSecondaryKeys\foo
+% {aggregate k = {k-internal}{#1,#2}}
+% \foo{}\par
+% \foo{k=1,k=2,k=3,k=4}
+% \end{exresult}
+%
+% But also more strange stuff could end there, like macros or using the same
+% value multiple times:
+% \begin{lstlisting}
+% \ekvcSecondaryKeys\foo
+% {aggregate k = {k-internal}{\old{#1}\new{#2\old{#1}}}}
+% \end{lstlisting}
+%
+%
% \begin{function}{flag-bool}
% \begin{syntax}
% flag-bool \key\ = \meta{cs} \prefixes3
@@ -1283,7 +1331,50 @@
% \foo{c=1-2}
% \end{exresult}
%
+% Additionally, there is a more general version of the |aggregate| secondary key
+% type (described in \autoref{sec:secondaries}), namely the |process| key type:
%
+% \begin{function}{process}
+% \begin{syntax}
+% process \key\ = \marg{primary}\marg{definition} \prefixes2
+% \end{syntax}
+% This will grab the current value of a \meta{primary} key as |#1| (without
+% changing the current value) and the new value as |#2| and leave all the
+% processing to \meta{definition}. You should use |\ekvcPass| to forward the
+% values afterwards. Unlike |aggregate| you can specify whether the \key\
+% should be long or not, this isn't inherited from the \meta{primary} key.
+% Keep in mind that you could easily break things here if your code does not
+% work by expansion.
+% \end{function}
+% \example We could define a key that only accepts values greater than the
+% current value with this:\\
+% \begin{minipage}[c]{.75\linewidth}
+% \begin{lstlisting}
+% \ekvcSplit\foo{internal=5}{a is #1.\par}
+% \ekvcSecondaryKeys\foo
+% {
+% process a={internal}
+% {%
+% \ifnum#1<#2
+% \ekvcPass\foo{internal}{#2}%
+% \fi
+% }
+% }
+% \foo{a=1}
+% \foo{a=5}
+% \foo{a=9}
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+% \ekvcSplit\foo{internal=5}{a is #1.\par}
+% \ekvcSecondaryKeys\foo
+% {process a={internal}{\ifnum#1<#2 \ekvcPass\foo{internal}{#2}\fi}}
+% \foo{a=1}
+% \foo{a=5}
+% \foo{a=9}
+% \end{exresult}
+%
+%
% \subsection{Speed Considerations}\label{sec:speed}
%
% As already mentioned in the introduction there are some speed considerations
@@ -1457,8 +1548,8 @@
% \begin{macro}{\ekvcVersion,\ekvcDate}
% We're on our first input, so lets store the version and date in a macro.
% \begin{macrocode}
-\def\ekvcVersion{1.0}
-\def\ekvcDate{2021-06-20}
+\def\ekvcVersion{1.1}
+\def\ekvcDate{2021-07-07}
% \end{macrocode}
% \end{macro}
%
@@ -2535,6 +2626,190 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[internal]{\ekvc at t@aggregate}
+% Aggregating isn't easy to define. We'll have to extract the correct mark for
+% the specified key, branch correctly for short and long keys, and use a small
+% hack to have the correct arguments on the user interface (|#1| as the
+% current contents, |#2| as the new value). This is split into a few steps
+% here.
+%
+% First, assert that the user input is well-behaved.
+% \begin{macrocode}
+\protected\def\ekvc at t@aggregate#1%
+ {%
+ \ekvc at assert@not at long{aggregate #1}%
+ \ekvc at type@aggregate
+ \ekvc at type@aggregate at long\ekvc at type@aggregate at short
+ {process}%
+ {#1}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvc at type@aggregate,\ekvc at type@aggregate at a,\ekvc at type@aggregate at b}
+% The next step stores the user defined processing in a temporary macro that's
+% used to do the parameter number swapping later. It also builds the names of
+% the key macro and the helper which would be used for processing a short key.
+% \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate#1#2#3#4#5%
+ {%
+ \ekvc at assert@twoargs{#5}{#3 #4}{\ekvc at type@aggregate at a#1#2{#4}#5}%
+ }
+\protected\long\def\ekvc at type@aggregate at a#1#2#3#4#5%
+ {%
+ \ekvifdefined\ekvc at set{#4}%
+ {%
+ \def\ekvc at type@aggregate at tmp##1##2{#5}%
+ \begingroup\expandafter\endgroup
+ \expandafter\ekvc at type@aggregate at b
+ \csname\ekv at name\ekvc at set{#4}\expandafter\endcsname
+ \csname ekvc@\ekvc at set(#4)\endcsname
+ #1#2%
+ {#3}%
+ }%
+ {\ekvc at err@unknown at key{#4}}%
+ }
+\protected\long\def\ekvc at type@aggregate at b#1#2#3#4%
+ {%
+ \ekvc at type@aggregate at check@long#1#2%
+ {#3#1}%
+ {#4#2}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvc at type@aggregate at check@long,
+% \ekvc at type@aggregate at check@long at a,\ekvc at type@aggregate at check@long at b
+% }
+% To check whether the primary key is long we see whether its |\meaning|
+% contains the helper which would only be there for short keys. For this we
+% have to get the stringified name of the internal (using |\detokenize|),
+% and afterwards get the |\meaning| of the macro. A temporary helper does the
+% real test by gobbling and forwarding the result to |\ekv at ifempty|.
+% \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate at check@long#1#2%
+ {\expandafter\ekvc at type@aggregate at check@long at a\detokenize{#2}\ekv at stop#1}
+\protected\long\def\ekvc at type@aggregate at check@long at a#1\ekv at stop#2%
+ {%
+ \def\ekvc at type@aggregate at check@long@@##1#1{}%
+ \expandafter\ekvc at type@aggregate at check@long at b\meaning#2\ekv at stop{#1}%
+ }
+\protected\def\ekvc at type@aggregate at check@long at b#1\ekv at stop#2%
+ {\expandafter\ekv at ifempty\expandafter{\ekvc at type@aggregate at check@long@@#1#2}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at type@aggregate at long,\ekvc at type@aggregate at long@}
+% The long variant just builds the split mark we extract, uses the hack to
+% swap argument order, and then does the definition via |\ekvlet| and a
+% temporary macro.
+% \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate at long#1%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@aggregate at long@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ }
+\protected\long\def\ekvc at type@aggregate at long@#1#2#3%
+ {%
+ \long\def\ekvc at type@aggregate at tmp##1##2#1##3{##2#1{#2}}
+ \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvc at type@aggregate at short,\ekvc at type@aggregate at short@}
+% The short variant will have to build the marker and the name of the helper
+% function, and swap the user argument order. Hence here are a few more
+% |\expandafter|s involved. But afterwards we can do the definition of the key
+% and the helper macro directly.
+% \begin{macrocode}
+\protected\long\def\ekvc at type@aggregate at short#1#2%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@aggregate at short@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ {#2}%
+ }
+\protected\long\def\ekvc at type@aggregate at short@#1#2#3#4%
+ {%
+ \ekvdef\ekvc at set{#4}{#2{##1}}%
+ \long\def#2##1##2#1##3{##2#1{#3}}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at t@process}
+% The |process| type can reuse much of |aggregate|, just the last step of
+% definition differ.
+% \begin{macrocode}
+\protected\def\ekvc at t@process
+ {%
+ \ifx\ekvc at long\long
+ \ekv at fi@firstoftwo
+ \fi
+ \@secondoftwo
+ {%
+ \ekvc at type@aggregate
+ \ekvc at type@process at long\ekvc at type@process at long
+ }%
+ {%
+ \ekvc at type@aggregate
+ \ekvc at type@process at short\ekvc at type@process at short
+ }%
+ {process}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at type@process at long,\ekvc at type@process at long@}
+% This defines a temporary macro to grab the current value (found after the
+% marker |#1|), executes the user code and puts everything back to where it
+% belongs. Then |\ekvlet| is used to assign that meaning to the key macro.
+% \begin{macrocode}
+\protected\long\def\ekvc at type@process at long#1%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@process at long@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ }
+\protected\long\def\ekvc at type@process at long@#1#2#3%
+ {%
+ \long\def\ekvc at type@aggregate at tmp##1##2#1##3{#2##2#1{##3}}%
+ \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at type@process at short,\ekvc at type@process at short@}
+% We define the key macro directly to just grab the argument once and forward
+% it to the auxiliary. That one does essentially the same as the long variant.
+% \begin{macrocode}
+\protected\long\def\ekvc at type@process at short#1#2%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@process at short@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ {#2}%
+ }
+\protected\long\def\ekvc at type@process at short@#1#2#3#4%
+ {%
+ \ekvdef\ekvc at set{#4}{#2{##1}}%
+ \long\def#2##1##2#1##3{#3##2#1{##3}}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[internal]{\ekvc at t@flag-bool}
% \begin{macrocode}
\protected\expandafter\def\csname ekvc at t@flag-bool\endcsname#1#2%
@@ -2806,7 +3081,34 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[internal]{\ekvc at ifnottwoargs,\ekvc at ifempty@gtwo}
+% Used to test whether a token list contains exactly two \TeX\ arguments.
+% \begin{macrocode}
+\long\def\ekvc at ifnottwoargs#1%
+ {%
+ \ekvc at ifempty@gtwo#1\ekv at ifempty@B
+ \ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+ }
+\long\def\ekvc at ifempty@gtwo#1#2{\ekv at ifempty@\ekv at ifempty@A}
+% \end{macrocode}
+% \end{macro}
%
+% \begin{macro}[internal]{\ekvc at extract@mark,\ekvc at extract@mark@}
+% This is used to extract the mark of a split or hash key from its definition.
+% This is kind of fragile, it assumes |#1| is always a macro used for hashing
+% or splitting. Also it assumes that the escape character is a backslash.
+% \begin{macrocode}
+\def\ekvc at extract@mark#1{\expandafter\ekvc at extract@mark@\meaning#1\ekv at stop}
+\begingroup
+\lccode`;=`\#
+\lccode`/=`\\
+\lowercase{\endgroup
+\def\ekvc at extract@mark@#1:#2/#3 ;#4\ekv at stop{#3}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
% \subsubsection{Assertions}
% \begin{macro}[internal]{\ekvc at assert@not at long}
% Some keys don't want to be |long| and we have to educate the user, so let's
@@ -2816,13 +3118,23 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[internal]{\ekvc at assert@twoargs}
+% Some keys need exactly two arguments as their definition, so we have to
+% somehow assert this.
+% \begin{macrocode}
+\protected\long\def\ekvc at assert@twoargs#1#2%
+ {\ekvc at ifnottwoargs{#1}{\ekvc at err@not at two{#2}}}
+% \end{macrocode}
+% \end{macro}
%
+%
% \subsubsection{Messages}
%
% \begin{macro}[internal]
% {
% \ekvc at err@toomany,\ekvc at err@value at required,\ekvc at err@missing at type,
-% \ekvc at err@already at defined,\ekvc at err@no at key@macro
+% \ekvc at err@already at defined,\ekvc at err@no at key@macro,
+% \ekvc at err@not at two
% }
% Boring unexpandable error messages.
% \begin{macrocode}
@@ -2859,6 +3171,14 @@
}
\long\def\ekvc at err@no at key@macro#1%
{\errmessage{expkv-cs Error: \string#1 is no key=val macro}}
+\protected\long\def\ekvc at err@not at two#1%
+ {%
+ \errmessage
+ {%
+ expkv-cs Error: Definition of `\unexpanded{#1}' doesn't contain exactly
+ two arguments%
+ }%
+ }
% \end{macrocode}
% \end{macro}
%
Modified: trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex 2021-07-07 20:54:00 UTC (rev 59863)
+++ trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex 2021-07-07 20:54:41 UTC (rev 59864)
@@ -35,8 +35,8 @@
\else
\expandafter\endinput
\fi
-\def\ekvcVersion{1.0}
-\def\ekvcDate{2021-06-20}
+\def\ekvcVersion{1.1}
+\def\ekvcDate{2021-07-07}
\csname ekvc at tmp\endcsname
\expandafter\chardef\csname ekvc at tmp\endcsname=\catcode`\@
\catcode`\@=11
@@ -690,6 +690,115 @@
}%
{\ekvc at err@unknown at key{#1}}%
}
+\protected\def\ekvc at t@aggregate#1%
+ {%
+ \ekvc at assert@not at long{aggregate #1}%
+ \ekvc at type@aggregate
+ \ekvc at type@aggregate at long\ekvc at type@aggregate at short
+ {process}%
+ {#1}%
+ }
+\protected\long\def\ekvc at type@aggregate#1#2#3#4#5%
+ {%
+ \ekvc at assert@twoargs{#5}{#3 #4}{\ekvc at type@aggregate at a#1#2{#4}#5}%
+ }
+\protected\long\def\ekvc at type@aggregate at a#1#2#3#4#5%
+ {%
+ \ekvifdefined\ekvc at set{#4}%
+ {%
+ \def\ekvc at type@aggregate at tmp##1##2{#5}%
+ \begingroup\expandafter\endgroup
+ \expandafter\ekvc at type@aggregate at b
+ \csname\ekv at name\ekvc at set{#4}\expandafter\endcsname
+ \csname ekvc@\ekvc at set(#4)\endcsname
+ #1#2%
+ {#3}%
+ }%
+ {\ekvc at err@unknown at key{#4}}%
+ }
+\protected\long\def\ekvc at type@aggregate at b#1#2#3#4%
+ {%
+ \ekvc at type@aggregate at check@long#1#2%
+ {#3#1}%
+ {#4#2}%
+ }
+\protected\long\def\ekvc at type@aggregate at check@long#1#2%
+ {\expandafter\ekvc at type@aggregate at check@long at a\detokenize{#2}\ekv at stop#1}
+\protected\long\def\ekvc at type@aggregate at check@long at a#1\ekv at stop#2%
+ {%
+ \def\ekvc at type@aggregate at check@long@@##1#1{}%
+ \expandafter\ekvc at type@aggregate at check@long at b\meaning#2\ekv at stop{#1}%
+ }
+\protected\def\ekvc at type@aggregate at check@long at b#1\ekv at stop#2%
+ {\expandafter\ekv at ifempty\expandafter{\ekvc at type@aggregate at check@long@@#1#2}}
+\protected\long\def\ekvc at type@aggregate at long#1%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@aggregate at long@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ }
+\protected\long\def\ekvc at type@aggregate at long@#1#2#3%
+ {%
+ \long\def\ekvc at type@aggregate at tmp##1##2#1##3{##2#1{#2}}
+ \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+ }
+\protected\long\def\ekvc at type@aggregate at short#1#2%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@aggregate at short@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ {#2}%
+ }
+\protected\long\def\ekvc at type@aggregate at short@#1#2#3#4%
+ {%
+ \ekvdef\ekvc at set{#4}{#2{##1}}%
+ \long\def#2##1##2#1##3{##2#1{#3}}%
+ }
+\protected\def\ekvc at t@process
+ {%
+ \ifx\ekvc at long\long
+ \ekv at fi@firstoftwo
+ \fi
+ \@secondoftwo
+ {%
+ \ekvc at type@aggregate
+ \ekvc at type@process at long\ekvc at type@process at long
+ }%
+ {%
+ \ekvc at type@aggregate
+ \ekvc at type@process at short\ekvc at type@process at short
+ }%
+ {process}%
+ }
+\protected\long\def\ekvc at type@process at long#1%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@process at long@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ }
+\protected\long\def\ekvc at type@process at long@#1#2#3%
+ {%
+ \long\def\ekvc at type@aggregate at tmp##1##2#1##3{#2##2#1{##3}}%
+ \ekvlet\ekvc at set{#3}\ekvc at type@aggregate at tmp
+ }
+\protected\long\def\ekvc at type@process at short#1#2%
+ {%
+ \begingroup\expandafter\endgroup\expandafter
+ \ekvc at type@process at short@
+ \csname\ekvc at extract@mark#1\expandafter\endcsname
+ \csname ekvc@\ekvc at set(#2)\expandafter\endcsname
+ \expandafter{\ekvc at type@aggregate at tmp{##3}{##1}}%
+ {#2}%
+ }
+\protected\long\def\ekvc at type@process at short@#1#2#3#4%
+ {%
+ \ekvdef\ekvc at set{#4}{#2{##1}}%
+ \long\def#2##1##2#1##3{#3##2#1{##3}}%
+ }
\protected\expandafter\def\csname ekvc at t@flag-bool\endcsname#1#2%
{%
\ekvc at assert@not at long{flag-bool #1}%
@@ -831,7 +940,22 @@
{%
\ekv at ifempty@\ekv at ifempty@A
}
+\long\def\ekvc at ifnottwoargs#1%
+ {%
+ \ekvc at ifempty@gtwo#1\ekv at ifempty@B
+ \ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
+ }
+\long\def\ekvc at ifempty@gtwo#1#2{\ekv at ifempty@\ekv at ifempty@A}
+\def\ekvc at extract@mark#1{\expandafter\ekvc at extract@mark@\meaning#1\ekv at stop}
+\begingroup
+\lccode`;=`\#
+\lccode`/=`\\
+\lowercase{\endgroup
+\def\ekvc at extract@mark@#1:#2/#3 ;#4\ekv at stop{#3}%
+}
\long\def\ekvc at assert@not at long#1{\ifx\ekvc at long\long\ekvc at err@no at long{#1}\fi}
+\protected\long\def\ekvc at assert@twoargs#1#2%
+ {\ekvc at ifnottwoargs{#1}{\ekvc at err@not at two{#2}}}
\protected\def\ekvc at err@toomany#1%
{%
\errmessage{expkv-cs Error: Too many keys for macro `\string#1'}%
@@ -865,6 +989,14 @@
}
\long\def\ekvc at err@no at key@macro#1%
{\errmessage{expkv-cs Error: \string#1 is no key=val macro}}
+\protected\long\def\ekvc at err@not at two#1%
+ {%
+ \errmessage
+ {%
+ expkv-cs Error: Definition of `\unexpanded{#1}' doesn't contain exactly
+ two arguments%
+ }%
+ }
\ekv at exparg{\long\def\ekvc at err#1}{\ekverr{expkv-cs}{#1}}
\long\def\ekvc at err@unknown at hash#1{\ekvc at err{unknown hash `#1'}}
\long\def\ekvc at err@missing at hash#1{\ekvc at err{hash `#1' not found}}
More information about the tex-live-commits
mailing list.