diff options
author | Karl Berry <karl@freefriends.org> | 2020-10-12 21:40:18 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-10-12 21:40:18 +0000 |
commit | 6f427f96627adfd5999246707610e7c96564897d (patch) | |
tree | 30ce1093d2bcb8db6cd22e6f3778bcf7d6330485 /Master/texmf-dist/source | |
parent | ce08ee94146637c4c9b8f352678141b83d741eed (diff) |
expkv-def (12oct20)
git-svn-id: svn://tug.org/texlive/trunk@56643 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r-- | Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx | 798 |
1 files changed, 459 insertions, 339 deletions
diff --git a/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx b/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx index 12b58cbe97e..2dc41641530 100644 --- a/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx +++ b/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx @@ -146,30 +146,23 @@ and the derived files expkv-def.pdf \newcommand\key{\meta{key}} \newcommand\val{\meta{value}} \newcommand\set{\meta{set}} -\newcommand\enfprot{\textcolor{black}{protected}} -\newcommand\allprot{\textcolor{gray}{protected}} -\newcommand\notprot{\textcolor{red!80!black}{protected}} -\newcommand\enflong{\textcolor{black}{long}} -\newcommand\alllong{\textcolor{gray}{long}} -\newcommand\notlong{\textcolor{red!80!black}{long}} -\newcommand\enfalso{\textcolor{black}{also}} -\newcommand\allalso{\textcolor{gray}{also}} -\newcommand\notalso{\textcolor{red!80!black}{also}} -\newcommand\prefixes[3] +\newcommand\enfprefix{\textcolor{black}} +\newcommand\allprefix{\textcolor{gray}} +\newcommand\notprefix{\textcolor{red!80!black}} +\newcommand\printprefix[2] {^^A - \hfill \ifcase\numexpr#1\relax\or - \enfalso\or - \allalso\or - \notalso\fi\space - \ifcase\numexpr#2\relax\or - \enfprot\or - \allprot\or - \notprot\fi\space - \ifcase\numexpr#3\relax\or - \enflong\or - \alllong\or - \notlong\fi + \enfprefix{#2}\or + \allprefix{#2}\or + \notprefix{#2}\fi + } +\newcommand\prefixes[4] + {^^A + \hfill + \printprefix{#1}{new} + \printprefix{#2}{also} + \printprefix{#3}{protected} + \printprefix{#4}{long}^^A } \hypersetup{linkcolor=red!80!black,urlcolor=purple!80!black} \DoNotIndex{\def,\edef,\,,\=,\begingroup,\catcode,\chardef,\csname,\endcsname} @@ -282,9 +275,9 @@ and the derived files expkv-def.pdf % The two |p|-type prefixes |long| and |protected| are pretty simple by nature, % so their description is pretty simple. They affect the \key\ at use-time, so % omitting |long| doesn't mean that a \meta{definition} can't contain a |\par| -% token, only that the \key\ will not accept a |\par| in \val. On the other hand -% |also| might be simple on first sight as well, but its rules are a bit more -% complicated. +% token, only that the \key\ will not accept a |\par| in \val. On the other +% hand |new| and |also| might be simple on first sight as well, but their rules +% are a bit more complicated. % % \begin{function}{also} % The following key type will be \emph{added} to an existing \key's @@ -306,9 +299,16 @@ and the derived files expkv-def.pdf % \ekvdefinekeys{also-example} % { % bool key = \ifmybool -% ,also code key = \domystuff +% ,also code key = \domystuff{#1} % } % \end{lstlisting} +% +% If you use |also| on a |choice|, |bool|, |invbool|, or |boolpair| key it is +% tried to determine if the key already is of one of those types. If this test +% is true the declared choices will be added to the possible choices but the +% key's definition will not be changed other than that. If that wouldn't have +% been done, the callbacks of the different choices could get called multiple +% times. % \end{function} % % \begin{function}{protected,protect} @@ -320,17 +320,33 @@ and the derived files expkv-def.pdf % The following key will be defined |\long|. % \end{function} % +% \begin{function}{new} +% The following key must be new (so previously undefined). An error is thrown +% if it is already defined and the new definition is ignored. |new| only +% asserts that there are no conflicts between |NoVal| keys and other |NoVal| +% keys or value taking keys and other value taking keys. For example you can +% use the following without an error: +% \begin{lstlisting} +% \ekvdefinekeys{new-example} +% { +% code key = \domystuffwitharg{#1} +% ,new noval key = \domystuffwithoutarg +% } +% \end{lstlisting} +% \end{function} +% % \subsubsection{\texttt{t}-Prefixes}\label{sec:prefix:t} % Since the |p|-type prefixes apply to some of the |t|-prefixes automatically % but sometimes one might be disallowed we need some way to highlight this % behaviour. In the following an enforced prefix will be printed black -% (\texttt{\enfprot}), allowed prefixes will be grey (\texttt{\allprot}), and -% disallowed prefixes will be red (\texttt{\notprot}). This will be put -% flush-right in the syntax showing line. +% (\texttt{\enfprefix{protected}}), allowed prefixes will be grey +% (\texttt{\allprefix{protected}}), and disallowed prefixes will be red +% (\texttt{\notprefix{protected}}). This will be put flush-right in the syntax +% showing line. % % \begin{function}{code,ecode} % \begin{syntax} -% code \key\ = \marg{definition} \prefixes222 +% code \key\ = \marg{definition} \prefixes2222 % \end{syntax} % Define \key\ to expand to \meta{definition}. The \key\ will require a \val\ % for which you can use |#1| inside \meta{definition}. The |ecode| variant @@ -339,7 +355,7 @@ and the derived files expkv-def.pdf % % \begin{function}{noval,enoval} % \begin{syntax} -% noval \key\ = \marg{definition} \prefixes223 +% noval \key\ = \marg{definition} \prefixes2223 % \end{syntax} % The |noval| type defines \key\ to expand to \meta{definition}. The \key\ % will not take a \val. |enoval| fully expands \meta{definition} inside an @@ -348,7 +364,7 @@ and the derived files expkv-def.pdf % % \begin{function}{default,qdefault,edefault} % \begin{syntax} -% default \key\ = \marg{definition} \prefixes223 +% default \key\ = \marg{definition} \prefixes3223 % \end{syntax} % This serves to place a default \val\ for a \key\ that takes an argument, the % \key\ can be of any argument-grabbing kind, and when used without a \val\ @@ -360,7 +376,7 @@ and the derived files expkv-def.pdf % % \begin{function}{initial,oinitial,einitial} % \begin{syntax} -% initial \key\ = \{\val\} \prefixes333 +% initial \key\ = \{\val\} \prefixes3333 % \end{syntax} % With |initial| you can set an initial \val\ for an already defined argument % taking \key. It'll just call the key-macro of \key\ and pass it \val. The @@ -371,7 +387,7 @@ and the derived files expkv-def.pdf % % \begin{function}{bool,gbool,boolTF,gboolTF} % \begin{syntax} -% bool \key\ = \meta{cs} \prefixes223 +% bool \key\ = \meta{cs} \prefixes2223 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\iffoo|. % This will define \key\ to be a boolean key, which only takes the values @@ -394,9 +410,28 @@ and the derived files expkv-def.pdf % choices. % \end{function} % +% \begin{function}{invbool,ginvbool,invboolTF,ginvboolTF} +% \begin{syntax} +% bool \key\ = \meta{cs} \prefixes2223 +% \end{syntax} +% These are inverse boolean keys, they behave like |bool| and friends but set +% the opposite meaning to the macro \meta{cs} in each case. So if +% \texttt{key=true} is used |invbool| will set \meta{cs} to |\iffalse| and +% vice versa. +% \end{function} +% +% \begin{function}{boolpair,gboolpair,boolpairTF,gboolpairTF} +% \begin{syntax} +% boolpair \key\ = \meta{cs_1}\meta{cs_2} \prefixes2223 +% \end{syntax} +% The |boolpair| key type behaves like both |bool| and |invbool|, the +% \meta{cs_1} will be set to the meaning according to the rules of |bool|, and +% \meta{cs_2} will be set to the opposite. +% \end{function} +% % \begin{function}{store,estore,gstore,xstore} % \begin{syntax} -% store \key\ = \meta{cs} \prefixes212 +% store \key\ = \meta{cs} \prefixes2212 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\foo|. % This will define \key\ to store \val\ inside of the control sequence. If @@ -408,7 +443,7 @@ and the derived files expkv-def.pdf % % \begin{function}{data,edata,gdata,xdata} % \begin{syntax} -% data \key\ = \meta{cs} \prefixes212 +% data \key\ = \meta{cs} \prefixes2212 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\foo|. This will % define \key\ to store \val\ inside of the control sequence. But unlike the @@ -424,7 +459,7 @@ and the derived files expkv-def.pdf % % \begin{function}{dataT,edataT,gdataT,xdataT} % \begin{syntax} -% dataT \key\ = \meta{cs} \prefixes212 +% dataT \key\ = \meta{cs} \prefixes2212 % \end{syntax} % Just like |data|, but instead of \meta{cs} grabbing two arguments it'll only % grab one, so by default it'll behave like |\@gobble|, and if a \val\ was @@ -434,7 +469,7 @@ and the derived files expkv-def.pdf % % \begin{function}{int,eint,gint,xint} % \begin{syntax} -% int \key\ = \meta{cs} \prefixes212 +% int \key\ = \meta{cs} \prefixes2212 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\foo|. % An |int| key will be a \TeX-count register. If \meta{cs} isn't defined yet, @@ -445,7 +480,7 @@ and the derived files expkv-def.pdf % % \begin{function}{dimen,edimen,gdimen,xdimen} % \begin{syntax} -% dimen \key\ = \meta{cs} \prefixes212 +% dimen \key\ = \meta{cs} \prefixes2212 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\foo|. % This is just like |int| but uses a dimen register, |\newdimen| and @@ -454,7 +489,7 @@ and the derived files expkv-def.pdf % % \begin{function}{skip,eskip,gskip,xskip} % \begin{syntax} -% skip \key\ = \meta{cs} \prefixes212 +% skip \key\ = \meta{cs} \prefixes2212 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\foo|. % This is just like |int| but uses a skip register, |\newskip| and |\glueexpr| @@ -463,7 +498,7 @@ and the derived files expkv-def.pdf % % \begin{function}{toks,gtoks,apptoks,gapptoks} % \begin{syntax} -% toks \key\ = \meta{cs} \prefixes212 +% toks \key\ = \meta{cs} \prefixes2212 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\foo|. % Store \val\ inside of a toks-register. The |g| variants use |\global|, the @@ -473,7 +508,7 @@ and the derived files expkv-def.pdf % % \begin{function}{box,gbox} % \begin{syntax} -% box \key\ = \meta{cs} \prefixes212 +% box \key\ = \meta{cs} \prefixes2212 % \end{syntax} % The \meta{cs} should be a single control sequence, such as |\foo|. % Typesets \val\ into a |\hbox| and stores the result in a box register. The @@ -482,7 +517,7 @@ and the derived files expkv-def.pdf % % \begin{function}{meta} % \begin{syntax} -% meta \key\ = \{\kv, \ldots\} \prefixes222 +% meta \key\ = \{\kv, \ldots\} \prefixes2222 % \end{syntax} % This key type can set other keys, you can access the \val\ which was passed % to \key\ inside the \kv\ list with |#1|. It works by calling a sub-|\ekvset| @@ -493,7 +528,7 @@ and the derived files expkv-def.pdf % % \begin{function}{nmeta} % \begin{syntax} -% nmeta \key\ = \{\kv, \ldots\} \prefixes223 +% nmeta \key\ = \{\kv, \ldots\} \prefixes2223 % \end{syntax} % This key type can set other keys, the difference to |meta| is, that this key % doesn't take a value, so the \kv\ list is static. @@ -501,7 +536,7 @@ and the derived files expkv-def.pdf % % \begin{function}{smeta} % \begin{syntax} -% smeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes222 +% smeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes2222 % \end{syntax} % Yet another |meta| variant. An |smeta| key will take a \val\ which you can % access using |#1|, but it sets the \kv\ list inside of \set, so is equal to @@ -510,7 +545,7 @@ and the derived files expkv-def.pdf % % \begin{function}{snmeta} % \begin{syntax} -% snmeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes223 +% snmeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes2223 % \end{syntax} % And the last |meta| variant. |snmeta| is a combination of |smeta| and % |nmeta|. It doesn't take an argument and sets the \kv\ list inside of \set. @@ -518,7 +553,7 @@ and the derived files expkv-def.pdf % % \begin{function}{set} % \begin{syntax} -% set \key\ = \marg{set} \prefixes233 +% set \key\ = \marg{set} \prefixes2233 % \end{syntax} % This will define \key\ to change the set of the current |\ekvset| % invocation to \set. You can omit \set\ (including the equals sign), @@ -530,7 +565,7 @@ and the derived files expkv-def.pdf % % \begin{function}{choice} % \begin{syntax} -% choice \key\ = \{\val=\meta{definition}, \ldots\} \prefixes223 +% choice \key\ = \{\val=\meta{definition}, \ldots\} \prefixes2223 % \end{syntax} % Defines \key\ to be a |choice| key, meaning it will only accept a limited % set of values. You should define each possible \val\ inside of the @@ -546,12 +581,12 @@ and the derived files expkv-def.pdf % % \begin{function}{unknown-choice} % \begin{syntax} -% unknown-choice \key\ = \marg{definition} \prefixes323 +% unknown-choice \key\ = \marg{definition} \prefixes2323 % \end{syntax} -% By default an unknown \val\ passed to a |choice| key will throw an error. -% However, with this prefix you can define an alternative action which should -% be executed if \key\ received an unknown choice. In \meta{definition} you -% can refer to the choice which was passed in with |#1|. +% By default an unknown \val\ passed to a |choice| or |bool| key will throw an +% error. However, with this prefix you can define an alternative action which +% should be executed if \key\ received an unknown choice. In \meta{definition} +% you can refer to the choice which was passed in with |#1|. % \end{function} % % \subsection{Bugs} @@ -579,8 +614,8 @@ and the derived files expkv-def.pdf % ,skip keyI = \keyI % ,toks keyJ = \keyJ % ,default keyJ = \empty test -% ,box keyK = \keyK -% ,qdefault keyK = text +% ,new box keyK = \keyK +% ,qdefault keyK = K % ,choice keyL = % { % protected 1 = \texttt{a} @@ -591,6 +626,8 @@ and the derived files expkv-def.pdf % } % ,edefault keyL = 2 % ,meta keyM = {keyA={#1},keyB=false} +% ,invbool keyN = \keyN +% ,boolpair keyO = \keyOa\keyOb % } % \end{lstlisting} % @@ -718,8 +755,8 @@ and the derived files expkv-def.pdf % \begin{macro}{\ekvdVersion,\ekvdDate} % We're on our first input, so lets store the version and date in a macro. % \begin{macrocode} -\def\ekvdVersion{0.5} -\def\ekvdDate{2020-07-12} +\def\ekvdVersion{0.6} +\def\ekvdDate{2020-10-12} % \end{macrocode} % \end{macro} % @@ -745,8 +782,8 @@ and the derived files expkv-def.pdf % \expkvd\ will use |\ekvd@long|, |\ekvd@prot|, and |\ekvd@ifalso| to store % whether a key should be defined as |\long| or |\protected| or adds an action % to an existing key, and we have to clear them for every new key. By default -% |long| and |protected| will just be empty and |ifalso| will be -% |\@secondoftwo|. +% |long| and |protected| will just be empty, |ifalso| will be +% |\@secondoftwo|, and |ifnew| will just use its third argument. % \begin{macrocode} \def\ekvd@empty{} \protected\def\ekvd@clear@prefixes @@ -754,23 +791,12 @@ and the derived files expkv-def.pdf \let\ekvd@long\ekvd@empty \let\ekvd@prot\ekvd@empty \let\ekvd@ifalso\@secondoftwo + \long\def\ekvd@ifnew##1##2##3{##3}% } \ekvd@clear@prefixes % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\ekvd@exp@Nno,\ekvd@exp@reinsert@n} -% These are expansion helpers, similar to what \LaTeX3 uses, but simpler and -% for just a few cases -% \begin{macrocode} -\long\def\ekvd@exp@Nno#1#2#3% - {% - \expandafter\ekvd@exp@reinsert@n\expandafter{#3}{#1{#2}}% - } -\long\def\ekvd@exp@reinsert@n#1#2{#2{#1}} -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\ekvdefinekeys} % This is the one front-facing macro which provides the interface to define % keys. It's using |\ekvparse| to handle the \kv\ list, the interpretation will @@ -780,18 +806,28 @@ and the derived files expkv-def.pdf \protected\def\ekvdefinekeys#1% {% \def\ekvd@set{#1}% - \ekvparse\ekvd@noarg\ekvd@ + \ekvparse\ekvd@noarg\ekvd@arg } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\ekvd@noarg,\ekvd@} -% |\ekvd@noarg| just places a special marker and gives control to |\ekvd@|. -% |\ekvd@| has to test whether there is a space inside the key and if so calls -% the prefix grabbing routine, else we throw an error and ignore the key. +% \begin{macro}[internal]{\ekvd@noarg,\ekvd@arg,\ekvd@handle} +% |\ekvd@noarg| and |\ekvd@arg| store whether there was a value in the \kv\ +% pair. |\ekvd@handle| has to test whether there is a space inside the key and +% if so calls the prefix grabbing routine, else we throw an error and ignore the +% key. % \begin{macrocode} -\protected\def\ekvd@noarg#1{\ekvd@{#1}\ekvd@noarg@mark} -\protected\long\def\ekvd@#1#2% +\protected\def\ekvd@noarg#1% + {% + \let\ekvd@ifnoarg\@firstoftwo + \ekvd@handle{#1}{}% + } +\protected\def\ekvd@arg + {% + \let\ekvd@ifnoarg\@secondoftwo + \ekvd@handle + } +\protected\long\def\ekvd@handle#1#2% {% \ekvd@clear@prefixes \edef\ekvd@cur{\detokenize{#1}}% @@ -839,7 +875,7 @@ and the derived files expkv-def.pdf % \end{macro} % % \begin{macro}[internal] -% {\ekvd@p@long,\ekvd@p@protected,\ekvd@p@protect,\ekvd@p@also} +% {\ekvd@p@long,\ekvd@p@protected,\ekvd@p@protect,\ekvd@p@also,\ekvd@p@new} % Define the |@p@| type prefixes, they all just store some information in a % temporary macro. % \begin{macrocode} @@ -847,36 +883,45 @@ and the derived files expkv-def.pdf \protected\def\ekvd@p@protected{\let\ekvd@prot\protected} \let\ekvd@p@protect\ekvd@p@protected \protected\def\ekvd@p@also{\let\ekvd@ifalso\@firstoftwo} +\protected\def\ekvd@p@new{\let\ekvd@ifnew\ekvd@assert@new} % \end{macrocode} % \end{macro} % % \subsubsection{Key Types} % -% \begin{macro}[internal]{\ekvd@t@set} +% \begin{macro}[internal]{\ekvd@type@set,\ekvd@t@set} % The |set| type is quite straight forward, just define a |NoVal| key to call % |\ekvchangeset|. % \begin{macrocode} -\protected\def\ekvd@t@set#1#2% +\protected\def\ekvd@type@set#1#2% {% \ekvd@assert@not@long \ekvd@assert@not@protected - \ekv@ifempty{#2}% - {\ekvd@err@missing@definition}% + \ekvd@ifnew{NoVal}{#1}% {% - \ekvd@ifalso + \ekv@ifempty{#2}% + {\ekvd@err@missing@definition}% {% - \ekvd@ifnoarg{#2}% - {\ekvd@add@noval{#1}{\ekvchangeset{#1}}}% - {\ekvd@add@noval{#1}{\ekvchangeset{#2}}}% - \ekvd@assert@not@protected@also - }% - {% - \ekvd@ifnoarg{#2}% - {\ekvdefNoVal\ekvd@set{#1}{\ekvchangeset{#1}}}% - {\ekvdefNoVal\ekvd@set{#1}{\ekvchangeset{#2}}}% + \ekvd@ifalso + {% + \ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekvd@add@noval{#1}}}% + {\ekvchangeset{#2}}% + \ekvd@assert@not@protected@also + }% + {% + \ekv@expB@unbraceA + {\ekv@expB@unbraceA{\ekvdefNoVal\ekvd@set{#1}}}% + {\ekvchangeset{#2}}% + }% }% }% } +\protected\def\ekvd@t@set#1#2% + {% + \ekvd@ifnoarg + {\ekvd@type@set{#1}{#1}}% + {\ekvd@type@set{#1}{#2}}% + } % \end{macrocode} % \end{macro} % @@ -888,19 +933,22 @@ and the derived files expkv-def.pdf % |@type@|. |noval| and |enoval| are so similar that we can use such a |@type@| % macro, even if we could've done |noval| in a slightly faster way without it. % \begin{macrocode} -\protected\long\def\ekvd@type@noval#1#2#3#4% +\protected\long\def\ekvd@type@noval#1#2#3% {% - \ekvd@assert@arg{#4}% + \ekvd@ifnew{NoVal}{#2}% {% - \ekvd@assert@not@long - \ekvd@prot#2\ekvd@tmp{#4}% - \ekvd@ifalso - {\ekvd@exp@Nno\ekvd@add@noval{#3}\ekvd@tmp{}}% - {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}% + \ekvd@assert@arg + {% + \ekvd@assert@not@long + \ekvd@prot#1\ekvd@tmp{#3}% + \ekvd@ifalso + {\ekv@expB@unbraceA{\ekvd@add@noval{#2}}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#2}\ekvd@tmp}% + }% }% } -\protected\def\ekvd@t@noval{\ekvd@type@noval{}\def} -\protected\def\ekvd@t@enoval{\ekvd@type@noval e\edef} +\protected\def\ekvd@t@noval{\ekvd@type@noval\def} +\protected\def\ekvd@t@enoval{\ekvd@type@noval\edef} % \end{macrocode} % \end{macro} % @@ -908,18 +956,21 @@ and the derived files expkv-def.pdf % |code| is simple as well, |ecode| has to use |\edef| on a temporary macro, % since \expkv\ doesn't provide an |\ekvedef|. % \begin{macrocode} -\protected\long\def\ekvd@type@code#1#2#3#4% +\protected\long\def\ekvd@type@code#1#2#3% {% - \ekvd@assert@arg{#4} + \ekvd@ifnew{}{#2}% {% - \ekvd@prot\ekvd@long#2\ekvd@tmp##1{#4}% - \ekvd@ifalso - {\ekvd@exp@Nno\ekvd@add@val{#3}{\ekvd@tmp{##1}}{}}% - {\ekvlet\ekvd@set{#3}\ekvd@tmp}% + \ekvd@assert@arg + {% + \ekvd@prot\ekvd@long#1\ekvd@tmp##1{#3}% + \ekvd@ifalso + {\ekv@expB@unbraceA{\ekvd@add@val{#2}}{\ekvd@tmp{##1}}{}}% + {\ekvlet\ekvd@set{#2}\ekvd@tmp}% + }% }% } -\protected\def\ekvd@t@code{\ekvd@type@code{}\def} -\protected\def\ekvd@t@ecode{\ekvd@type@code e\edef} +\protected\def\ekvd@t@code{\ekvd@type@code\def} +\protected\def\ekvd@t@ecode{\ekvd@type@code\edef} % \end{macrocode} % \end{macro} % @@ -930,27 +981,28 @@ and the derived files expkv-def.pdf % temporary macro that expands |\ekvd@set| and the |\csname| for the key, and in % the case of |qdefault| does the first expansion step of the key-macro. % \begin{macrocode} -\protected\long\def\ekvd@type@default#1#2#3#4% +\protected\long\def\ekvd@type@default#1#2#3% {% - \ekvd@assert@arg{#4}% + \ekvd@assert@arg {% - \ekvifdefined\ekvd@set{#3}% + \ekvifdefined\ekvd@set{#2}% {% + \ekvd@assert@not@new \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp {% - \unexpanded\expandafter#2% - {\csname\ekv@name\ekvd@set{#3}\endcsname{#4}}% + \unexpanded\expandafter#1% + {\csname\ekv@name\ekvd@set{#2}\endcsname{#3}}% }% \ekvd@ifalso - {\ekvd@exp@Nno\ekvd@add@noval{#3}\ekvd@tmp{}}% - {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}% + {\ekv@expB@unbraceA{\ekvd@add@noval{#2}}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#2}\ekvd@tmp}% }% - {\ekvd@err@undefined@key{#3}}% + {\ekvd@err@undefined@key{#2}}% }% } -\protected\def\ekvd@t@default{\ekvd@type@default{}{}} -\protected\def\ekvd@t@qdefault{\ekvd@type@default q{\expandafter\expandafter}} +\protected\def\ekvd@t@default{\ekvd@type@default{}} +\protected\def\ekvd@t@qdefault{\ekvd@type@default{\expandafter\expandafter}} % \end{macrocode} % \end{macro} % @@ -960,15 +1012,16 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\long\def\ekvd@t@edefault#1#2% {% - \ekvd@assert@arg{#2}% + \ekvd@assert@arg {% \ekvifdefined\ekvd@set{#1}% {% + \ekvd@assert@not@new \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp {\csname\ekv@name\ekvd@set{#1}\endcsname{#2}}% \ekvd@ifalso - {\ekvd@exp@Nno\ekvd@add@noval{#1}\ekvd@tmp{}}% + {\ekv@expB@unbraceA{\ekvd@add@noval{#1}}\ekvd@tmp{}}% {\ekvletNoVal\ekvd@set{#1}\ekvd@tmp}% }% {\ekvd@err@undefined@key{#1}}% @@ -979,115 +1032,150 @@ and the derived files expkv-def.pdf % % \begin{macro}[internal]{\ekvd@t@initial,\ekvd@t@oinitial,\ekvd@t@einitial} % \begin{macrocode} -\long\def\ekvd@t@initial#1#2% - {% - \ekvd@assert@arg{#2}% - {% - \ekvifdefined\ekvd@set{#1}% - {% - \ekvd@assert@not@also - \ekvd@assert@not@long - \ekvd@assert@not@protected - \csname\ekv@name\ekvd@set{#1}\endcsname{#2}% - }% - {\ekvd@err@undefined@key{#1}}% - }% - } -\long\def\ekvd@t@oinitial#1#2% +\long\def\ekvd@type@initial#1#2#3% {% - \ekvd@assert@arg{#2}% + \ekvd@assert@arg {% - \ekvifdefined\ekvd@set{#1}% + \ekvifdefined\ekvd@set{#2}% {% + \ekvd@assert@not@new \ekvd@assert@not@also \ekvd@assert@not@long \ekvd@assert@not@protected - \csname\ekv@name\ekvd@set{#1}\expandafter\endcsname\expandafter{#2}% - }% - {\ekvd@err@undefined@key{#1}}% - }% - } -\long\def\ekvd@t@einitial#1#2% - {% - \ekvd@assert@arg{#2}% - {% - \ekvifdefined\ekvd@set{#1}% - {% - \ekvd@assert@not@also - \ekvd@assert@not@long - \ekvd@assert@not@protected - \edef\ekvd@tmp{#2}% - \csname\ekv@name\ekvd@set{#1}\expandafter\endcsname\expandafter + #1{#3}% + \csname\ekv@name\ekvd@set{#2}\expandafter\endcsname\expandafter {\ekvd@tmp}% }% - {\ekvd@err@undefined@key{#1}}% + {\ekvd@err@undefined@key{#2}}% }% } +\def\ekvd@t@initial{\ekvd@type@initial{\def\ekvd@tmp}} +\def\ekvd@t@oinitial{\ekvd@type@initial{\ekv@expB@unbraceA{\def\ekvd@tmp}}} +\def\ekvd@t@einitial{\ekvd@type@initial{\edef\ekvd@tmp}} % \end{macrocode} % \end{macro} % % \begin{macro}[internal] -% {\ekvd@type@bool,\ekvd@t@bool,\ekvd@t@gbool,\ekvd@t@boolTF,\ekvd@t@gboolTF} +% { +% \ekvd@type@bool,\ekvd@t@bool,\ekvd@t@gbool,\ekvd@t@boolTF,\ekvd@t@gboolTF, +% \ekvd@t@invbool,\ekvd@t@ginvbool,\ekvd@t@invboolTF,\ekvd@t@ginvboolTF, +% } % The boolean types are a quicker version of a |choice| that accept |true| and % |false|, and set up the |NoVal| action to be identical to \texttt{\key=true}. % The |true| and |false| actions are always just |\let|ting the macro in |#7| to % some other macro (\emph{e.g.}, \cs[no-index]{iftrue}). % \begin{macrocode} -\protected\def\ekvd@type@bool#1#2#3#4#5#6#7% +\protected\def\ekvd@type@bool#1#2#3#4#5% {% - \ekvd@assert@filledarg{#7}% + \ekvd@ifnew{}{#4}% {% - \ekvd@newlet#7#5% - \ekvd@type@choice{#1bool#2}{#6}% - \protected\ekvdefNoVal\ekvd@set{#6}{#3\let#7#4}% - \protected\expandafter\def - \csname\ekvd@choice@name\ekvd@set{#6}{true}\endcsname - {#3\let#7#4}% - \protected\expandafter\def - \csname\ekvd@choice@name\ekvd@set{#6}{false}\endcsname - {#3\let#7#5}% + \ekvd@ifnew{NoVal}{#4}% + {% + \ekvd@assert@filledarg{#5}% + {% + \ekvd@newlet#5#3% + \ekvd@type@choice{#4}% + \protected\ekvdefNoVal\ekvd@set{#4}{#1\let#5#2}% + \protected\expandafter\def + \csname\ekvd@choice@name\ekvd@set{#4}{true}\endcsname + {#1\let#5#2}% + \protected\expandafter\def + \csname\ekvd@choice@name\ekvd@set{#4}{false}\endcsname + {#1\let#5#3}% + }% + }% }% } -\protected\def\ekvd@t@bool{\ekvd@type@bool{}{}{}\iftrue\iffalse} -\protected\def\ekvd@t@gbool{\ekvd@type@bool g{}\global\iftrue\iffalse} -\protected\def\ekvd@t@boolTF{\ekvd@type@bool{}{TF}{}\@firstoftwo\@secondoftwo} -\protected\def\ekvd@t@gboolTF - {\ekvd@type@bool g{TF}\global\@firstoftwo\@secondoftwo} +\protected\def\ekvd@t@bool{\ekvd@type@bool{}\iftrue\iffalse} +\protected\def\ekvd@t@gbool{\ekvd@type@bool\global\iftrue\iffalse} +\protected\def\ekvd@t@boolTF{\ekvd@type@bool{}\@firstoftwo\@secondoftwo} +\protected\def\ekvd@t@gboolTF{\ekvd@type@bool\global\@firstoftwo\@secondoftwo} +\protected\def\ekvd@t@invbool{\ekvd@type@bool{}\iffalse\iftrue} +\protected\def\ekvd@t@ginvbool{\ekvd@type@bool\global\iffalse\iftrue} +\protected\def\ekvd@t@invboolTF{\ekvd@type@bool{}\@secondoftwo\@firstoftwo} +\protected\def\ekvd@t@ginvboolTF + {\ekvd@type@bool\global\@secondoftwo\@firstoftwo} % \end{macrocode} % \end{macro} % % \begin{macro}[internal] % { -% \ekvd@type@data,\ekvd@t@data,\ekvd@t@gdata,\ekvd@t@dataT,\ekvd@t@gdataT +% \ekvd@type@boolpair, +% \ekvd@t@boolpair,\ekvd@t@gboolpair,\ekvd@t@boolpairTF,\ekvd@t@gboolpairTF % } +% The boolean pair types are essentially the same as the boolean types, but set +% two macros instead of one. % \begin{macrocode} -\protected\def\ekvd@type@data#1#2#3#4#5#6#7#8% +\protected\def\ekvd@type@boolpair#1#2#3#4#5#6% {% - \ekvd@assert@filledarg{#8}% + \ekvd@ifnew{}{#4}% {% - \ekvd@newlet#8#3% - \ekvd@ifalso + \ekvd@ifnew{NoVal}{#4}% {% - \let\ekvd@prot\protected - \ekvd@add@val{#7}{\long#4#8####1#5{####1{#6}}}{}% + \ekvd@newlet#5#3% + \ekvd@newlet#6#2% + \ekvd@type@choice{#4}% + \protected\ekvdefNoVal\ekvd@set{#4}{#1\let#5#2#1\let#6#3}% + \protected\expandafter\def + \csname\ekvd@choice@name\ekvd@set{#4}{true}\endcsname + {#1\let#5#2#1\let#6#3}% + \protected\expandafter\def + \csname\ekvd@choice@name\ekvd@set{#4}{false}\endcsname + {#1\let#5#3#1\let#6#2}% }% + }% + } +\protected\def\ekvd@t@boolpair#1#2% + {\ekvd@assert@twoargs{#2}{\ekvd@type@boolpair{}\iftrue\iffalse{#1}#2}} +\protected\def\ekvd@t@gboolpair#1#2% + {\ekvd@assert@twoargs{#2}{\ekvd@type@boolpair\global\iftrue\iffalse{#1}#2}} +\protected\def\ekvd@t@boolpairTF#1#2% + {% + \ekvd@assert@twoargs{#2}% + {\ekvd@type@boolpair{}\@firstoftwo\@secondoftwo{#1}#2}% + } +\protected\def\ekvd@t@gboolpairTF#1#2% + {% + \ekvd@assert@twoargs{#2}% + {\ekvd@type@boolpair\global\@firstoftwo\@secondoftwo{#1}#2}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% { +% \ekvd@type@data,\ekvd@t@data,\ekvd@t@gdata,\ekvd@t@dataT,\ekvd@t@gdataT +% } +% \begin{macrocode} +\protected\def\ekvd@type@data#1#2#3#4#5#6% + {% + \ekvd@ifnew{}{#5}% + {% + \ekvd@assert@filledarg{#6}% {% - \protected\ekvd@long\ekvdef\ekvd@set{#7}% - {\long#4#8####1#5{####1{#6}}}% + \ekvd@newlet#6#1% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#5}{\long#2#6####1#3{####1{#4}}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#5}% + {\long#2#6####1#3{####1{#4}}}% + }% }% }% } \protected\def\ekvd@t@data - {\ekvd@type@data{}{}\@secondoftwo\edef{####2}{\unexpanded{##1}}} -\protected\def\ekvd@t@edata{\ekvd@type@data e{}\@secondoftwo\edef{####2}{##1}} + {\ekvd@type@data\@secondoftwo\edef{####2}{\unexpanded{##1}}} +\protected\def\ekvd@t@edata{\ekvd@type@data\@secondoftwo\edef{####2}{##1}} \protected\def\ekvd@t@gdata - {\ekvd@type@data g{}\@secondoftwo\xdef{####2}{\unexpanded{##1}}} -\protected\def\ekvd@t@xdata{\ekvd@type@data x{}\@secondoftwo\xdef{####2}{##1}} -\protected\def\ekvd@t@dataT{\ekvd@type@data{}T\@gobble\edef{}{\unexpanded{##1}}} -\protected\def\ekvd@t@edataT{\ekvd@type@data eT\@gobble\edef{}{##1}} -\protected\def\ekvd@t@gdataT - {\ekvd@type@data gT\@gobble\xdef{}{\unexpanded{##1}}} -\protected\def\ekvd@t@xdataT{\ekvd@type@data xT\@gobble\xdef{}{##1}} + {\ekvd@type@data\@secondoftwo\xdef{####2}{\unexpanded{##1}}} +\protected\def\ekvd@t@xdata{\ekvd@type@data\@secondoftwo\xdef{####2}{##1}} +\protected\def\ekvd@t@dataT{\ekvd@type@data\@gobble\edef{}{\unexpanded{##1}}} +\protected\def\ekvd@t@edataT{\ekvd@type@data\@gobble\edef{}{##1}} +\protected\def\ekvd@t@gdataT{\ekvd@type@data\@gobble\xdef{}{\unexpanded{##1}}} +\protected\def\ekvd@t@xdataT{\ekvd@type@data\@gobble\xdef{}{##1}} % \end{macrocode} % \end{macro} % @@ -1098,45 +1186,51 @@ and the derived files expkv-def.pdf % whether the first argument is defined and if not does % |\csname new#2\endcsname#1|. % \begin{macrocode} -\protected\def\ekvd@type@box#1#2#3#4% +\protected\def\ekvd@type@box#1#2#3% {% - \ekvd@assert@filledarg{#4}% + \ekvd@ifnew{}{#2}% {% - \ekvd@newreg#4{box}% - \ekvd@ifalso - {% - \let\ekvd@prot\protected - \ekvd@add@val{#3}{#2\setbox#4\hbox{\begingroup##1\endgroup}}{}% - }% + \ekvd@assert@filledarg{#3}% {% - \protected\ekvd@long\ekvdef\ekvd@set{#3}% - {#2\setbox#4\hbox{\begingroup##1\endgroup}}% + \ekvd@newreg#3{box}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#2}{#1\setbox#3\hbox{\begingroup##1\endgroup}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#2}% + {#1\setbox#3\hbox{\begingroup##1\endgroup}}% + }% }% }% } -\protected\def\ekvd@t@box{\ekvd@type@box{}{}} -\protected\def\ekvd@t@gbox{\ekvd@type@box g\global} +\protected\def\ekvd@t@box{\ekvd@type@box{}} +\protected\def\ekvd@t@gbox{\ekvd@type@box\global} % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\ekvd@type@toks,\ekvd@t@toks,\ekvd@t@gtoks} % Similar to |box|, but set the |toks|. % \begin{macrocode} -\protected\def\ekvd@type@toks#1#2#3#4% +\protected\def\ekvd@type@toks#1#2#3% {% - \ekvd@assert@filledarg{#4}% + \ekvd@ifnew{}{#2}% {% - \ekvd@newreg#4{toks}% - \ekvd@ifalso + \ekvd@assert@filledarg{#3}% {% - \let\ekvd@prot\protected - \ekvd@add@val{#3}{#2#4{##1}}{}% + \ekvd@newreg#3{toks}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#2}{#1#3{##1}}{}% + }% + {\protected\ekvd@long\ekvdef\ekvd@set{#2}{#1#3{##1}}}% }% - {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}}% }% } -\protected\def\ekvd@t@toks{\ekvd@type@toks{}{}} -\protected\def\ekvd@t@gtoks{\ekvd@type@toks{g}\global} +\protected\def\ekvd@t@toks{\ekvd@type@toks{}} +\protected\def\ekvd@t@gtoks{\ekvd@type@toks\global} % \end{macrocode} % \end{macro} % @@ -1144,24 +1238,27 @@ and the derived files expkv-def.pdf % Just like |toks|, but expand the current contents of the |toks| register to % append the new contents. % \begin{macrocode} -\protected\def\ekvd@type@apptoks#1#2#3#4% +\protected\def\ekvd@type@apptoks#1#2#3% {% - \ekvd@assert@filledarg{#4}% + \ekvd@ifnew{}{#2}% {% - \ekvd@newreg#4{toks}% - \ekvd@ifalso - {% - \let\ekvd@prot\protected - \ekvd@add@val{#3}{#2#4\expandafter{\the#4##1}}{}% - }% + \ekvd@assert@filledarg{#3}% {% - \protected\ekvd@long\ekvdef\ekvd@set{#3}% - {#2#4\expandafter{\the#4##1}}% + \ekvd@newreg#3{toks}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#2}{#1#3\expandafter{\the#3##1}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#2}% + {#1#3\expandafter{\the#3##1}}% + }% }% }% } -\protected\def\ekvd@t@apptoks{\ekvd@type@apptoks{}{}} -\protected\def\ekvd@t@gapptoks{\ekvd@type@apptoks{g}\global} +\protected\def\ekvd@t@apptoks{\ekvd@type@apptoks{}} +\protected\def\ekvd@t@gapptoks{\ekvd@type@apptoks\global} % \end{macrocode} % \end{macro} % @@ -1174,31 +1271,34 @@ and the derived files expkv-def.pdf % The |\ekvd@type@reg| can handle all the types for which the assignment will % just be \texttt{\meta{register}=\meta{value}}. % \begin{macrocode} -\protected\def\ekvd@type@reg#1#2#3#4#5#6#7% +\protected\def\ekvd@type@reg#1#2#3#4#5#6% {% - \ekvd@assert@filledarg{#7}% + \ekvd@ifnew{}{#5}% {% - \ekvd@newreg#7{#2}% - \ekvd@ifalso + \ekvd@assert@filledarg{#6}% {% - \let\evkd@prot\protected - \ekvd@add@val{#6}{#3#7=#4##1#5\relax}{}% + \ekvd@newreg#6{#1}% + \ekvd@ifalso + {% + \let\evkd@prot\protected + \ekvd@add@val{#5}{#2#6=#3##1#4\relax}{}% + }% + {\protected\ekvd@long\ekvdef\ekvd@set{#5}{#2#6=#3##1#4\relax}}% }% - {\protected\ekvd@long\ekvdef\ekvd@set{#6}{#3#7=#4##1#5\relax}}% }% } -\protected\def\ekvd@t@int{\ekvd@type@reg{int}{count}{}{}{}} -\protected\def\ekvd@t@eint{\ekvd@type@reg{eint}{count}{}\numexpr\relax} -\protected\def\ekvd@t@gint{\ekvd@type@reg{gint}{count}\global{}{}} -\protected\def\ekvd@t@xint{\ekvd@type@reg{xint}{count}\global\numexpr\relax} -\protected\def\ekvd@t@dimen{\ekvd@type@reg{dimen}{dimen}{}{}{}} -\protected\def\ekvd@t@edimen{\ekvd@type@reg{edimen}{dimen}{}\dimexpr\relax} -\protected\def\ekvd@t@gdimen{\ekvd@type@reg{gdimen}{dimen}\global{}{}} -\protected\def\ekvd@t@xdimen{\ekvd@type@reg{xdimen}{dimen}\global\dimexpr\relax} -\protected\def\ekvd@t@skip{\ekvd@type@reg{skip}{skip}{}{}{}} -\protected\def\ekvd@t@eskip{\ekvd@type@reg{eskip}{skip}{}\glueexpr\relax} -\protected\def\ekvd@t@gskip{\ekvd@type@reg{gskip}{skip}\global{}{}} -\protected\def\ekvd@t@xskip{\ekvd@type@reg{xskip}{skip}\global\glueexpr\relax} +\protected\def\ekvd@t@int{\ekvd@type@reg{count}{}{}{}} +\protected\def\ekvd@t@eint{\ekvd@type@reg{count}{}\numexpr\relax} +\protected\def\ekvd@t@gint{\ekvd@type@reg{count}\global{}{}} +\protected\def\ekvd@t@xint{\ekvd@type@reg{count}\global\numexpr\relax} +\protected\def\ekvd@t@dimen{\ekvd@type@reg{dimen}{}{}{}} +\protected\def\ekvd@t@edimen{\ekvd@type@reg{dimen}{}\dimexpr\relax} +\protected\def\ekvd@t@gdimen{\ekvd@type@reg{dimen}\global{}{}} +\protected\def\ekvd@t@xdimen{\ekvd@type@reg{dimen}\global\dimexpr\relax} +\protected\def\ekvd@t@skip{\ekvd@type@reg{skip}{}{}{}} +\protected\def\ekvd@t@eskip{\ekvd@type@reg{skip}{}\glueexpr\relax} +\protected\def\ekvd@t@gskip{\ekvd@type@reg{skip}\global{}{}} +\protected\def\ekvd@t@xskip{\ekvd@type@reg{skip}\global\glueexpr\relax} % \end{macrocode} % \end{macro} % @@ -1208,40 +1308,24 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@store#1#2#3#4% {% - \ekvd@assert@filledarg{#4}% - {% - \ekvd@newlet#4\ekvd@empty - \ekvd@ifalso - {% - \let\ekvd@prot\protected - \ekvd@add@val{#3}{#2#4{\unexpanded{##1}}}{}% - }% - {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{\unexpanded{##1}}}}% - }% - } -\protected\def\ekvd@t@store{\ekvd@type@store{}\edef} -\protected\def\ekvd@t@gstore{\ekvd@type@store{g}\xdef} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\ekvd@type@estore,\ekvd@t@estore,\ekvd@t@xstore} -% And the straight forward |estore| types. -% \begin{macrocode} -\protected\def\ekvd@type@estore#1#2#3#4% - {% - \ekvd@assert@filledarg{#4}% + \ekvd@ifnew{}{#3}% {% - \ekvd@newlet#4\ekvd@empty - \ekvd@ifalso + \ekvd@assert@filledarg{#4}% {% - \let\ekvd@prot\protected - \ekvd@add@val{#3}{#2#4{##1}}{}% + \ekvd@newlet#4\ekvd@empty + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#1#4{#2}}{}% + }% + {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#1#4{#2}}}% }% - {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}}% }% } -\protected\def\ekvd@t@estore{\ekvd@type@estore{e}\edef} -\protected\def\ekvd@t@xstore{\ekvd@type@estore{x}\xdef} +\protected\def\ekvd@t@store{\ekvd@type@store\edef{\unexpanded{##1}}} +\protected\def\ekvd@t@gstore{\ekvd@type@store\xdef{\unexpanded{##1}}} +\protected\def\ekvd@t@estore{\ekvd@type@store\edef{##1}} +\protected\def\ekvd@t@xstore{\ekvd@type@store\xdef{##1}} % \end{macrocode} % \end{macro} % @@ -1253,15 +1337,18 @@ and the derived files expkv-def.pdf % |meta| sets up things such that another instance of |\ekvset| will be run on % the argument, with the same \set. % \begin{macrocode} -\protected\long\def\ekvd@type@meta#1#2#3#4#5#6#7#8% +\protected\long\def\ekvd@type@meta#1#2#3#4#5#6#7% {% - \ekvd@assert@filledarg{#8}% + \ekvd@ifnew{#1}{#6}% {% - \edef\ekvd@tmp{\ekvd@set}% - \expandafter\ekvd@type@meta@a\expandafter{\ekvd@tmp}{#8}{#3}% - \ekvd@ifalso - {\ekvd@exp@Nno#4{#7}{\ekvd@tmp#5}{#6}}% - {#2\ekvd@set{#7}\ekvd@tmp}% + \ekvd@assert@filledarg{#7}% + {% + \edef\ekvd@tmp{\ekvd@set}% + \expandafter\ekvd@type@meta@a\expandafter{\ekvd@tmp}{#7}{#2}% + \ekvd@ifalso + {\ekv@expB@unbraceA{#3{#6}}{\ekvd@tmp#4}{#5}}% + {\csname ekvlet#1\endcsname\ekvd@set{#6}\ekvd@tmp}% + }% }% } \protected\long\def\ekvd@type@meta@a#1#2% @@ -1276,12 +1363,11 @@ and the derived files expkv-def.pdf {% \ekvd@prot\ekvd@long\def\ekvd@tmp#2{#1}% } -\protected\def\ekvd@t@meta{\ekvd@type@meta{}\ekvlet{##1}\ekvd@add@val{{##1}}{}} +\protected\def\ekvd@t@meta{\ekvd@type@meta{}{##1}\ekvd@add@val{{##1}}{}} \protected\def\ekvd@t@nmeta {% \ekvd@assert@not@long - \ekvd@type@meta - n\ekvletNoVal{}\ekvd@add@noval{}\ekvd@assert@not@long@also + \ekvd@type@meta{NoVal}{}\ekvd@add@noval{}\ekvd@assert@not@long@also } % \end{macrocode} % \end{macro} @@ -1292,23 +1378,24 @@ and the derived files expkv-def.pdf % such that the first is the \set\ for which the sub-|\ekvset| and the second is % the \kv\ list. % \begin{macrocode} -\protected\long\def\ekvd@type@smeta#1#2#3#4#5#6#7#8% +\protected\long\def\ekvd@type@smeta#1#2#3#4#5#6#7% {% - \ekvd@assert@twoargs{#8}% + \ekvd@ifnew{#1}{#6}% {% - \ekvd@type@meta@a#8{#3}% - \ekvd@ifalso - {\ekvd@exp@Nno#4{#7}{\ekvd@tmp#5}{#6}}% - {#2\ekvd@set{#7}\ekvd@tmp}% + \ekvd@assert@twoargs{#7}% + {% + \ekvd@type@meta@a#7{#2}% + \ekvd@ifalso + {\ekv@expB@unbraceA{#3{#6}}{\ekvd@tmp#4}{#5}}% + {\csname ekvlet#1\endcsname\ekvd@set{#6}\ekvd@tmp}% + }% }% } -\protected\def\ekvd@t@smeta - {\ekvd@type@smeta{}\ekvlet{##1}\ekvd@add@val{{##1}}{}} +\protected\def\ekvd@t@smeta{\ekvd@type@smeta{}{##1}\ekvd@add@val{{##1}}{}} \protected\def\ekvd@t@snmeta {% \ekvd@assert@not@long - \ekvd@type@smeta - n\ekvletNoVal{}\ekvd@add@noval{}\ekvd@assert@not@long@also + \ekvd@type@smeta{NoVal}{}\ekvd@add@noval{}\ekvd@assert@not@long@also } % \end{macrocode} % \end{macro} @@ -1326,18 +1413,28 @@ and the derived files expkv-def.pdf % allowed to be long). |\ekvd@type@choice| will just define the choice-key, the % handling of the choices definition will be done by |\ekvd@populate@choice|. % \begin{macrocode} -\protected\def\ekvd@type@choice#1#2% +\protected\def\ekvd@type@choice#1% {% \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp##1% - {% - \unexpanded{\ekvd@h@choice}{\ekvd@choice@name\ekvd@set{#2}{##1}}% - }% + {\unexpanded{\ekvd@h@choice}{\ekvd@choice@name\ekvd@set{#1}{##1}}}% \ekvd@ifalso {% - \ekvd@exp@Nno\ekvd@add@val{#2}{\ekvd@tmp{##1}}\ekvd@assert@not@long@also + \ekvd@assert@val{#1}% + {% + \ekvd@if@not@already@choice{#1}% + {% + \ekv@expB@unbraceA + {% + \expandafter\ekvd@add@aux + \csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}{#1}% + }% + {\ekvd@tmp{##1}}% + {\ekvd@long\ekvdef}\ekvd@assert@not@long@also + }% + }% }% - {\ekvlet\ekvd@set{#2}\ekvd@tmp}% + {\ekvlet\ekvd@set{#1}\ekvd@tmp}% } % \end{macrocode} % |\ekvd@populate@choice| just uses |\ekvparse| and then gives control to @@ -1362,7 +1459,7 @@ and the derived files expkv-def.pdf \protected\long\def\ekvd@populate@choice@#1#2% {% \ekvd@clear@prefixes - \expandafter\ekvd@assert@arg@msg\expandafter{\ekvd@cur : #1}{#2}% + \expandafter\ekvd@assert@arg@msg\expandafter{\ekvd@cur : #1}% {% \ekvd@ifspace{#1}% {\ekvd@choice@prefix\ekv@mark#1\ekv@stop}% @@ -1406,17 +1503,21 @@ and the derived files expkv-def.pdf } \protected\def\ekvd@choice@p@long{\ekvd@choice@invalid@p{long}}% \protected\def\ekvd@choice@p@also{\ekvd@choice@invalid@p{also}}% +\protected\def\ekvd@choice@p@new{\ekvd@choice@invalid@p{new}}% % \end{macrocode} % Finally we're able to set up the |@t@choice| macro, which has to store the % current choice-key's name, define the key, and parse the available choices. % \begin{macrocode} \protected\long\def\ekvd@t@choice#1#2% {% - \ekvd@assert@arg{#2}% + \ekvd@ifnew{}{#1}% {% - \ekvd@type@choice{choice}{#1}% - \def\ekvd@set@choice{#1}% - \ekvd@populate@choice{#2}% + \ekvd@assert@arg + {% + \ekvd@type@choice{#1}% + \def\ekvd@set@choice{#1}% + \ekvd@populate@choice{#2}% + }% }% } % \end{macrocode} @@ -1426,12 +1527,20 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\long\expandafter\def\csname ekvd@t@unknown-choice\endcsname#1#2% {% - \ekvd@assert@arg{#2}% + \ifx\ekvd@ifnew\ekvd@assert@new + \ekv@fi@firstoftwo + \fi + \@secondoftwo + {\ekv@ifdefined{\ekvd@unknown@choice@name\ekvd@set{#1}}\ekvd@err@not@new}% + \@firstofone {% - \ekvd@assert@not@long - \ekvd@assert@not@also - \ekvd@prot\expandafter - \def\csname\ekvd@unknown@choice@name\ekvd@set{#1}\endcsname##1{#2}% + \ekvd@assert@arg + {% + \ekvd@assert@not@long + \ekvd@assert@not@also + \ekvd@prot\expandafter + \def\csname\ekvd@unknown@choice@name\ekvd@set{#1}\endcsname##1{#2}% + }% }% } % \end{macrocode} @@ -1644,30 +1753,14 @@ and the derived files expkv-def.pdf % \end{macrocode} % \end{macro} % -% \begin{macro}[internal] -% { -% \ekvd@assert@arg,\ekvd@assert@arg@msg,\ekvd@ifnoarg,\ekvd@ifnoarg@, -% \ekvd@ifnoarg@ -% } -% An |\ifx| comparison would fail if the first token of the user input is a -% \TeX-if primitive or the user input contains unbalanced \TeX-if constructs, so -% the test is done using \TeX's argument grabbing logic. +% \begin{macro}[internal]{\ekvd@assert@arg,\ekvd@assert@arg@msg,\ekvd@ifnoarg} +% There is no need to actually define |\ekvd@ifnoarg| here, as it will be set by +% either |\ekvd@arg| or |\ekvd@noarg|. % \begin{macrocode} -\long\def\ekvd@assert@arg#1{\ekvd@ifnoarg{#1}\ekvd@err@missing@definition} -\long\def\ekvd@assert@arg@msg#1#2% +\def\ekvd@assert@arg{\ekvd@ifnoarg\ekvd@err@missing@definition} +\long\def\ekvd@assert@arg@msg#1% {% - \ekvd@ifnoarg{#2}{\ekvd@err@missing@definition@msg{#1}}% - } -\long\def\ekvd@ifnoarg#1% - {% - \ekvd@ifnoarg@\ekvd@ifnoarg@mark#1\ekvd@ifnoarg@mark\ekvd@ifnoarg@t - \ekvd@ifnoarg@mark\ekvd@noarg@mark\ekvd@ifnoarg@mark\@secondoftwo - } -\long\def\ekvd@ifnoarg@#1\ekvd@ifnoarg@mark\ekvd@noarg@mark\ekvd@ifnoarg@mark{} -\long\def\ekvd@ifnoarg@t - \ekvd@ifnoarg@mark\ekvd@noarg@mark\ekvd@ifnoarg@mark\@secondoftwo#1#2% - {% - #1% + \ekvd@ifnoarg{\ekvd@err@missing@definition@msg{#1}}% } % \end{macrocode} % \end{macro} @@ -1680,7 +1773,7 @@ and the derived files expkv-def.pdf } \long\def\ekvd@ifnoarg@or@empty#1% {% - \ekvd@ifnoarg{#1}% + \ekvd@ifnoarg \@firstoftwo {\ekv@ifempty{#1}}% } @@ -1690,7 +1783,8 @@ and the derived files expkv-def.pdf % \begin{macro}[internal] % { % \ekvd@assert@not@long,\ekvd@assert@not@protected,\ekvd@assert@not@also -% \ekvd@assert@not@long@also,\ekvd@assert@not@protected@also +% \ekvd@assert@not@long@also,\ekvd@assert@not@protected@also, +% \ekvd@assert@new,\ekvd@assert@not@new % } % Some key-types don't want to be |also|, |\long| or |\protected|, so we provide % macros to test this and throw an error, this could be silently ignored but now @@ -1699,17 +1793,41 @@ and the derived files expkv-def.pdf % \begin{macrocode} \def\ekvd@assert@not@long{\ifx\ekvd@long\long\ekvd@err@no@prefix{long}\fi} \def\ekvd@assert@not@protected - {% - \ifx\ekvd@prot\protected\ekvd@err@no@prefix{protected}\fi - } + {\ifx\ekvd@prot\protected\ekvd@err@no@prefix{protected}\fi} \def\ekvd@assert@not@also{\ekvd@ifalso{\ekvd@err@no@prefix{also}}{}} \def\ekvd@assert@not@long@also + {\ifx\ekvd@long\long\ekvd@err@no@prefix@also{long}\fi} +\def\ekvd@assert@not@protected@also + {\ifx\ekvd@prot\protected\ekvd@err@no@prefix@also{protected}\fi} +\def\ekvd@assert@new#1#2% + {\csname ekvifdefined#1\endcsname\ekvd@set{#2}{\ekvd@err@not@new}} +\def\ekvd@assert@not@new + {\ifx\ekvd@ifnew\ekvd@assert@new\ekvd@err@no@prefix{new}\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% { +% \ekvd@if@not@already@choice, \ekvd@if@not@already@choice@a, +% \ekvd@if@not@already@choice@b +% } +% It is bad to use |also| on a key that already contains a |choice|, as both +% choices would share the same valid values and thus lead to each callback being +% used twice. The following is a rudimentary test against this. +% \begin{macrocode} +\protected\def\ekvd@if@not@already@choice#1% {% - \ifx\ekvd@long\long\ekvd@err@no@prefix@also{long}\fi + \expandafter\ekvd@if@not@already@choice@a + \csname\ekv@name\ekvd@set{#1}\endcsname + {}\ekvd@h@choice\ekvd@stop } -\def\ekvd@assert@not@protected@also +\protected\def\ekvd@if@not@already@choice@a + {% + \expandafter\ekvd@if@not@already@choice@b + } +\long\protected\def\ekvd@if@not@already@choice@b#1\ekvd@h@choice#2\ekvd@stop {% - \ifx\ekvd@prot\protected\ekvd@err@no@prefix@also{protected}\fi + \ekv@ifempty{#2}\@firstofone\@gobble } % \end{macrocode} % \end{macro} @@ -1741,7 +1859,7 @@ and the derived files expkv-def.pdf % \ekvd@err@missing@type,\ekvd@err@undefined@prefix,\ekvd@err@undefined@key, % \ekvd@err@no@prefix,\ekvd@err@no@prefix@msg,\ekvd@err@no@prefix@also, % \ekvd@err@add@val@on@noval,\ekvd@err@add@noval@on@val, -% \ekvd@err@unsupported@arg +% \ekvd@err@unsupported@arg,\ekvd@err@not@new % } % The non-expandable error messages are boring, so here they are: % \begin{macrocode} @@ -1781,6 +1899,8 @@ and the derived files expkv-def.pdf `\ekvd@extracted@args' for key `\ekvd@cur'% }% } +\protected\def\ekvd@err@not@new + {\ekvd@errm{The key for `\ekvd@cur' is already defined}} % \end{macrocode} % \end{macro} % |