diff options
author | Karl Berry <karl@freefriends.org> | 2020-07-13 21:10:18 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-07-13 21:10:18 +0000 |
commit | ef73787cfd526899301624dd2dc857195c1f6cfa (patch) | |
tree | 94ae45b1cdb21aa8b33fc3141a7d6462777a6fc1 | |
parent | 1f17cf107fbe98a4f0e280b82af0768266bc3446 (diff) |
expkv-def (13jul20)
git-svn-id: svn://tug.org/texlive/trunk@55829 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/expkv-def/README.md | 2 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/expkv-def/expkv-def.pdf | bin | 305480 -> 349285 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx | 637 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex | 449 |
4 files changed, 799 insertions, 289 deletions
diff --git a/Master/texmf-dist/doc/latex/expkv-def/README.md b/Master/texmf-dist/doc/latex/expkv-def/README.md index 444d887336e..69406f1aada 100644 --- a/Master/texmf-dist/doc/latex/expkv-def/README.md +++ b/Master/texmf-dist/doc/latex/expkv-def/README.md @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------- # expkv-def -- a key-defining frontend for expkv -Version 2020-07-04 v0.4 +Version 2020-07-12 v0.5 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-def/expkv-def.pdf b/Master/texmf-dist/doc/latex/expkv-def/expkv-def.pdf Binary files differindex f051a5fe6a7..82f51f95b53 100644 --- a/Master/texmf-dist/doc/latex/expkv-def/expkv-def.pdf +++ b/Master/texmf-dist/doc/latex/expkv-def/expkv-def.pdf 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 3dfff1f80f9..12b58cbe97e 100644 --- a/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx +++ b/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx @@ -152,14 +152,21 @@ and the derived files expkv-def.pdf \newcommand\enflong{\textcolor{black}{long}} \newcommand\alllong{\textcolor{gray}{long}} \newcommand\notlong{\textcolor{red!80!black}{long}} -\newcommand\prefixes[2] +\newcommand\enfalso{\textcolor{black}{also}} +\newcommand\allalso{\textcolor{gray}{also}} +\newcommand\notalso{\textcolor{red!80!black}{also}} +\newcommand\prefixes[3] {^^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#2\relax\or + \ifcase\numexpr#3\relax\or \enflong\or \alllong\or \notlong\fi @@ -170,7 +177,7 @@ and the derived files expkv-def.pdf \DoNotIndex{\protected,\ProvidesFile,\ProvidesPackage,\relax,\space} \DoNotIndex{\@,\unexpanded,\string,\expanded,\dimexpr,\global,\glueexpr,\hbox} \DoNotIndex{\numexpr,\RequirePackage,\setbox,\the,\unless,\xdef,\@firstofone} -\DoNotIndex{\@firstoftwo,\@gobble,\@secondoftwo} +\DoNotIndex{\@firstoftwo,\@gobble,\@secondoftwo,\meaning,\detokenize} \DoNotIndex{\ifcsname} \DoNotIndex{\ifx} \DoNotIndex{\ifdefined} @@ -272,10 +279,38 @@ and the derived files expkv-def.pdf % is allowed for all |t|-prefixes. % % \subsubsection{\texttt{p}-Prefixes}\label{sec:prefix:p} -% The |p|-type prefixes 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. +% 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. +% +% \begin{function}{also} +% The following key type will be \emph{added} to an existing \key's +% definition. You can't add a type taking an argument at use time to an +% existing key which doesn't take an argument and vice versa. Also you'll get +% an error if you try to add an action which isn't allowed to be either |long| +% or |protected| to a key which already is |long| or |protected| (the opposite +% order would be suboptimal as well, but can't be really captured with the +% current code). +% +% A key already defined as |long| or |protected| will stay |long| or +% |protected|, but you can as well add |long| or |protected| with the |also| +% definition. +% +% As a small example, suppose you want to create a boolean key, but +% additionally to setting a boolean value you want to execute some more code +% as well, you can use the following +% \begin{lstlisting} +% \ekvdefinekeys{also-example} +% { +% bool key = \ifmybool +% ,also code key = \domystuff +% } +% \end{lstlisting} +% \end{function} +% % \begin{function}{protected,protect} % The following key will be defined |\protected|. Note that key-types which % can't be defined expandable will always use |\protected|. @@ -295,7 +330,7 @@ and the derived files expkv-def.pdf % % \begin{function}{code,ecode} % \begin{syntax} -% code \key\ = \marg{definition} \prefixes22 +% code \key\ = \marg{definition} \prefixes222 % \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 @@ -304,7 +339,7 @@ and the derived files expkv-def.pdf % % \begin{function}{noval,enoval} % \begin{syntax} -% noval \key\ = \marg{definition} \prefixes23 +% noval \key\ = \marg{definition} \prefixes223 % \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 @@ -313,7 +348,7 @@ and the derived files expkv-def.pdf % % \begin{function}{default,qdefault,edefault} % \begin{syntax} -% default \key\ = \marg{definition} \prefixes23 +% default \key\ = \marg{definition} \prefixes223 % \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\ @@ -325,7 +360,7 @@ and the derived files expkv-def.pdf % % \begin{function}{initial,oinitial,einitial} % \begin{syntax} -% initial \key\ = \{\val\} \prefixes33 +% initial \key\ = \{\val\} \prefixes333 % \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 @@ -336,7 +371,7 @@ and the derived files expkv-def.pdf % % \begin{function}{bool,gbool,boolTF,gboolTF} % \begin{syntax} -% bool \key\ = \meta{cs} \prefixes23 +% bool \key\ = \meta{cs} \prefixes223 % \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 @@ -361,7 +396,7 @@ and the derived files expkv-def.pdf % % \begin{function}{store,estore,gstore,xstore} % \begin{syntax} -% store \key\ = \meta{cs} \prefixes12 +% store \key\ = \meta{cs} \prefixes212 % \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 @@ -373,7 +408,7 @@ and the derived files expkv-def.pdf % % \begin{function}{data,edata,gdata,xdata} % \begin{syntax} -% data \key\ = \meta{cs} \prefixes12 +% data \key\ = \meta{cs} \prefixes212 % \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 @@ -389,7 +424,7 @@ and the derived files expkv-def.pdf % % \begin{function}{dataT,edataT,gdataT,xdataT} % \begin{syntax} -% dataT \key\ = \meta{cs} \prefixes12 +% dataT \key\ = \meta{cs} \prefixes212 % \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 @@ -399,7 +434,7 @@ and the derived files expkv-def.pdf % % \begin{function}{int,eint,gint,xint} % \begin{syntax} -% int \key\ = \meta{cs} \prefixes12 +% int \key\ = \meta{cs} \prefixes212 % \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, @@ -410,7 +445,7 @@ and the derived files expkv-def.pdf % % \begin{function}{dimen,edimen,gdimen,xdimen} % \begin{syntax} -% dimen \key\ = \meta{cs} \prefixes12 +% dimen \key\ = \meta{cs} \prefixes212 % \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 @@ -419,7 +454,7 @@ and the derived files expkv-def.pdf % % \begin{function}{skip,eskip,gskip,xskip} % \begin{syntax} -% skip \key\ = \meta{cs} \prefixes12 +% skip \key\ = \meta{cs} \prefixes212 % \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| @@ -428,7 +463,7 @@ and the derived files expkv-def.pdf % % \begin{function}{toks,gtoks,apptoks,gapptoks} % \begin{syntax} -% toks \key\ = \meta{cs} \prefixes12 +% toks \key\ = \meta{cs} \prefixes212 % \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 @@ -438,7 +473,7 @@ and the derived files expkv-def.pdf % % \begin{function}{box,gbox} % \begin{syntax} -% box \key\ = \meta{cs} \prefixes12 +% box \key\ = \meta{cs} \prefixes212 % \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 @@ -447,7 +482,7 @@ and the derived files expkv-def.pdf % % \begin{function}{meta} % \begin{syntax} -% meta \key\ = \{\kv, \ldots\} \prefixes22 +% meta \key\ = \{\kv, \ldots\} \prefixes222 % \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| @@ -458,7 +493,7 @@ and the derived files expkv-def.pdf % % \begin{function}{nmeta} % \begin{syntax} -% nmeta \key\ = \{\kv, \ldots\} \prefixes23 +% nmeta \key\ = \{\kv, \ldots\} \prefixes223 % \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. @@ -466,7 +501,7 @@ and the derived files expkv-def.pdf % % \begin{function}{smeta} % \begin{syntax} -% smeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes22 +% smeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes222 % \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 @@ -475,7 +510,7 @@ and the derived files expkv-def.pdf % % \begin{function}{snmeta} % \begin{syntax} -% snmeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes23 +% snmeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes223 % \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. @@ -483,7 +518,7 @@ and the derived files expkv-def.pdf % % \begin{function}{set} % \begin{syntax} -% set \key\ = \marg{set} \prefixes33 +% set \key\ = \marg{set} \prefixes233 % \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), @@ -495,7 +530,7 @@ and the derived files expkv-def.pdf % % \begin{function}{choice} % \begin{syntax} -% choice \key\ = \{\val=\meta{definition}, \ldots\} \prefixes23 +% choice \key\ = \{\val=\meta{definition}, \ldots\} \prefixes223 % \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 @@ -511,7 +546,7 @@ and the derived files expkv-def.pdf % % \begin{function}{unknown-choice} % \begin{syntax} -% unknown-choice \key\ = \marg{definition} \prefixes23 +% unknown-choice \key\ = \marg{definition} \prefixes323 % \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 @@ -532,7 +567,7 @@ and the derived files expkv-def.pdf % \begin{lstlisting} % \ekvdefinekeys{example} % { -% ,long code keyA = #1 +% long code keyA = #1 % ,noval keyA = NoVal given % ,bool keyB = \keyB % ,boolTF keyC = \keyC @@ -548,7 +583,7 @@ and the derived files expkv-def.pdf % ,qdefault keyK = text % ,choice keyL = % { -% ,protected 1 = \texttt{a} +% protected 1 = \texttt{a} % ,2 = b % ,3 = c % ,4 = d @@ -556,7 +591,6 @@ and the derived files expkv-def.pdf % } % ,edefault keyL = 2 % ,meta keyM = {keyA={#1},keyB=false} -% ,data % } % \end{lstlisting} % @@ -566,7 +600,7 @@ and the derived files expkv-def.pdf % \begin{lstlisting} % \ekvdefinekeys{ex} % { -% ,data name = \Pname +% data name = \Pname % ,data age = \Page % ,dataT hobby = \Phobby % } @@ -593,7 +627,7 @@ and the derived files expkv-def.pdf % \begingroup % \ekvdefinekeys{ex} % { -% ,data name = \Pname +% data name = \Pname % ,data age = \Page % ,dataT hobby = \Phobby % } @@ -684,8 +718,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.4} -\def\ekvdDate{2020-07-04} +\def\ekvdVersion{0.5} +\def\ekvdDate{2020-07-12} % \end{macrocode} % \end{macro} % @@ -707,21 +741,36 @@ and the derived files expkv-def.pdf % \expkvd\ was initialized. % % \begin{macro}[internal] -% {\ekvd@long,\ekvd@prot,\ekvd@clear@prefixes,\ekvd@empty} -% \expkvd\ will use |\ekvd@long| and |\ekvd@prot| to store whether a key should -% be defined as |\long| or |\protected|, and we have to clear them for every new -% key. By default they'll just be empty. +% {\ekvd@long,\ekvd@prot,\ekvd@clear@prefixes,\ekvd@empty,\ekvd@ifalso} +% \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|. % \begin{macrocode} \def\ekvd@empty{} \protected\def\ekvd@clear@prefixes {% \let\ekvd@long\ekvd@empty \let\ekvd@prot\ekvd@empty + \let\ekvd@ifalso\@secondoftwo } \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 @@ -745,9 +794,10 @@ and the derived files expkv-def.pdf \protected\long\def\ekvd@#1#2% {% \ekvd@clear@prefixes + \edef\ekvd@cur{\detokenize{#1}}% \ekvd@ifspace{#1}% {\ekvd@prefix\ekv@mark#1\ekv@stop{#2}}% - {\ekvd@err@missing@prefix{#1}}% + \ekvd@err@missing@type } % \end{macrocode} % \end{macro} @@ -767,7 +817,7 @@ and the derived files expkv-def.pdf {\ekv@strip{#2}{\csname ekvd@t@#1\endcsname}}% {% \ekv@ifdefined{ekvd@p@#1}% - {\csname ekvd@p@#1\endcsname{#2}}% + {\csname ekvd@p@#1\endcsname\ekvd@prefix@after@p{#2}}% {\ekvd@err@undefined@prefix{#1}\@gobble}% }% } @@ -783,21 +833,20 @@ and the derived files expkv-def.pdf {% \ekvd@ifspace{#1}% {\ekvd@prefix#1\ekv@stop}% - {% - \expandafter\ekvd@err@missing@prefix\expandafter{\ekv@gobble@mark#1}% - \@gobble - }% + {\ekvd@err@missing@type\@gobble}% } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\ekvd@p@long,\ekvd@p@protected,\ekvd@p@protect} +% \begin{macro}[internal] +% {\ekvd@p@long,\ekvd@p@protected,\ekvd@p@protect,\ekvd@p@also} % Define the |@p@| type prefixes, they all just store some information in a -% temporary macro and call |\ekvd@prefix@after@p|. +% temporary macro. % \begin{macrocode} -\protected\def\ekvd@p@long{\let\ekvd@long\long\ekvd@prefix@after@p} -\protected\def\ekvd@p@protected{\let\ekvd@prot\protected\ekvd@prefix@after@p} +\protected\def\ekvd@p@long{\let\ekvd@long\long} +\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} % \end{macrocode} % \end{macro} % @@ -809,14 +858,23 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@t@set#1#2% {% - \ekvd@assert@not@long{set #1}% - \ekvd@assert@not@protected{set #1}% - \ekvd@ifnoarg{#2}% - {\ekvdefNoVal\ekvd@set{#1}{\ekvchangeset{#1}}}% + \ekvd@assert@not@long + \ekvd@assert@not@protected + \ekv@ifempty{#2}% + {\ekvd@err@missing@definition}% {% - \ekv@ifempty{#2}% - {\ekvd@err@missing@definition{set #1}}% - {\ekvdefNoVal\ekvd@set{#1}{\ekvchangeset{#2}}}% + \ekvd@ifalso + {% + \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}}}% + }% }% } % \end{macrocode} @@ -832,11 +890,13 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\long\def\ekvd@type@noval#1#2#3#4% {% - \ekvd@assert@arg{#1noval #3}{#4}% + \ekvd@assert@arg{#4}% {% - \ekvd@assert@not@long{#1noval #3}% + \ekvd@assert@not@long \ekvd@prot#2\ekvd@tmp{#4}% - \ekvletNoVal\ekvd@set{#3}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@noval{#3}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}% }% } \protected\def\ekvd@t@noval{\ekvd@type@noval{}\def} @@ -850,10 +910,12 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\long\def\ekvd@type@code#1#2#3#4% {% - \ekvd@assert@arg{#1code #3}{#4} + \ekvd@assert@arg{#4} {% \ekvd@prot\ekvd@long#2\ekvd@tmp##1{#4}% - \ekvlet\ekvd@set{#3}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@val{#3}{\ekvd@tmp{##1}}{}}% + {\ekvlet\ekvd@set{#3}\ekvd@tmp}% }% } \protected\def\ekvd@t@code{\ekvd@type@code{}\def} @@ -870,17 +932,19 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\long\def\ekvd@type@default#1#2#3#4% {% - \ekvd@assert@arg{#1default #3}{#4}% + \ekvd@assert@arg{#4}% {% \ekvifdefined\ekvd@set{#3}% {% - \ekvd@assert@not@long{#1default #3}% + \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp {% \unexpanded\expandafter#2% {\csname\ekv@name\ekvd@set{#3}\endcsname{#4}}% }% - \ekvletNoVal\ekvd@set{#3}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@noval{#3}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}% }% {\ekvd@err@undefined@key{#3}}% }% @@ -896,14 +960,16 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\long\def\ekvd@t@edefault#1#2% {% - \ekvd@assert@arg{edefault #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{edefault #1}% + \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp {\csname\ekv@name\ekvd@set{#1}\endcsname{#2}}% - \ekvletNoVal\ekvd@set{#1}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@noval{#1}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#1}\ekvd@tmp}% }% {\ekvd@err@undefined@key{#1}}% }% @@ -915,12 +981,13 @@ and the derived files expkv-def.pdf % \begin{macrocode} \long\def\ekvd@t@initial#1#2% {% - \ekvd@assert@arg{initial #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{initial #1}% - \ekvd@assert@not@protected{initial #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}}% @@ -928,12 +995,13 @@ and the derived files expkv-def.pdf } \long\def\ekvd@t@oinitial#1#2% {% - \ekvd@assert@arg{oinitial #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{oinitial #1}% - \ekvd@assert@not@protected{oinitial #1}% + \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}}% @@ -941,12 +1009,13 @@ and the derived files expkv-def.pdf } \long\def\ekvd@t@einitial#1#2% {% - \ekvd@assert@arg{einitial #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{einitial #1}% - \ekvd@assert@not@protected{einitial #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 {\ekvd@tmp}% @@ -966,7 +1035,7 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@bool#1#2#3#4#5#6#7% {% - \ekvd@assert@filledarg{#1bool#2 #6}{#7}% + \ekvd@assert@filledarg{#7}% {% \ekvd@newlet#7#5% \ekvd@type@choice{#1bool#2}{#6}% @@ -992,22 +1061,33 @@ and the derived files expkv-def.pdf % \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#7% +\protected\def\ekvd@type@data#1#2#3#4#5#6#7#8% {% - \ekvd@assert@filledarg{#1data#2 #6}{#7}% + \ekvd@assert@filledarg{#8}% {% - \ekvd@newlet#7#3% - \protected\ekvd@long\ekvdef\ekvd@set{#6}{\long#4#7####1#5{####1{##1}}}% + \ekvd@newlet#8#3% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#7}{\long#4#8####1#5{####1{#6}}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#7}% + {\long#4#8####1#5{####1{#6}}}% + }% }% } -\protected\def\ekvd@t@data{\ekvd@type@data{}{}\@secondoftwo\def{####2}} -\protected\def\ekvd@t@edata{\ekvd@type@data e{}\@secondoftwo\edef{####2}} -\protected\def\ekvd@t@gdata{\ekvd@type@data g{}\@secondoftwo\gdef{####2}} -\protected\def\ekvd@t@xdata{\ekvd@type@data x{}\@secondoftwo\xdef{####2}} -\protected\def\ekvd@t@dataT{\ekvd@type@data{}T\@gobble\def{}} -\protected\def\ekvd@t@edataT{\ekvd@type@data eT\@gobble\edef{}} -\protected\def\ekvd@t@gdataT{\ekvd@type@data gT\@gobble\gdef{}} -\protected\def\ekvd@t@xdataT{\ekvd@type@data xT\@gobble\xdef{}} +\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}} +\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}} % \end{macrocode} % \end{macro} % @@ -1020,11 +1100,18 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@box#1#2#3#4% {% - \ekvd@assert@filledarg{#1box #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newreg#4{box}% - \protected\ekvd@long\ekvdef\ekvd@set{#3}% - {#2\setbox#4\hbox{\begingroup##1\endgroup}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2\setbox#4\hbox{\begingroup##1\endgroup}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#3}% + {#2\setbox#4\hbox{\begingroup##1\endgroup}}% + }% }% } \protected\def\ekvd@t@box{\ekvd@type@box{}{}} @@ -1037,10 +1124,15 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@toks#1#2#3#4% {% - \ekvd@assert@filledarg{#1toks #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newreg#4{toks}% - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2#4{##1}}{}% + }% + {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}}% }% } \protected\def\ekvd@t@toks{\ekvd@type@toks{}{}} @@ -1054,10 +1146,18 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@apptoks#1#2#3#4% {% - \ekvd@assert@filledarg{#1apptoks #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newreg#4{toks}% - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4\expandafter{\the#4##1}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2#4\expandafter{\the#4##1}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#3}% + {#2#4\expandafter{\the#4##1}}% + }% }% } \protected\def\ekvd@t@apptoks{\ekvd@type@apptoks{}{}} @@ -1076,10 +1176,15 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@reg#1#2#3#4#5#6#7% {% - \ekvd@assert@filledarg{#1 #6}{#7}% + \ekvd@assert@filledarg{#7}% {% \ekvd@newreg#7{#2}% - \protected\ekvd@long\ekvdef\ekvd@set{#6}{#3#7=#4##1#5\relax}% + \ekvd@ifalso + {% + \let\evkd@prot\protected + \ekvd@add@val{#6}{#3#7=#4##1#5\relax}{}% + }% + {\protected\ekvd@long\ekvdef\ekvd@set{#6}{#3#7=#4##1#5\relax}}% }% } \protected\def\ekvd@t@int{\ekvd@type@reg{int}{count}{}{}{}} @@ -1103,10 +1208,15 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@store#1#2#3#4% {% - \ekvd@assert@filledarg{#1store #3}{#4}% + \ekvd@assert@filledarg{#4}% {% - \unless\ifdefined#4\let#4\ekvd@empty\fi - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{\unexpanded{##1}}}% + \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} @@ -1119,10 +1229,15 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@estore#1#2#3#4% {% - \ekvd@assert@filledarg{#1store #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newlet#4\ekvd@empty - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2#4{##1}}{}% + }% + {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}}% }% } \protected\def\ekvd@t@estore{\ekvd@type@estore{e}\edef} @@ -1138,13 +1253,15 @@ 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% +\protected\long\def\ekvd@type@meta#1#2#3#4#5#6#7#8% {% - \ekvd@assert@filledarg{#1meta #4}{#5}% + \ekvd@assert@filledarg{#8}% {% \edef\ekvd@tmp{\ekvd@set}% - \expandafter\ekvd@type@meta@a\expandafter{\ekvd@tmp}{#5}{#3}% - #2\ekvd@set{#4}\ekvd@tmp + \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}% }% } \protected\long\def\ekvd@type@meta@a#1#2% @@ -1159,11 +1276,12 @@ 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}} -\protected\long\def\ekvd@t@nmeta#1#2% +\protected\def\ekvd@t@meta{\ekvd@type@meta{}\ekvlet{##1}\ekvd@add@val{{##1}}{}} +\protected\def\ekvd@t@nmeta {% - \ekvd@assert@not@long{nmeta #1}% - \ekvd@type@meta n\ekvletNoVal{}{#1}{#2}% + \ekvd@assert@not@long + \ekvd@type@meta + n\ekvletNoVal{}\ekvd@add@noval{}\ekvd@assert@not@long@also } % \end{macrocode} % \end{macro} @@ -1174,19 +1292,23 @@ 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% +\protected\long\def\ekvd@type@smeta#1#2#3#4#5#6#7#8% {% - \ekvd@assert@twoargs{s#1meta #4}{#5}% + \ekvd@assert@twoargs{#8}% {% - \ekvd@type@meta@a#5{#3}% - #2\ekvd@set{#4}\ekvd@tmp + \ekvd@type@meta@a#8{#3}% + \ekvd@ifalso + {\ekvd@exp@Nno#4{#7}{\ekvd@tmp#5}{#6}}% + {#2\ekvd@set{#7}\ekvd@tmp}% }% } -\protected\def\ekvd@t@smeta{\ekvd@type@smeta{}\ekvlet{##1}} -\protected\long\def\ekvd@t@snmeta#1#2% +\protected\def\ekvd@t@smeta + {\ekvd@type@smeta{}\ekvlet{##1}\ekvd@add@val{{##1}}{}} +\protected\def\ekvd@t@snmeta {% - \ekvd@assert@not@long{snmeta #1}% - \ekvd@type@smeta n\ekvletNoVal{}{#1}{#2}% + \ekvd@assert@not@long + \ekvd@type@smeta + n\ekvletNoVal{}\ekvd@add@noval{}\ekvd@assert@not@long@also } % \end{macrocode} % \end{macro} @@ -1206,12 +1328,16 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@type@choice#1#2% {% - \ekvd@assert@not@long{#1 #2}% + \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp##1% {% \unexpanded{\ekvd@h@choice}{\ekvd@choice@name\ekvd@set{#2}{##1}}% }% - \ekvlet\ekvd@set{#2}\ekvd@tmp + \ekvd@ifalso + {% + \ekvd@exp@Nno\ekvd@add@val{#2}{\ekvd@tmp{##1}}\ekvd@assert@not@long@also + }% + {\ekvlet\ekvd@set{#2}\ekvd@tmp}% } % \end{macrocode} % |\ekvd@populate@choice| just uses |\ekvparse| and then gives control to @@ -1224,7 +1350,7 @@ and the derived files expkv-def.pdf } \protected\long\def\ekvd@populate@choice@noarg#1% {% - \expandafter\ekvd@err@missing@definition\expandafter{\ekvd@set@choice : #1}% + \expandafter\ekvd@err@missing@definition@msg\expandafter{\ekvd@cur : #1}% } % \end{macrocode} % |\ekvd@populate@choice@| runs the prefix-test, if there is none we can @@ -1236,7 +1362,7 @@ and the derived files expkv-def.pdf \protected\long\def\ekvd@populate@choice@#1#2% {% \ekvd@clear@prefixes - \expandafter\ekvd@assert@arg\expandafter{\ekvd@set@choice : #1}{#2}% + \expandafter\ekvd@assert@arg@msg\expandafter{\ekvd@cur : #1}{#2}% {% \ekvd@ifspace{#1}% {\ekvd@choice@prefix\ekv@mark#1\ekv@stop}% @@ -1269,23 +1395,24 @@ and the derived files expkv-def.pdf } \protected\def\ekvd@choice@p@protected{\let\ekvd@prot\protected} \let\ekvd@choice@p@protect\ekvd@choice@p@protected -\protected\def\ekvd@choice@p@long\ekvd@ifspace#1% +\protected\def\ekvd@choice@invalid@p#1\ekvd@ifspace#2% {% - \expandafter\ekvd@choice@p@long@\expandafter{\ekv@gobble@mark#1}% - \ekvd@ifspace{#1}% + \expandafter\ekvd@choice@invalid@p@\expandafter{\ekv@gobble@mark#2}{#1}% + \ekvd@ifspace{#2}% } -\protected\def\ekvd@choice@p@long@#1% +\protected\def\ekvd@choice@invalid@p@#1#2% {% - \expandafter\ekvd@err@no@long\expandafter - {\ekvd@set@choice : long #1}% + \expandafter\ekvd@err@no@prefix@msg\expandafter{\ekvd@cur : #2 #1}{#2}% } +\protected\def\ekvd@choice@p@long{\ekvd@choice@invalid@p{long}}% +\protected\def\ekvd@choice@p@also{\ekvd@choice@invalid@p{also}}% % \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{choice #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvd@type@choice{choice}{#1}% \def\ekvd@set@choice{#1}% @@ -1299,9 +1426,10 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\long\expandafter\def\csname ekvd@t@unknown-choice\endcsname#1#2% {% - \ekvd@assert@arg{unknown-choice #1}{#2}% + \ekvd@assert@arg{#2}% {% - \ekvd@assert@not@long{unknown-choice #1}% + \ekvd@assert@not@long + \ekvd@assert@not@also \ekvd@prot\expandafter \def\csname\ekvd@unknown@choice@name\ekvd@set{#1}\endcsname##1{#2}% }% @@ -1336,6 +1464,93 @@ and the derived files expkv-def.pdf % \end{macrocode} % \end{macro} % +% +% \subsubsection{Handling \texttt{also}} +% +% \begin{macro}[internal] +% {\ekvd@add@val,\ekvd@add@noval,\ekvd@add@aux,\ekvd@add@aux@} +% \begin{macrocode} +\protected\long\def\ekvd@add@val#1#2#3% + {% + \ekvd@assert@val{#1}% + {% + \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}% + {#1}{#2}{\ekvd@long\ekvdef}{#3}% + }% + } +\protected\long\def\ekvd@add@noval#1#2#3% + {% + \ekvd@assert@noval{#1}% + {% + \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}N\endcsname{}% + {#1}{#2}\ekvdefNoVal{#3}% + }% + } +\protected\long\def\ekvd@add@aux#1#2% + {% + \ekvd@extract@prefixes#1% + \expandafter\ekvd@add@aux@\expandafter{#1#2}% + } +\protected\long\def\ekvd@add@aux@#1#2#3#4#5% + {% + #5% + \ekvd@prot#4\ekvd@set{#2}{#1#3}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% { +% \ekvd@extract@prefixes,\ekvd@extract@prefixes@, +% \ekvd@extract@prefixes@long,\ekvd@extract@prefixes@prot +% } +% This macro checks which prefixes were used for the definition of a macro and +% sets |\ekvd@long| and |\ekvd@prot| accordingly. +% \begin{macrocode} +\protected\def\ekvd@extract@prefixes#1% + {% + \expandafter\ekvd@extract@prefixes@\meaning#1\ekvd@stop + } +% \end{macrocode} +% In the following definition |#1| will get replaced by |macro:|, |#2| by +% |\long| and |#3| by |\protected| (in each, all tokens will have category +% other). This allows us to parse the |\meaning| of a macro for those strings. +% \begin{macrocode} +\protected\def\ekvd@extract@prefixes@#1#2#3% + {% + \protected\def\ekvd@extract@prefixes@##1#1##2\ekvd@stop + {% + \ekvd@extract@prefixes@long + ##1\ekvd@mark\@firstofone#2\ekvd@mark\@gobble\ekvd@stop + {\let\ekvd@long\long}% + \ekvd@extract@prefixes@prot + ##1\ekvd@mark\@firstofone#3\ekvd@mark\@gobble\ekvd@stop + {\let\ekvd@prot\protected}% + }% + \protected\def\ekvd@extract@prefixes@long##1#2##2\ekvd@mark##3##4\ekvd@stop + {##3}% + \protected\def\ekvd@extract@prefixes@prot##1#3##2\ekvd@mark##3##4\ekvd@stop + {##3}% + } +% \end{macrocode} +% We use a temporary macro to expand the three arguments of +% |\ekvd@extract@prefixes@|, which will set up the real meaning of itself and +% the parsing for |\long| and |\protected|. +% \begin{macrocode} +\begingroup +\edef\ekvd@tmp + {% + \endgroup + \ekvd@extract@prefixes@ + {\detokenize{macro:}}% + {\string\long}% + {\string\protected}% + } +\ekvd@tmp +% \end{macrocode} +% \end{macro} +% +% % \subsubsection{Tests} % % \begin{macro}[internal]{\ekvd@newlet,\ekvd@newreg} @@ -1344,11 +1559,11 @@ and the derived files expkv-def.pdf % \begin{macrocode} \protected\def\ekvd@newlet#1#2% {% - \unless\ifdefined#1\let#1#2\fi + \ifdefined#1\ekv@fi@gobble\fi\@firstofone{\let#1#2}% } \protected\def\ekvd@newreg#1#2% {% - \unless\ifdefined#1\csname new#2\endcsname#1\fi + \ifdefined#1\ekv@fi@gobble\fi\@firstofone{\csname new#2\endcsname#1}% } % \end{macrocode} % \end{macro} @@ -1360,10 +1575,9 @@ and the derived files expkv-def.pdf % only macros will be gobbled that are needed for the true branch, which doesn't % hurt, and if there are more this will not be empty. % \begin{macrocode} -\long\def\ekvd@assert@twoargs#1#2% +\long\def\ekvd@assert@twoargs#1% {% - \ekvd@ifnottwoargs{#2}% - {\ekvd@err@missing@definition{#1}}% + \ekvd@ifnottwoargs{#1}{\ekvd@err@missing@definition}% } \long\def\ekvd@ifnottwoargs#1% {% @@ -1375,15 +1589,74 @@ and the derived files expkv-def.pdf % \end{macro} % % \begin{macro}[internal] -% {\ekvd@assert@arg,\ekvd@ifnoarg,\ekvd@ifnoarg@,\ekvd@ifnoarg@} +% { +% \ekvd@assert@val,\ekvd@assert@val@,\ekvd@assert@noval,\ekvd@assert@noval@, +% \ekvd@extract@args,\ekvd@extracted@args,\ekvd@one@arg@string +% } +% Assert that a given key is defined as a value taking key or a |NoVal| key with +% the correct argument structure, respectively. +% \begin{macrocode} +\protected\def\ekvd@assert@val#1% + {% + \ekvifdefined\ekvd@set{#1}% + {\expandafter\ekvd@assert@val@\csname\ekv@name\ekvd@set{#1}\endcsname}% + {% + \ekvifdefinedNoVal\ekvd@set{#1}% + \ekvd@err@add@val@on@noval + {\ekvd@err@undefined@key{#1}}% + \@gobble + }% + } +\protected\def\ekvd@assert@val@#1% + {% + \expandafter\ekvd@extract@args\meaning#1\ekvd@stop + \unless\ifx\ekvd@extracted@args\ekvd@one@arg@string + \ekvd@err@unsupported@arg + \fi + \@firstofone + }% +\protected\def\ekvd@assert@noval#1% + {% + \ekvifdefinedNoVal\ekvd@set{#1}% + {\expandafter\ekvd@assert@noval@\csname\ekv@name\ekvd@set{#1}N\endcsname}% + {% + \ekvifdefined\ekvd@set{#1}% + \ekvd@err@add@noval@on@val + {\ekvd@err@undefined@key{#1}}% + \@gobble + }% + } +\protected\def\ekvd@assert@noval@#1% + {% + \expandafter\ekvd@extract@args\meaning#1\ekvd@stop + \unless\ifx\ekvd@extracted@args\ekvd@empty + \ekvd@err@unsupported@arg + \fi + \@firstofone + } +\protected\def\ekvd@extract@args#1% + {% + \protected\def\ekvd@extract@args##1#1##2->##3\ekvd@stop + {\def\ekvd@extracted@args{##2}}% + } +\expandafter\ekvd@extract@args\expandafter{\detokenize{macro:}} +\edef\ekvd@one@arg@string{\string#1} +% \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{macrocode} -\long\def\ekvd@assert@arg#1#2% +\long\def\ekvd@assert@arg#1{\ekvd@ifnoarg{#1}\ekvd@err@missing@definition} +\long\def\ekvd@assert@arg@msg#1#2% {% - \ekvd@ifnoarg{#2}% - {\ekvd@err@missing@definition{#1}}% + \ekvd@ifnoarg{#2}{\ekvd@err@missing@definition@msg{#1}}% } \long\def\ekvd@ifnoarg#1% {% @@ -1401,10 +1674,9 @@ and the derived files expkv-def.pdf % % \begin{macro}[internal]{\ekvd@assert@filledarg,\ekvd@ifnoarg@or@empty} % \begin{macrocode} -\long\def\ekvd@assert@filledarg#1#2% +\long\def\ekvd@assert@filledarg#1% {% - \ekvd@ifnoarg@or@empty{#2}% - {\ekvd@err@missing@definition{#1}}% + \ekvd@ifnoarg@or@empty{#1}\ekvd@err@missing@definition } \long\def\ekvd@ifnoarg@or@empty#1% {% @@ -1415,18 +1687,29 @@ and the derived files expkv-def.pdf % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\ekvd@assert@not@long,\ekvd@assert@not@protected} -% Some key-types don't want to be |\long| or |\protected|, so we provide macros -% to test this and throw an error, this could be silently ignored but now users -% will learn to not use unnecessary stuff which slows the compilation down. +% \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 +% } +% 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 +% users will learn to not use unnecessary stuff which slows the compilation +% down. % \begin{macrocode} -\long\def\ekvd@assert@not@long#1% +\def\ekvd@assert@not@long{\ifx\ekvd@long\long\ekvd@err@no@prefix{long}\fi} +\def\ekvd@assert@not@protected {% - \ifx\ekvd@long\long\ekvd@err@no@long{#1}\fi + \ifx\ekvd@prot\protected\ekvd@err@no@prefix{protected}\fi } -\long\def\ekvd@assert@not@protected#1% +\def\ekvd@assert@not@also{\ekvd@ifalso{\ekvd@err@no@prefix{also}}{}} +\def\ekvd@assert@not@long@also {% - \ifx\ekvd@prot\protected\ekvd@err@no@protected{#1}\fi + \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 } % \end{macrocode} % \end{macro} @@ -1454,29 +1737,49 @@ and the derived files expkv-def.pdf % % \begin{macro}[internal] % { -% \ekvd@err@missing@definition,\ekvd@err@missing@prefix, -% \ekvd@err@undefined@prefix,\ekvd@err@undefined@key,\ekvd@err@no@protected, -% \ekvd@err@no@long +% \ekvd@errm,\ekvd@err@missing@definition,\ekvd@err@missing@definition@msg, +% \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 % } % The non-expandable error messages are boring, so here they are: % \begin{macrocode} -\protected\def\ekvd@err@missing@definition#1% - {\errmessage{expkv-def Error: Missing definition for key `\unexpanded{#1}'}} -\protected\def\ekvd@err@missing@prefix#1% - {\errmessage{expkv-def Error: Missing prefix for key `\unexpanded{#1}'}} +\protected\def\ekvd@errm#1{\errmessage{expkv-def Error: #1}} +\protected\def\ekvd@err@missing@definition + {\ekvd@errm{Missing definition for key `\ekvd@cur'}} +\protected\def\ekvd@err@missing@definition@msg#1% + {\ekvd@errm{Missing definition for key `\unexpanded{#1}'}} +\protected\def\ekvd@err@missing@type + {\ekvd@errm{Missing type prefix for key `\ekvd@cur'}} \protected\def\ekvd@err@undefined@prefix#1% - {\errmessage{expkv-def Error: Undefined prefix `\unexpanded{#1}'}} -\protected\def\ekvd@err@undefined@key#1% - {\errmessage{expkv-def Error: Undefined key `\unexpanded{#1}'}} -\protected\def\ekvd@err@no@protected#1% {% - \errmessage - {expkv-def Error: prefix `protected' not accepted for `\unexpanded{#1}'}% + \ekvd@errm + {Undefined prefix `\unexpanded{#1}' found while processing `\ekvd@cur'}% } -\protected\def\ekvd@err@no@long#1% +\protected\def\ekvd@err@undefined@key#1% + {% + \ekvd@errm + {Undefined key `\unexpanded{#1}' found while processing `\ekvd@cur'}% + } +\protected\def\ekvd@err@no@prefix#1% + {\ekvd@errm{prefix `#1' not accepted in `\ekvd@cur'}} +\protected\def\ekvd@err@no@prefix@msg#1#2% + {\ekvd@errm{prefix `#2' not accepted in `\unexpanded{#1}'}} +\protected\def\ekvd@err@no@prefix@also#1% + {\ekvd@errm{`\ekvd@cur' not allowed with a `#1' key}} +\protected\def\ekvd@err@add@val@on@noval + {\ekvd@errm{`\ekvd@cur' not allowed with a NoVal key}} +\protected\def\ekvd@err@add@noval@on@val + {\ekvd@errm{`\ekvd@cur' not allowed with a value taking key}} +\protected\def\ekvd@err@unsupported@arg\fi\@firstofone#1% {% - \errmessage - {expkv-def Error: prefix `long' not accepted for `\unexpanded{#1}'}% + \fi + \ekvd@errm + {% + Existing key-macro has the unsupported argument string + `\ekvd@extracted@args' for key `\ekvd@cur'% + }% } % \end{macrocode} % \end{macro} diff --git a/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex b/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex index d0f61214e56..9d504637338 100644 --- a/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex +++ b/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex @@ -35,8 +35,8 @@ \else \expandafter\endinput \fi -\def\ekvdVersion{0.4} -\def\ekvdDate{2020-07-04} +\def\ekvdVersion{0.5} +\def\ekvdDate{2020-07-12} \csname ekvd@tmp\endcsname \expandafter\chardef\csname ekvd@tmp\endcsname=\catcode`\@ \catcode`\@=11 @@ -45,8 +45,14 @@ {% \let\ekvd@long\ekvd@empty \let\ekvd@prot\ekvd@empty + \let\ekvd@ifalso\@secondoftwo } \ekvd@clear@prefixes +\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}} \protected\def\ekvdefinekeys#1% {% \def\ekvd@set{#1}% @@ -56,9 +62,10 @@ \protected\long\def\ekvd@#1#2% {% \ekvd@clear@prefixes + \edef\ekvd@cur{\detokenize{#1}}% \ekvd@ifspace{#1}% {\ekvd@prefix\ekv@mark#1\ekv@stop{#2}}% - {\ekvd@err@missing@prefix{#1}}% + \ekvd@err@missing@type } \protected\def\ekvd@prefix#1 {\ekv@strip{#1}\ekvd@prefix@\ekv@mark} \protected\def\ekvd@prefix@#1#2\ekv@stop @@ -67,7 +74,7 @@ {\ekv@strip{#2}{\csname ekvd@t@#1\endcsname}}% {% \ekv@ifdefined{ekvd@p@#1}% - {\csname ekvd@p@#1\endcsname{#2}}% + {\csname ekvd@p@#1\endcsname\ekvd@prefix@after@p{#2}}% {\ekvd@err@undefined@prefix{#1}\@gobble}% }% } @@ -75,60 +82,73 @@ {% \ekvd@ifspace{#1}% {\ekvd@prefix#1\ekv@stop}% - {% - \expandafter\ekvd@err@missing@prefix\expandafter{\ekv@gobble@mark#1}% - \@gobble - }% + {\ekvd@err@missing@type\@gobble}% } -\protected\def\ekvd@p@long{\let\ekvd@long\long\ekvd@prefix@after@p} -\protected\def\ekvd@p@protected{\let\ekvd@prot\protected\ekvd@prefix@after@p} +\protected\def\ekvd@p@long{\let\ekvd@long\long} +\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@t@set#1#2% {% - \ekvd@assert@not@long{set #1}% - \ekvd@assert@not@protected{set #1}% - \ekvd@ifnoarg{#2}% - {\ekvdefNoVal\ekvd@set{#1}{\ekvchangeset{#1}}}% + \ekvd@assert@not@long + \ekvd@assert@not@protected + \ekv@ifempty{#2}% + {\ekvd@err@missing@definition}% {% - \ekv@ifempty{#2}% - {\ekvd@err@missing@definition{set #1}}% - {\ekvdefNoVal\ekvd@set{#1}{\ekvchangeset{#2}}}% + \ekvd@ifalso + {% + \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}}}% + }% }% } \protected\long\def\ekvd@type@noval#1#2#3#4% {% - \ekvd@assert@arg{#1noval #3}{#4}% + \ekvd@assert@arg{#4}% {% - \ekvd@assert@not@long{#1noval #3}% + \ekvd@assert@not@long \ekvd@prot#2\ekvd@tmp{#4}% - \ekvletNoVal\ekvd@set{#3}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@noval{#3}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}% }% } \protected\def\ekvd@t@noval{\ekvd@type@noval{}\def} \protected\def\ekvd@t@enoval{\ekvd@type@noval e\edef} \protected\long\def\ekvd@type@code#1#2#3#4% {% - \ekvd@assert@arg{#1code #3}{#4} + \ekvd@assert@arg{#4} {% \ekvd@prot\ekvd@long#2\ekvd@tmp##1{#4}% - \ekvlet\ekvd@set{#3}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@val{#3}{\ekvd@tmp{##1}}{}}% + {\ekvlet\ekvd@set{#3}\ekvd@tmp}% }% } \protected\def\ekvd@t@code{\ekvd@type@code{}\def} \protected\def\ekvd@t@ecode{\ekvd@type@code e\edef} \protected\long\def\ekvd@type@default#1#2#3#4% {% - \ekvd@assert@arg{#1default #3}{#4}% + \ekvd@assert@arg{#4}% {% \ekvifdefined\ekvd@set{#3}% {% - \ekvd@assert@not@long{#1default #3}% + \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp {% \unexpanded\expandafter#2% {\csname\ekv@name\ekvd@set{#3}\endcsname{#4}}% }% - \ekvletNoVal\ekvd@set{#3}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@noval{#3}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}% }% {\ekvd@err@undefined@key{#3}}% }% @@ -137,26 +157,29 @@ \protected\def\ekvd@t@qdefault{\ekvd@type@default q{\expandafter\expandafter}} \protected\long\def\ekvd@t@edefault#1#2% {% - \ekvd@assert@arg{edefault #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{edefault #1}% + \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp {\csname\ekv@name\ekvd@set{#1}\endcsname{#2}}% - \ekvletNoVal\ekvd@set{#1}\ekvd@tmp + \ekvd@ifalso + {\ekvd@exp@Nno\ekvd@add@noval{#1}\ekvd@tmp{}}% + {\ekvletNoVal\ekvd@set{#1}\ekvd@tmp}% }% {\ekvd@err@undefined@key{#1}}% }% } \long\def\ekvd@t@initial#1#2% {% - \ekvd@assert@arg{initial #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{initial #1}% - \ekvd@assert@not@protected{initial #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}}% @@ -164,12 +187,13 @@ } \long\def\ekvd@t@oinitial#1#2% {% - \ekvd@assert@arg{oinitial #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{oinitial #1}% - \ekvd@assert@not@protected{oinitial #1}% + \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}}% @@ -177,12 +201,13 @@ } \long\def\ekvd@t@einitial#1#2% {% - \ekvd@assert@arg{einitial #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvifdefined\ekvd@set{#1}% {% - \ekvd@assert@not@long{einitial #1}% - \ekvd@assert@not@protected{einitial #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 {\ekvd@tmp}% @@ -192,7 +217,7 @@ } \protected\def\ekvd@type@bool#1#2#3#4#5#6#7% {% - \ekvd@assert@filledarg{#1bool#2 #6}{#7}% + \ekvd@assert@filledarg{#7}% {% \ekvd@newlet#7#5% \ekvd@type@choice{#1bool#2}{#6}% @@ -210,59 +235,95 @@ \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@type@data#1#2#3#4#5#6#7% +\protected\def\ekvd@type@data#1#2#3#4#5#6#7#8% {% - \ekvd@assert@filledarg{#1data#2 #6}{#7}% + \ekvd@assert@filledarg{#8}% {% - \ekvd@newlet#7#3% - \protected\ekvd@long\ekvdef\ekvd@set{#6}{\long#4#7####1#5{####1{##1}}}% + \ekvd@newlet#8#3% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#7}{\long#4#8####1#5{####1{#6}}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#7}% + {\long#4#8####1#5{####1{#6}}}% + }% }% } -\protected\def\ekvd@t@data{\ekvd@type@data{}{}\@secondoftwo\def{####2}} -\protected\def\ekvd@t@edata{\ekvd@type@data e{}\@secondoftwo\edef{####2}} -\protected\def\ekvd@t@gdata{\ekvd@type@data g{}\@secondoftwo\gdef{####2}} -\protected\def\ekvd@t@xdata{\ekvd@type@data x{}\@secondoftwo\xdef{####2}} -\protected\def\ekvd@t@dataT{\ekvd@type@data{}T\@gobble\def{}} -\protected\def\ekvd@t@edataT{\ekvd@type@data eT\@gobble\edef{}} -\protected\def\ekvd@t@gdataT{\ekvd@type@data gT\@gobble\gdef{}} -\protected\def\ekvd@t@xdataT{\ekvd@type@data xT\@gobble\xdef{}} +\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}} +\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}} \protected\def\ekvd@type@box#1#2#3#4% {% - \ekvd@assert@filledarg{#1box #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newreg#4{box}% - \protected\ekvd@long\ekvdef\ekvd@set{#3}% - {#2\setbox#4\hbox{\begingroup##1\endgroup}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2\setbox#4\hbox{\begingroup##1\endgroup}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#3}% + {#2\setbox#4\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@type@toks#1#2#3#4% {% - \ekvd@assert@filledarg{#1toks #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newreg#4{toks}% - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2#4{##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@type@apptoks#1#2#3#4% {% - \ekvd@assert@filledarg{#1apptoks #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newreg#4{toks}% - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4\expandafter{\the#4##1}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2#4\expandafter{\the#4##1}}{}% + }% + {% + \protected\ekvd@long\ekvdef\ekvd@set{#3}% + {#2#4\expandafter{\the#4##1}}% + }% }% } \protected\def\ekvd@t@apptoks{\ekvd@type@apptoks{}{}} \protected\def\ekvd@t@gapptoks{\ekvd@type@apptoks{g}\global} \protected\def\ekvd@type@reg#1#2#3#4#5#6#7% {% - \ekvd@assert@filledarg{#1 #6}{#7}% + \ekvd@assert@filledarg{#7}% {% \ekvd@newreg#7{#2}% - \protected\ekvd@long\ekvdef\ekvd@set{#6}{#3#7=#4##1#5\relax}% + \ekvd@ifalso + {% + \let\evkd@prot\protected + \ekvd@add@val{#6}{#3#7=#4##1#5\relax}{}% + }% + {\protected\ekvd@long\ekvdef\ekvd@set{#6}{#3#7=#4##1#5\relax}}% }% } \protected\def\ekvd@t@int{\ekvd@type@reg{int}{count}{}{}{}} @@ -279,31 +340,43 @@ \protected\def\ekvd@t@xskip{\ekvd@type@reg{xskip}{skip}\global\glueexpr\relax} \protected\def\ekvd@type@store#1#2#3#4% {% - \ekvd@assert@filledarg{#1store #3}{#4}% + \ekvd@assert@filledarg{#4}% {% - \unless\ifdefined#4\let#4\ekvd@empty\fi - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{\unexpanded{##1}}}% + \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} \protected\def\ekvd@type@estore#1#2#3#4% {% - \ekvd@assert@filledarg{#1store #3}{#4}% + \ekvd@assert@filledarg{#4}% {% \ekvd@newlet#4\ekvd@empty - \protected\ekvd@long\ekvdef\ekvd@set{#3}{#2#4{##1}}% + \ekvd@ifalso + {% + \let\ekvd@prot\protected + \ekvd@add@val{#3}{#2#4{##1}}{}% + }% + {\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\long\def\ekvd@type@meta#1#2#3#4#5% +\protected\long\def\ekvd@type@meta#1#2#3#4#5#6#7#8% {% - \ekvd@assert@filledarg{#1meta #4}{#5}% + \ekvd@assert@filledarg{#8}% {% \edef\ekvd@tmp{\ekvd@set}% - \expandafter\ekvd@type@meta@a\expandafter{\ekvd@tmp}{#5}{#3}% - #2\ekvd@set{#4}\ekvd@tmp + \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}% }% } \protected\long\def\ekvd@type@meta@a#1#2% @@ -318,34 +391,43 @@ {% \ekvd@prot\ekvd@long\def\ekvd@tmp#2{#1}% } -\protected\def\ekvd@t@meta{\ekvd@type@meta{}\ekvlet{##1}} -\protected\long\def\ekvd@t@nmeta#1#2% +\protected\def\ekvd@t@meta{\ekvd@type@meta{}\ekvlet{##1}\ekvd@add@val{{##1}}{}} +\protected\def\ekvd@t@nmeta {% - \ekvd@assert@not@long{nmeta #1}% - \ekvd@type@meta n\ekvletNoVal{}{#1}{#2}% + \ekvd@assert@not@long + \ekvd@type@meta + n\ekvletNoVal{}\ekvd@add@noval{}\ekvd@assert@not@long@also } -\protected\long\def\ekvd@type@smeta#1#2#3#4#5% +\protected\long\def\ekvd@type@smeta#1#2#3#4#5#6#7#8% {% - \ekvd@assert@twoargs{s#1meta #4}{#5}% + \ekvd@assert@twoargs{#8}% {% - \ekvd@type@meta@a#5{#3}% - #2\ekvd@set{#4}\ekvd@tmp + \ekvd@type@meta@a#8{#3}% + \ekvd@ifalso + {\ekvd@exp@Nno#4{#7}{\ekvd@tmp#5}{#6}}% + {#2\ekvd@set{#7}\ekvd@tmp}% }% } -\protected\def\ekvd@t@smeta{\ekvd@type@smeta{}\ekvlet{##1}} -\protected\long\def\ekvd@t@snmeta#1#2% +\protected\def\ekvd@t@smeta + {\ekvd@type@smeta{}\ekvlet{##1}\ekvd@add@val{{##1}}{}} +\protected\def\ekvd@t@snmeta {% - \ekvd@assert@not@long{snmeta #1}% - \ekvd@type@smeta n\ekvletNoVal{}{#1}{#2}% + \ekvd@assert@not@long + \ekvd@type@smeta + n\ekvletNoVal{}\ekvd@add@noval{}\ekvd@assert@not@long@also } \protected\def\ekvd@type@choice#1#2% {% - \ekvd@assert@not@long{#1 #2}% + \ekvd@assert@not@long \ekvd@prot\edef\ekvd@tmp##1% {% \unexpanded{\ekvd@h@choice}{\ekvd@choice@name\ekvd@set{#2}{##1}}% }% - \ekvlet\ekvd@set{#2}\ekvd@tmp + \ekvd@ifalso + {% + \ekvd@exp@Nno\ekvd@add@val{#2}{\ekvd@tmp{##1}}\ekvd@assert@not@long@also + }% + {\ekvlet\ekvd@set{#2}\ekvd@tmp}% } \protected\def\ekvd@populate@choice {% @@ -353,12 +435,12 @@ } \protected\long\def\ekvd@populate@choice@noarg#1% {% - \expandafter\ekvd@err@missing@definition\expandafter{\ekvd@set@choice : #1}% + \expandafter\ekvd@err@missing@definition@msg\expandafter{\ekvd@cur : #1}% } \protected\long\def\ekvd@populate@choice@#1#2% {% \ekvd@clear@prefixes - \expandafter\ekvd@assert@arg\expandafter{\ekvd@set@choice : #1}{#2}% + \expandafter\ekvd@assert@arg@msg\expandafter{\ekvd@cur : #1}{#2}% {% \ekvd@ifspace{#1}% {\ekvd@choice@prefix\ekv@mark#1\ekv@stop}% @@ -391,19 +473,20 @@ } \protected\def\ekvd@choice@p@protected{\let\ekvd@prot\protected} \let\ekvd@choice@p@protect\ekvd@choice@p@protected -\protected\def\ekvd@choice@p@long\ekvd@ifspace#1% +\protected\def\ekvd@choice@invalid@p#1\ekvd@ifspace#2% {% - \expandafter\ekvd@choice@p@long@\expandafter{\ekv@gobble@mark#1}% - \ekvd@ifspace{#1}% + \expandafter\ekvd@choice@invalid@p@\expandafter{\ekv@gobble@mark#2}{#1}% + \ekvd@ifspace{#2}% } -\protected\def\ekvd@choice@p@long@#1% +\protected\def\ekvd@choice@invalid@p@#1#2% {% - \expandafter\ekvd@err@no@long\expandafter - {\ekvd@set@choice : long #1}% + \expandafter\ekvd@err@no@prefix@msg\expandafter{\ekvd@cur : #2 #1}{#2}% } +\protected\def\ekvd@choice@p@long{\ekvd@choice@invalid@p{long}}% +\protected\def\ekvd@choice@p@also{\ekvd@choice@invalid@p{also}}% \protected\long\def\ekvd@t@choice#1#2% {% - \ekvd@assert@arg{choice #1}{#2}% + \ekvd@assert@arg{#2}% {% \ekvd@type@choice{choice}{#1}% \def\ekvd@set@choice{#1}% @@ -412,9 +495,10 @@ } \protected\long\expandafter\def\csname ekvd@t@unknown-choice\endcsname#1#2% {% - \ekvd@assert@arg{unknown-choice #1}{#2}% + \ekvd@assert@arg{#2}% {% - \ekvd@assert@not@long{unknown-choice #1}% + \ekvd@assert@not@long + \ekvd@assert@not@also \ekvd@prot\expandafter \def\csname\ekvd@unknown@choice@name\ekvd@set{#1}\endcsname##1{#2}% }% @@ -433,18 +517,73 @@ \fi #1% } +\protected\long\def\ekvd@add@val#1#2#3% + {% + \ekvd@assert@val{#1}% + {% + \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}% + {#1}{#2}{\ekvd@long\ekvdef}{#3}% + }% + } +\protected\long\def\ekvd@add@noval#1#2#3% + {% + \ekvd@assert@noval{#1}% + {% + \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}N\endcsname{}% + {#1}{#2}\ekvdefNoVal{#3}% + }% + } +\protected\long\def\ekvd@add@aux#1#2% + {% + \ekvd@extract@prefixes#1% + \expandafter\ekvd@add@aux@\expandafter{#1#2}% + } +\protected\long\def\ekvd@add@aux@#1#2#3#4#5% + {% + #5% + \ekvd@prot#4\ekvd@set{#2}{#1#3}% + } +\protected\def\ekvd@extract@prefixes#1% + {% + \expandafter\ekvd@extract@prefixes@\meaning#1\ekvd@stop + } +\protected\def\ekvd@extract@prefixes@#1#2#3% + {% + \protected\def\ekvd@extract@prefixes@##1#1##2\ekvd@stop + {% + \ekvd@extract@prefixes@long + ##1\ekvd@mark\@firstofone#2\ekvd@mark\@gobble\ekvd@stop + {\let\ekvd@long\long}% + \ekvd@extract@prefixes@prot + ##1\ekvd@mark\@firstofone#3\ekvd@mark\@gobble\ekvd@stop + {\let\ekvd@prot\protected}% + }% + \protected\def\ekvd@extract@prefixes@long##1#2##2\ekvd@mark##3##4\ekvd@stop + {##3}% + \protected\def\ekvd@extract@prefixes@prot##1#3##2\ekvd@mark##3##4\ekvd@stop + {##3}% + } +\begingroup +\edef\ekvd@tmp + {% + \endgroup + \ekvd@extract@prefixes@ + {\detokenize{macro:}}% + {\string\long}% + {\string\protected}% + } +\ekvd@tmp \protected\def\ekvd@newlet#1#2% {% - \unless\ifdefined#1\let#1#2\fi + \ifdefined#1\ekv@fi@gobble\fi\@firstofone{\let#1#2}% } \protected\def\ekvd@newreg#1#2% {% - \unless\ifdefined#1\csname new#2\endcsname#1\fi + \ifdefined#1\ekv@fi@gobble\fi\@firstofone{\csname new#2\endcsname#1}% } -\long\def\ekvd@assert@twoargs#1#2% +\long\def\ekvd@assert@twoargs#1% {% - \ekvd@ifnottwoargs{#2}% - {\ekvd@err@missing@definition{#1}}% + \ekvd@ifnottwoargs{#1}{\ekvd@err@missing@definition}% } \long\def\ekvd@ifnottwoargs#1% {% @@ -452,10 +591,55 @@ \ekv@ifempty@false\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo } \long\def\ekvd@ifempty@gtwo#1#2{\ekv@ifempty@\ekv@ifempty@A} -\long\def\ekvd@assert@arg#1#2% +\protected\def\ekvd@assert@val#1% {% - \ekvd@ifnoarg{#2}% - {\ekvd@err@missing@definition{#1}}% + \ekvifdefined\ekvd@set{#1}% + {\expandafter\ekvd@assert@val@\csname\ekv@name\ekvd@set{#1}\endcsname}% + {% + \ekvifdefinedNoVal\ekvd@set{#1}% + \ekvd@err@add@val@on@noval + {\ekvd@err@undefined@key{#1}}% + \@gobble + }% + } +\protected\def\ekvd@assert@val@#1% + {% + \expandafter\ekvd@extract@args\meaning#1\ekvd@stop + \unless\ifx\ekvd@extracted@args\ekvd@one@arg@string + \ekvd@err@unsupported@arg + \fi + \@firstofone + }% +\protected\def\ekvd@assert@noval#1% + {% + \ekvifdefinedNoVal\ekvd@set{#1}% + {\expandafter\ekvd@assert@noval@\csname\ekv@name\ekvd@set{#1}N\endcsname}% + {% + \ekvifdefined\ekvd@set{#1}% + \ekvd@err@add@noval@on@val + {\ekvd@err@undefined@key{#1}}% + \@gobble + }% + } +\protected\def\ekvd@assert@noval@#1% + {% + \expandafter\ekvd@extract@args\meaning#1\ekvd@stop + \unless\ifx\ekvd@extracted@args\ekvd@empty + \ekvd@err@unsupported@arg + \fi + \@firstofone + } +\protected\def\ekvd@extract@args#1% + {% + \protected\def\ekvd@extract@args##1#1##2->##3\ekvd@stop + {\def\ekvd@extracted@args{##2}}% + } +\expandafter\ekvd@extract@args\expandafter{\detokenize{macro:}} +\edef\ekvd@one@arg@string{\string#1} +\long\def\ekvd@assert@arg#1{\ekvd@ifnoarg{#1}\ekvd@err@missing@definition} +\long\def\ekvd@assert@arg@msg#1#2% + {% + \ekvd@ifnoarg{#2}{\ekvd@err@missing@definition@msg{#1}}% } \long\def\ekvd@ifnoarg#1% {% @@ -468,10 +652,9 @@ {% #1% } -\long\def\ekvd@assert@filledarg#1#2% +\long\def\ekvd@assert@filledarg#1% {% - \ekvd@ifnoarg@or@empty{#2}% - {\ekvd@err@missing@definition{#1}}% + \ekvd@ifnoarg@or@empty{#1}\ekvd@err@missing@definition } \long\def\ekvd@ifnoarg@or@empty#1% {% @@ -479,13 +662,19 @@ \@firstoftwo {\ekv@ifempty{#1}}% } -\long\def\ekvd@assert@not@long#1% +\def\ekvd@assert@not@long{\ifx\ekvd@long\long\ekvd@err@no@prefix{long}\fi} +\def\ekvd@assert@not@protected {% - \ifx\ekvd@long\long\ekvd@err@no@long{#1}\fi + \ifx\ekvd@prot\protected\ekvd@err@no@prefix{protected}\fi } -\long\def\ekvd@assert@not@protected#1% +\def\ekvd@assert@not@also{\ekvd@ifalso{\ekvd@err@no@prefix{also}}{}} +\def\ekvd@assert@not@long@also {% - \ifx\ekvd@prot\protected\ekvd@err@no@protected{#1}\fi + \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 } \long\def\ekvd@ifspace#1% {% @@ -496,23 +685,41 @@ {% \ekv@ifempty@\ekv@ifempty@A } -\protected\def\ekvd@err@missing@definition#1% - {\errmessage{expkv-def Error: Missing definition for key `\unexpanded{#1}'}} -\protected\def\ekvd@err@missing@prefix#1% - {\errmessage{expkv-def Error: Missing prefix for key `\unexpanded{#1}'}} +\protected\def\ekvd@errm#1{\errmessage{expkv-def Error: #1}} +\protected\def\ekvd@err@missing@definition + {\ekvd@errm{Missing definition for key `\ekvd@cur'}} +\protected\def\ekvd@err@missing@definition@msg#1% + {\ekvd@errm{Missing definition for key `\unexpanded{#1}'}} +\protected\def\ekvd@err@missing@type + {\ekvd@errm{Missing type prefix for key `\ekvd@cur'}} \protected\def\ekvd@err@undefined@prefix#1% - {\errmessage{expkv-def Error: Undefined prefix `\unexpanded{#1}'}} -\protected\def\ekvd@err@undefined@key#1% - {\errmessage{expkv-def Error: Undefined key `\unexpanded{#1}'}} -\protected\def\ekvd@err@no@protected#1% {% - \errmessage - {expkv-def Error: prefix `protected' not accepted for `\unexpanded{#1}'}% + \ekvd@errm + {Undefined prefix `\unexpanded{#1}' found while processing `\ekvd@cur'}% } -\protected\def\ekvd@err@no@long#1% +\protected\def\ekvd@err@undefined@key#1% + {% + \ekvd@errm + {Undefined key `\unexpanded{#1}' found while processing `\ekvd@cur'}% + } +\protected\def\ekvd@err@no@prefix#1% + {\ekvd@errm{prefix `#1' not accepted in `\ekvd@cur'}} +\protected\def\ekvd@err@no@prefix@msg#1#2% + {\ekvd@errm{prefix `#2' not accepted in `\unexpanded{#1}'}} +\protected\def\ekvd@err@no@prefix@also#1% + {\ekvd@errm{`\ekvd@cur' not allowed with a `#1' key}} +\protected\def\ekvd@err@add@val@on@noval + {\ekvd@errm{`\ekvd@cur' not allowed with a NoVal key}} +\protected\def\ekvd@err@add@noval@on@val + {\ekvd@errm{`\ekvd@cur' not allowed with a value taking key}} +\protected\def\ekvd@err@unsupported@arg\fi\@firstofone#1% {% - \errmessage - {expkv-def Error: prefix `long' not accepted for `\unexpanded{#1}'}% + \fi + \ekvd@errm + {% + Existing key-macro has the unsupported argument string + `\ekvd@extracted@args' for key `\ekvd@cur'% + }% } \def\ekvd@err@choice@invalid#1% {% |