texlive[55829] Master/texmf-dist: expkv-def (13jul20)

commits+karl at tug.org commits+karl at tug.org
Mon Jul 13 23:10:19 CEST 2020


Revision: 55829
          http://tug.org/svn/texlive?view=revision&revision=55829
Author:   karl
Date:     2020-07-13 23:10:18 +0200 (Mon, 13 Jul 2020)
Log Message:
-----------
expkv-def (13jul20)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/expkv-def/README.md
    trunk/Master/texmf-dist/doc/latex/expkv-def/expkv-def.pdf
    trunk/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx
    trunk/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex

Modified: trunk/Master/texmf-dist/doc/latex/expkv-def/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-def/README.md	2020-07-13 21:10:07 UTC (rev 55828)
+++ trunk/Master/texmf-dist/doc/latex/expkv-def/README.md	2020-07-13 21:10:18 UTC (rev 55829)
@@ -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

Modified: trunk/Master/texmf-dist/doc/latex/expkv-def/expkv-def.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx	2020-07-13 21:10:07 UTC (rev 55828)
+++ trunk/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx	2020-07-13 21:10:18 UTC (rev 55829)
@@ -152,14 +152,21 @@
 \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 @@
 \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 @@
 % 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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 %
 % \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 @@
 % \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 @@
 %     ,qdefault  keyK = text
 %     ,choice    keyL =
 %       {
-%         ,protected 1 = \texttt{a}
+%          protected 1 = \texttt{a}
 %         ,2 = b
 %         ,3 = c
 %         ,4 = d
@@ -556,7 +591,6 @@
 %       }
 %     ,edefault  keyL = 2
 %     ,meta      keyM = {keyA={#1},keyB=false}
-%     ,data
 %   }
 % \end{lstlisting}
 %
@@ -566,7 +600,7 @@
 % \begin{lstlisting}
 % \ekvdefinekeys{ex}
 %   {
-%     ,data  name  = \Pname
+%      data  name  = \Pname
 %     ,data  age   = \Page
 %     ,dataT hobby = \Phobby
 %   }
@@ -593,7 +627,7 @@
 % \begingroup
 % \ekvdefinekeys{ex}
 %   {
-%     ,data  name  = \Pname
+%      data  name  = \Pname
 %     ,data  age   = \Page
 %     ,dataT hobby = \Phobby
 %   }
@@ -684,8 +718,8 @@
 % \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,10 +741,12 @@
 % \expkvd\ was initialized.
 %
 % \begin{macro}[internal]
-%   {\ekvd at long,\ekvd at prot,\ekvd at clear@prefixes,\ekvd at empty}
-% \expkvd\ will use |\ekvd at long| and |\ekvd at 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 at long,\ekvd at prot,\ekvd at clear@prefixes,\ekvd at empty,\ekvd at ifalso}
+% \expkvd\ will use |\ekvd at long|, |\ekvd at prot|, and |\ekvd at 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 at empty{}
 \protected\def\ekvd at clear@prefixes
@@ -717,11 +753,24 @@
   {%
     \let\ekvd at long\ekvd at empty
     \let\ekvd at prot\ekvd at empty
+    \let\ekvd at ifalso\@secondoftwo
   }
 \ekvd at clear@prefixes
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}[internal]{\ekvd at exp@Nno,\ekvd at exp@reinsert at n}
+%   These are expansion helpers, similar to what \LaTeX3 uses, but simpler and
+%   for just a few cases
+%    \begin{macrocode}
+\long\def\ekvd at exp@Nno#1#2#3%
+  {%
+    \expandafter\ekvd at exp@reinsert at n\expandafter{#3}{#1{#2}}%
+  }
+\long\def\ekvd at exp@reinsert at 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 @@
 \protected\long\def\ekvd@#1#2%
   {%
     \ekvd at clear@prefixes
+    \edef\ekvd at cur{\detokenize{#1}}%
     \ekvd at ifspace{#1}%
       {\ekvd at prefix\ekv at mark#1\ekv at stop{#2}}%
-      {\ekvd at err@missing at prefix{#1}}%
+      \ekvd at err@missing at type
   }
 %    \end{macrocode}
 % \end{macro}
@@ -767,7 +817,7 @@
       {\ekv at strip{#2}{\csname ekvd at t@#1\endcsname}}%
       {%
         \ekv at ifdefined{ekvd at p@#1}%
-          {\csname ekvd at p@#1\endcsname{#2}}%
+          {\csname ekvd at p@#1\endcsname\ekvd at prefix@after at p{#2}}%
           {\ekvd at err@undefined at prefix{#1}\@gobble}%
       }%
   }
@@ -783,21 +833,20 @@
   {%
     \ekvd at ifspace{#1}%
       {\ekvd at prefix#1\ekv at stop}%
-      {%
-        \expandafter\ekvd at err@missing at prefix\expandafter{\ekv at gobble@mark#1}%
-        \@gobble
-      }%
+      {\ekvd at err@missing at type\@gobble}%
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[internal]{\ekvd at p@long,\ekvd at p@protected,\ekvd at p@protect}
+% \begin{macro}[internal]
+%   {\ekvd at p@long,\ekvd at p@protected,\ekvd at p@protect,\ekvd at p@also}
 % Define the |@p@| type prefixes, they all just store some information in a
-% temporary macro and call |\ekvd at prefix@after at p|.
+% temporary macro.
 %    \begin{macrocode}
-\protected\def\ekvd at p@long{\let\ekvd at long\long\ekvd at prefix@after at p}
-\protected\def\ekvd at p@protected{\let\ekvd at prot\protected\ekvd at prefix@after at p}
+\protected\def\ekvd at p@long{\let\ekvd at long\long}
+\protected\def\ekvd at p@protected{\let\ekvd at prot\protected}
 \let\ekvd at p@protect\ekvd at p@protected
+\protected\def\ekvd at p@also{\let\ekvd at ifalso\@firstoftwo}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -809,14 +858,23 @@
 %    \begin{macrocode}
 \protected\def\ekvd at t@set#1#2%
   {%
-    \ekvd at assert@not at long{set #1}%
-    \ekvd at assert@not at protected{set #1}%
-    \ekvd at ifnoarg{#2}%
-      {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#1}}}%
+    \ekvd at assert@not at long
+    \ekvd at assert@not at protected
+    \ekv at ifempty{#2}%
+      {\ekvd at err@missing at definition}%
       {%
-        \ekv at ifempty{#2}%
-          {\ekvd at err@missing at definition{set #1}}%
-          {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#2}}}%
+        \ekvd at ifalso
+          {%
+            \ekvd at ifnoarg{#2}%
+              {\ekvd at add@noval{#1}{\ekvchangeset{#1}}}%
+              {\ekvd at add@noval{#1}{\ekvchangeset{#2}}}%
+              \ekvd at assert@not at protected@also
+          }%
+          {%
+            \ekvd at ifnoarg{#2}%
+              {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#1}}}%
+              {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#2}}}%
+          }%
       }%
   }
 %    \end{macrocode}
@@ -832,11 +890,13 @@
 %    \begin{macrocode}
 \protected\long\def\ekvd at type@noval#1#2#3#4%
   {%
-    \ekvd at assert@arg{#1noval #3}{#4}%
+    \ekvd at assert@arg{#4}%
       {%
-        \ekvd at assert@not at long{#1noval #3}%
+        \ekvd at assert@not at long
         \ekvd at prot#2\ekvd at tmp{#4}%
-        \ekvletNoVal\ekvd at set{#3}\ekvd at tmp
+        \ekvd at ifalso
+          {\ekvd at exp@Nno\ekvd at add@noval{#3}\ekvd at tmp{}}%
+          {\ekvletNoVal\ekvd at set{#3}\ekvd at tmp}%
       }%
   }
 \protected\def\ekvd at t@noval{\ekvd at type@noval{}\def}
@@ -850,10 +910,12 @@
 %    \begin{macrocode}
 \protected\long\def\ekvd at type@code#1#2#3#4%
   {%
-    \ekvd at assert@arg{#1code #3}{#4}
+    \ekvd at assert@arg{#4}
       {%
         \ekvd at prot\ekvd at long#2\ekvd at tmp##1{#4}%
-        \ekvlet\ekvd at set{#3}\ekvd at tmp
+        \ekvd at ifalso
+          {\ekvd at exp@Nno\ekvd at add@val{#3}{\ekvd at tmp{##1}}{}}%
+          {\ekvlet\ekvd at set{#3}\ekvd at tmp}%
       }%
   }
 \protected\def\ekvd at t@code{\ekvd at type@code{}\def}
@@ -870,17 +932,19 @@
 %    \begin{macrocode}
 \protected\long\def\ekvd at type@default#1#2#3#4%
   {%
-    \ekvd at assert@arg{#1default #3}{#4}%
+    \ekvd at assert@arg{#4}%
       {%
         \ekvifdefined\ekvd at set{#3}%
           {%
-            \ekvd at assert@not at long{#1default #3}%
+            \ekvd at assert@not at long
             \ekvd at prot\edef\ekvd at tmp
               {%
                 \unexpanded\expandafter#2%
                   {\csname\ekv at name\ekvd at set{#3}\endcsname{#4}}%
               }%
-            \ekvletNoVal\ekvd at set{#3}\ekvd at tmp
+            \ekvd at ifalso
+              {\ekvd at exp@Nno\ekvd at add@noval{#3}\ekvd at tmp{}}%
+              {\ekvletNoVal\ekvd at set{#3}\ekvd at tmp}%
           }%
           {\ekvd at err@undefined at key{#3}}%
       }%
@@ -896,14 +960,16 @@
 %    \begin{macrocode}
 \protected\long\def\ekvd at t@edefault#1#2%
   {%
-    \ekvd at assert@arg{edefault #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{edefault #1}%
+            \ekvd at assert@not at long
             \ekvd at prot\edef\ekvd at tmp
               {\csname\ekv at name\ekvd at set{#1}\endcsname{#2}}%
-            \ekvletNoVal\ekvd at set{#1}\ekvd at tmp
+            \ekvd at ifalso
+              {\ekvd at exp@Nno\ekvd at add@noval{#1}\ekvd at tmp{}}%
+              {\ekvletNoVal\ekvd at set{#1}\ekvd at tmp}%
           }%
           {\ekvd at err@undefined at key{#1}}%
       }%
@@ -915,12 +981,13 @@
 %    \begin{macrocode}
 \long\def\ekvd at t@initial#1#2%
   {%
-    \ekvd at assert@arg{initial #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{initial #1}%
-            \ekvd at assert@not at protected{initial #1}%
+            \ekvd at assert@not at also
+            \ekvd at assert@not at long
+            \ekvd at assert@not at protected
             \csname\ekv at name\ekvd at set{#1}\endcsname{#2}%
           }%
           {\ekvd at err@undefined at key{#1}}%
@@ -928,12 +995,13 @@
   }
 \long\def\ekvd at t@oinitial#1#2%
   {%
-    \ekvd at assert@arg{oinitial #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{oinitial #1}%
-            \ekvd at assert@not at protected{oinitial #1}%
+            \ekvd at assert@not at also
+            \ekvd at assert@not at long
+            \ekvd at assert@not at protected
             \csname\ekv at name\ekvd at set{#1}\expandafter\endcsname\expandafter{#2}%
           }%
           {\ekvd at err@undefined at key{#1}}%
@@ -941,12 +1009,13 @@
   }
 \long\def\ekvd at t@einitial#1#2%
   {%
-    \ekvd at assert@arg{einitial #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{einitial #1}%
-            \ekvd at assert@not at protected{einitial #1}%
+            \ekvd at assert@not at also
+            \ekvd at assert@not at long
+            \ekvd at assert@not at protected
             \edef\ekvd at tmp{#2}%
             \csname\ekv at name\ekvd at set{#1}\expandafter\endcsname\expandafter
               {\ekvd at tmp}%
@@ -966,7 +1035,7 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@bool#1#2#3#4#5#6#7%
   {%
-    \ekvd at assert@filledarg{#1bool#2 #6}{#7}%
+    \ekvd at assert@filledarg{#7}%
       {%
         \ekvd at newlet#7#5%
         \ekvd at type@choice{#1bool#2}{#6}%
@@ -992,22 +1061,33 @@
 %     \ekvd at type@data,\ekvd at t@data,\ekvd at t@gdata,\ekvd at t@dataT,\ekvd at t@gdataT
 %   }
 %    \begin{macrocode}
-\protected\def\ekvd at type@data#1#2#3#4#5#6#7%
+\protected\def\ekvd at type@data#1#2#3#4#5#6#7#8%
   {%
-    \ekvd at assert@filledarg{#1data#2 #6}{#7}%
+    \ekvd at assert@filledarg{#8}%
       {%
-        \ekvd at newlet#7#3%
-        \protected\ekvd at long\ekvdef\ekvd at set{#6}{\long#4#7####1#5{####1{##1}}}%
+        \ekvd at newlet#8#3%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#7}{\long#4#8####1#5{####1{#6}}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#7}%
+              {\long#4#8####1#5{####1{#6}}}%
+          }%
       }%
   }
-\protected\def\ekvd at t@data{\ekvd at type@data{}{}\@secondoftwo\def{####2}}
-\protected\def\ekvd at t@edata{\ekvd at type@data e{}\@secondoftwo\edef{####2}}
-\protected\def\ekvd at t@gdata{\ekvd at type@data g{}\@secondoftwo\gdef{####2}}
-\protected\def\ekvd at t@xdata{\ekvd at type@data x{}\@secondoftwo\xdef{####2}}
-\protected\def\ekvd at t@dataT{\ekvd at type@data{}T\@gobble\def{}}
-\protected\def\ekvd at t@edataT{\ekvd at type@data eT\@gobble\edef{}}
-\protected\def\ekvd at t@gdataT{\ekvd at type@data gT\@gobble\gdef{}}
-\protected\def\ekvd at t@xdataT{\ekvd at type@data xT\@gobble\xdef{}}
+\protected\def\ekvd at t@data
+  {\ekvd at type@data{}{}\@secondoftwo\edef{####2}{\unexpanded{##1}}}
+\protected\def\ekvd at t@edata{\ekvd at type@data e{}\@secondoftwo\edef{####2}{##1}}
+\protected\def\ekvd at t@gdata
+  {\ekvd at type@data g{}\@secondoftwo\xdef{####2}{\unexpanded{##1}}}
+\protected\def\ekvd at t@xdata{\ekvd at type@data x{}\@secondoftwo\xdef{####2}{##1}}
+\protected\def\ekvd at t@dataT{\ekvd at type@data{}T\@gobble\edef{}{\unexpanded{##1}}}
+\protected\def\ekvd at t@edataT{\ekvd at type@data eT\@gobble\edef{}{##1}}
+\protected\def\ekvd at t@gdataT
+  {\ekvd at type@data gT\@gobble\xdef{}{\unexpanded{##1}}}
+\protected\def\ekvd at t@xdataT{\ekvd at type@data xT\@gobble\xdef{}{##1}}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1020,11 +1100,18 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@box#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1box #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newreg#4{box}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}%
-          {#2\setbox#4\hbox{\begingroup##1\endgroup}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2\setbox#4\hbox{\begingroup##1\endgroup}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#3}%
+              {#2\setbox#4\hbox{\begingroup##1\endgroup}}%
+          }%
       }%
   }
 \protected\def\ekvd at t@box{\ekvd at type@box{}{}}
@@ -1037,10 +1124,15 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@toks#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1toks #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newreg#4{toks}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4{##1}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}}%
       }%
   }
 \protected\def\ekvd at t@toks{\ekvd at type@toks{}{}}
@@ -1054,10 +1146,18 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@apptoks#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1apptoks #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newreg#4{toks}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4\expandafter{\the#4##1}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4\expandafter{\the#4##1}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#3}%
+              {#2#4\expandafter{\the#4##1}}%
+          }%
       }%
   }
 \protected\def\ekvd at t@apptoks{\ekvd at type@apptoks{}{}}
@@ -1076,10 +1176,15 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@reg#1#2#3#4#5#6#7%
   {%
-    \ekvd at assert@filledarg{#1 #6}{#7}%
+    \ekvd at assert@filledarg{#7}%
       {%
         \ekvd at newreg#7{#2}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#6}{#3#7=#4##1#5\relax}%
+        \ekvd at ifalso
+          {%
+            \let\evkd at prot\protected
+            \ekvd at add@val{#6}{#3#7=#4##1#5\relax}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#6}{#3#7=#4##1#5\relax}}%
       }%
   }
 \protected\def\ekvd at t@int{\ekvd at type@reg{int}{count}{}{}{}}
@@ -1103,10 +1208,15 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@store#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1store #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
-        \unless\ifdefined#4\let#4\ekvd at empty\fi
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{\unexpanded{##1}}}%
+        \ekvd at newlet#4\ekvd at empty
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4{\unexpanded{##1}}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{\unexpanded{##1}}}}%
       }%
   }
 \protected\def\ekvd at t@store{\ekvd at type@store{}\edef}
@@ -1119,10 +1229,15 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@estore#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1store #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newlet#4\ekvd at empty
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4{##1}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}}%
       }%
   }
 \protected\def\ekvd at t@estore{\ekvd at type@estore{e}\edef}
@@ -1138,13 +1253,15 @@
 % |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 at type@meta#1#2#3#4#5%
+\protected\long\def\ekvd at type@meta#1#2#3#4#5#6#7#8%
   {%
-    \ekvd at assert@filledarg{#1meta #4}{#5}%
+    \ekvd at assert@filledarg{#8}%
       {%
         \edef\ekvd at tmp{\ekvd at set}%
-        \expandafter\ekvd at type@meta at a\expandafter{\ekvd at tmp}{#5}{#3}%
-        #2\ekvd at set{#4}\ekvd at tmp
+        \expandafter\ekvd at type@meta at a\expandafter{\ekvd at tmp}{#8}{#3}%
+        \ekvd at ifalso
+          {\ekvd at exp@Nno#4{#7}{\ekvd at tmp#5}{#6}}%
+          {#2\ekvd at set{#7}\ekvd at tmp}%
       }%
   }
 \protected\long\def\ekvd at type@meta at a#1#2%
@@ -1159,11 +1276,12 @@
   {%
     \ekvd at prot\ekvd at long\def\ekvd at tmp#2{#1}%
   }
-\protected\def\ekvd at t@meta{\ekvd at type@meta{}\ekvlet{##1}}
-\protected\long\def\ekvd at t@nmeta#1#2%
+\protected\def\ekvd at t@meta{\ekvd at type@meta{}\ekvlet{##1}\ekvd at add@val{{##1}}{}}
+\protected\def\ekvd at t@nmeta
   {%
-    \ekvd at assert@not at long{nmeta #1}%
-    \ekvd at type@meta n\ekvletNoVal{}{#1}{#2}%
+    \ekvd at assert@not at long
+    \ekvd at type@meta
+      n\ekvletNoVal{}\ekvd at add@noval{}\ekvd at assert@not at long@also
   }
 %    \end{macrocode}
 % \end{macro}
@@ -1174,19 +1292,23 @@
 % 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 at type@smeta#1#2#3#4#5%
+\protected\long\def\ekvd at type@smeta#1#2#3#4#5#6#7#8%
   {%
-    \ekvd at assert@twoargs{s#1meta #4}{#5}%
+    \ekvd at assert@twoargs{#8}%
       {%
-        \ekvd at type@meta at a#5{#3}%
-        #2\ekvd at set{#4}\ekvd at tmp
+        \ekvd at type@meta at a#8{#3}%
+        \ekvd at ifalso
+          {\ekvd at exp@Nno#4{#7}{\ekvd at tmp#5}{#6}}%
+          {#2\ekvd at set{#7}\ekvd at tmp}%
       }%
   }
-\protected\def\ekvd at t@smeta{\ekvd at type@smeta{}\ekvlet{##1}}
-\protected\long\def\ekvd at t@snmeta#1#2%
+\protected\def\ekvd at t@smeta
+  {\ekvd at type@smeta{}\ekvlet{##1}\ekvd at add@val{{##1}}{}}
+\protected\def\ekvd at t@snmeta
   {%
-    \ekvd at assert@not at long{snmeta #1}%
-    \ekvd at type@smeta n\ekvletNoVal{}{#1}{#2}%
+    \ekvd at assert@not at long
+    \ekvd at type@smeta
+      n\ekvletNoVal{}\ekvd at add@noval{}\ekvd at assert@not at long@also
   }
 %    \end{macrocode}
 % \end{macro}
@@ -1206,12 +1328,16 @@
 %    \begin{macrocode}
 \protected\def\ekvd at type@choice#1#2%
   {%
-    \ekvd at assert@not at long{#1 #2}%
+    \ekvd at assert@not at long
     \ekvd at prot\edef\ekvd at tmp##1%
       {%
         \unexpanded{\ekvd at h@choice}{\ekvd at choice@name\ekvd at set{#2}{##1}}%
       }%
-    \ekvlet\ekvd at set{#2}\ekvd at tmp
+    \ekvd at ifalso
+      {%
+        \ekvd at exp@Nno\ekvd at add@val{#2}{\ekvd at tmp{##1}}\ekvd at assert@not at long@also
+      }%
+      {\ekvlet\ekvd at set{#2}\ekvd at tmp}%
   }
 %    \end{macrocode}
 % |\ekvd at populate@choice| just uses |\ekvparse| and then gives control to
@@ -1224,7 +1350,7 @@
   }
 \protected\long\def\ekvd at populate@choice at noarg#1%
   {%
-    \expandafter\ekvd at err@missing at definition\expandafter{\ekvd at set@choice : #1}%
+    \expandafter\ekvd at err@missing at definition@msg\expandafter{\ekvd at cur : #1}%
   }
 %    \end{macrocode}
 % |\ekvd at populate@choice@| runs the prefix-test, if there is none we can
@@ -1236,7 +1362,7 @@
 \protected\long\def\ekvd at populate@choice@#1#2%
   {%
     \ekvd at clear@prefixes
-    \expandafter\ekvd at assert@arg\expandafter{\ekvd at set@choice : #1}{#2}%
+    \expandafter\ekvd at assert@arg at msg\expandafter{\ekvd at cur : #1}{#2}%
       {%
         \ekvd at ifspace{#1}%
           {\ekvd at choice@prefix\ekv at mark#1\ekv at stop}%
@@ -1269,16 +1395,17 @@
   }
 \protected\def\ekvd at choice@p at protected{\let\ekvd at prot\protected}
 \let\ekvd at choice@p at protect\ekvd at choice@p at protected
-\protected\def\ekvd at choice@p at long\ekvd at ifspace#1%
+\protected\def\ekvd at choice@invalid at p#1\ekvd at ifspace#2%
   {%
-    \expandafter\ekvd at choice@p at long@\expandafter{\ekv at gobble@mark#1}%
-    \ekvd at ifspace{#1}%
+    \expandafter\ekvd at choice@invalid at p@\expandafter{\ekv at gobble@mark#2}{#1}%
+    \ekvd at ifspace{#2}%
   }
-\protected\def\ekvd at choice@p at long@#1%
+\protected\def\ekvd at choice@invalid at p@#1#2%
   {%
-    \expandafter\ekvd at err@no at long\expandafter
-      {\ekvd at set@choice : long #1}%
+    \expandafter\ekvd at err@no at prefix@msg\expandafter{\ekvd at cur : #2 #1}{#2}%
   }
+\protected\def\ekvd at choice@p at long{\ekvd at choice@invalid at p{long}}%
+\protected\def\ekvd at choice@p at also{\ekvd at choice@invalid at p{also}}%
 %    \end{macrocode}
 % Finally we're able to set up the |@t at choice| macro, which has to store the
 % current choice-key's name, define the key, and parse the available choices.
@@ -1285,7 +1412,7 @@
 %    \begin{macrocode}
 \protected\long\def\ekvd at t@choice#1#2%
   {%
-    \ekvd at assert@arg{choice #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvd at type@choice{choice}{#1}%
         \def\ekvd at set@choice{#1}%
@@ -1299,9 +1426,10 @@
 %    \begin{macrocode}
 \protected\long\expandafter\def\csname ekvd at t@unknown-choice\endcsname#1#2%
   {%
-    \ekvd at assert@arg{unknown-choice #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
-        \ekvd at assert@not at long{unknown-choice #1}%
+        \ekvd at assert@not at long
+        \ekvd at assert@not at also
         \ekvd at prot\expandafter
         \def\csname\ekvd at unknown@choice at name\ekvd at set{#1}\endcsname##1{#2}%
       }%
@@ -1336,6 +1464,93 @@
 %    \end{macrocode}
 % \end{macro}
 %
+%
+% \subsubsection{Handling \texttt{also}}
+%
+% \begin{macro}[internal]
+%   {\ekvd at add@val,\ekvd at add@noval,\ekvd at add@aux,\ekvd at add@aux@}
+%    \begin{macrocode}
+\protected\long\def\ekvd at add@val#1#2#3%
+  {%
+    \ekvd at assert@val{#1}%
+      {%
+        \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}\endcsname{{##1}}%
+          {#1}{#2}{\ekvd at long\ekvdef}{#3}%
+      }%
+  }
+\protected\long\def\ekvd at add@noval#1#2#3%
+  {%
+    \ekvd at assert@noval{#1}%
+      {%
+        \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}N\endcsname{}%
+          {#1}{#2}\ekvdefNoVal{#3}%
+      }%
+  }
+\protected\long\def\ekvd at add@aux#1#2%
+  {%
+    \ekvd at extract@prefixes#1%
+    \expandafter\ekvd at add@aux@\expandafter{#1#2}%
+  }
+\protected\long\def\ekvd at add@aux@#1#2#3#4#5%
+  {%
+    #5%
+    \ekvd at prot#4\ekvd at set{#2}{#1#3}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at extract@prefixes,\ekvd at extract@prefixes@,
+%     \ekvd at extract@prefixes at long,\ekvd at extract@prefixes at prot
+%   }
+% This macro checks which prefixes were used for the definition of a macro and
+% sets |\ekvd at long| and |\ekvd at prot| accordingly.
+%    \begin{macrocode}
+\protected\def\ekvd at extract@prefixes#1%
+  {%
+    \expandafter\ekvd at extract@prefixes@\meaning#1\ekvd at 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 at extract@prefixes@#1#2#3%
+  {%
+    \protected\def\ekvd at extract@prefixes@##1#1##2\ekvd at stop
+      {%
+        \ekvd at extract@prefixes at long
+          ##1\ekvd at mark\@firstofone#2\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at long\long}%
+        \ekvd at extract@prefixes at prot
+          ##1\ekvd at mark\@firstofone#3\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at prot\protected}%
+      }%
+    \protected\def\ekvd at extract@prefixes at long##1#2##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+    \protected\def\ekvd at extract@prefixes at prot##1#3##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+  }
+%    \end{macrocode}
+% We use a temporary macro to expand the three arguments of
+% |\ekvd at extract@prefixes@|, which will set up the real meaning of itself and
+% the parsing for |\long| and |\protected|.
+%    \begin{macrocode}
+\begingroup
+\edef\ekvd at tmp
+  {%
+    \endgroup
+    \ekvd at extract@prefixes@
+      {\detokenize{macro:}}%
+      {\string\long}%
+      {\string\protected}%
+  }
+\ekvd at tmp
+%    \end{macrocode}
+% \end{macro}
+%
+%
 % \subsubsection{Tests}
 %
 % \begin{macro}[internal]{\ekvd at newlet,\ekvd at newreg}
@@ -1344,11 +1559,11 @@
 %    \begin{macrocode}
 \protected\def\ekvd at newlet#1#2%
   {%
-    \unless\ifdefined#1\let#1#2\fi
+    \ifdefined#1\ekv at fi@gobble\fi\@firstofone{\let#1#2}%
   }
 \protected\def\ekvd at newreg#1#2%
   {%
-    \unless\ifdefined#1\csname new#2\endcsname#1\fi
+    \ifdefined#1\ekv at fi@gobble\fi\@firstofone{\csname new#2\endcsname#1}%
   }
 %    \end{macrocode}
 % \end{macro}
@@ -1360,10 +1575,9 @@
 % 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 at assert@twoargs#1#2%
+\long\def\ekvd at assert@twoargs#1%
   {%
-    \ekvd at ifnottwoargs{#2}%
-      {\ekvd at err@missing at definition{#1}}%
+    \ekvd at ifnottwoargs{#1}{\ekvd at err@missing at definition}%
   }
 \long\def\ekvd at ifnottwoargs#1%
   {%
@@ -1375,15 +1589,74 @@
 % \end{macro}
 %
 % \begin{macro}[internal]
-%   {\ekvd at assert@arg,\ekvd at ifnoarg,\ekvd at ifnoarg@,\ekvd at ifnoarg@}
+%   {
+%     \ekvd at assert@val,\ekvd at assert@val@,\ekvd at assert@noval,\ekvd at assert@noval@,
+%     \ekvd at extract@args,\ekvd at extracted@args,\ekvd at one@arg at 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 at assert@val#1%
+  {%
+    \ekvifdefined\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@val@\csname\ekv at name\ekvd at set{#1}\endcsname}%
+      {%
+        \ekvifdefinedNoVal\ekvd at set{#1}%
+          \ekvd at err@add at val@on at noval
+          {\ekvd at err@undefined at key{#1}}%
+        \@gobble
+      }%
+  }
+\protected\def\ekvd at assert@val@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekvd at one@arg at string
+      \ekvd at err@unsupported at arg
+    \fi
+    \@firstofone
+  }%
+\protected\def\ekvd at assert@noval#1%
+  {%
+    \ekvifdefinedNoVal\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@noval@\csname\ekv at name\ekvd at set{#1}N\endcsname}%
+      {%
+        \ekvifdefined\ekvd at set{#1}%
+          \ekvd at err@add at noval@on at val
+          {\ekvd at err@undefined at key{#1}}%
+        \@gobble
+      }%
+  }
+\protected\def\ekvd at assert@noval@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekvd at empty
+      \ekvd at err@unsupported at arg
+    \fi
+    \@firstofone
+  }
+\protected\def\ekvd at extract@args#1%
+  {%
+    \protected\def\ekvd at extract@args##1#1##2->##3\ekvd at stop
+      {\def\ekvd at extracted@args{##2}}%
+  }
+\expandafter\ekvd at extract@args\expandafter{\detokenize{macro:}}
+\edef\ekvd at one@arg at string{\string#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+%   {
+%     \ekvd at assert@arg,\ekvd at assert@arg at msg,\ekvd at ifnoarg,\ekvd at ifnoarg@,
+%     \ekvd at 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 at assert@arg#1#2%
+\long\def\ekvd at assert@arg#1{\ekvd at ifnoarg{#1}\ekvd at err@missing at definition}
+\long\def\ekvd at assert@arg at msg#1#2%
   {%
-    \ekvd at ifnoarg{#2}%
-      {\ekvd at err@missing at definition{#1}}%
+    \ekvd at ifnoarg{#2}{\ekvd at err@missing at definition@msg{#1}}%
   }
 \long\def\ekvd at ifnoarg#1%
   {%
@@ -1401,10 +1674,9 @@
 %
 % \begin{macro}[internal]{\ekvd at assert@filledarg,\ekvd at ifnoarg@or at empty}
 %    \begin{macrocode}
-\long\def\ekvd at assert@filledarg#1#2%
+\long\def\ekvd at assert@filledarg#1%
   {%
-    \ekvd at ifnoarg@or at empty{#2}%
-      {\ekvd at err@missing at definition{#1}}%
+    \ekvd at ifnoarg@or at empty{#1}\ekvd at err@missing at definition
   }
 \long\def\ekvd at ifnoarg@or at empty#1%
   {%
@@ -1415,19 +1687,30 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[internal]{\ekvd at assert@not at long,\ekvd at assert@not at 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 at assert@not at long,\ekvd at assert@not at protected,\ekvd at assert@not at also
+%     \ekvd at assert@not at long@also,\ekvd at assert@not at 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 at assert@not at long#1%
+\def\ekvd at assert@not at long{\ifx\ekvd at long\long\ekvd at err@no at prefix{long}\fi}
+\def\ekvd at assert@not at protected
   {%
-    \ifx\ekvd at long\long\ekvd at err@no at long{#1}\fi
+    \ifx\ekvd at prot\protected\ekvd at err@no at prefix{protected}\fi
   }
-\long\def\ekvd at assert@not at protected#1%
+\def\ekvd at assert@not at also{\ekvd at ifalso{\ekvd at err@no at prefix{also}}{}}
+\def\ekvd at assert@not at long@also
   {%
-    \ifx\ekvd at prot\protected\ekvd at err@no at protected{#1}\fi
+    \ifx\ekvd at long\long\ekvd at err@no at prefix@also{long}\fi
   }
+\def\ekvd at assert@not at protected@also
+  {%
+    \ifx\ekvd at prot\protected\ekvd at err@no at prefix@also{protected}\fi
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1454,29 +1737,49 @@
 %
 % \begin{macro}[internal]
 %   {
-%     \ekvd at err@missing at definition,\ekvd at err@missing at prefix,
-%     \ekvd at err@undefined at prefix,\ekvd at err@undefined at key,\ekvd at err@no at protected,
-%     \ekvd at err@no at long
+%     \ekvd at errm,\ekvd at err@missing at definition,\ekvd at err@missing at definition@msg,
+%     \ekvd at err@missing at type,\ekvd at err@undefined at prefix,\ekvd at err@undefined at key,
+%     \ekvd at err@no at prefix,\ekvd at err@no at prefix@msg,\ekvd at err@no at prefix@also,
+%     \ekvd at err@add at val@on at noval,\ekvd at err@add at noval@on at val,
+%     \ekvd at err@unsupported at arg
 %   }
 % The non-expandable error messages are boring, so here they are:
 %    \begin{macrocode}
-\protected\def\ekvd at err@missing at definition#1%
-  {\errmessage{expkv-def Error: Missing definition for key `\unexpanded{#1}'}}
-\protected\def\ekvd at err@missing at prefix#1%
-  {\errmessage{expkv-def Error: Missing prefix for key `\unexpanded{#1}'}}
+\protected\def\ekvd at errm#1{\errmessage{expkv-def Error: #1}}
+\protected\def\ekvd at err@missing at definition
+  {\ekvd at errm{Missing definition for key `\ekvd at cur'}}
+\protected\def\ekvd at err@missing at definition@msg#1%
+  {\ekvd at errm{Missing definition for key `\unexpanded{#1}'}}
+\protected\def\ekvd at err@missing at type
+  {\ekvd at errm{Missing type prefix for key `\ekvd at cur'}}
 \protected\def\ekvd at err@undefined at prefix#1%
-  {\errmessage{expkv-def Error: Undefined prefix `\unexpanded{#1}'}}
+  {%
+    \ekvd at errm
+      {Undefined prefix `\unexpanded{#1}' found while processing `\ekvd at cur'}%
+  }
 \protected\def\ekvd at err@undefined at key#1%
-  {\errmessage{expkv-def Error: Undefined key `\unexpanded{#1}'}}
-\protected\def\ekvd at err@no at protected#1%
   {%
-    \errmessage
-      {expkv-def Error: prefix `protected' not accepted for `\unexpanded{#1}'}%
+    \ekvd at errm
+      {Undefined key `\unexpanded{#1}' found while processing `\ekvd at cur'}%
   }
-\protected\def\ekvd at err@no at long#1%
+\protected\def\ekvd at err@no at prefix#1%
+  {\ekvd at errm{prefix `#1' not accepted in `\ekvd at cur'}}
+\protected\def\ekvd at err@no at prefix@msg#1#2%
+  {\ekvd at errm{prefix `#2' not accepted in `\unexpanded{#1}'}}
+\protected\def\ekvd at err@no at prefix@also#1%
+  {\ekvd at errm{`\ekvd at cur' not allowed with a `#1' key}}
+\protected\def\ekvd at err@add at val@on at noval
+  {\ekvd at errm{`\ekvd at cur' not allowed with a NoVal key}}
+\protected\def\ekvd at err@add at noval@on at val
+  {\ekvd at errm{`\ekvd at cur' not allowed with a value taking key}}
+\protected\def\ekvd at err@unsupported at arg\fi\@firstofone#1%
   {%
-    \errmessage
-      {expkv-def Error: prefix `long' not accepted for `\unexpanded{#1}'}%
+    \fi
+    \ekvd at errm
+      {%
+        Existing key-macro has the unsupported argument string
+        `\ekvd at extracted@args' for key `\ekvd at cur'%
+      }%
   }
 %    \end{macrocode}
 % \end{macro}

Modified: trunk/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex	2020-07-13 21:10:07 UTC (rev 55828)
+++ trunk/Master/texmf-dist/tex/generic/expkv-def/expkv-def.tex	2020-07-13 21:10:18 UTC (rev 55829)
@@ -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 at tmp\endcsname
 \expandafter\chardef\csname ekvd at tmp\endcsname=\catcode`\@
 \catcode`\@=11
@@ -45,8 +45,14 @@
   {%
     \let\ekvd at long\ekvd at empty
     \let\ekvd at prot\ekvd at empty
+    \let\ekvd at ifalso\@secondoftwo
   }
 \ekvd at clear@prefixes
+\long\def\ekvd at exp@Nno#1#2#3%
+  {%
+    \expandafter\ekvd at exp@reinsert at n\expandafter{#3}{#1{#2}}%
+  }
+\long\def\ekvd at exp@reinsert at n#1#2{#2{#1}}
 \protected\def\ekvdefinekeys#1%
   {%
     \def\ekvd at set{#1}%
@@ -56,9 +62,10 @@
 \protected\long\def\ekvd@#1#2%
   {%
     \ekvd at clear@prefixes
+    \edef\ekvd at cur{\detokenize{#1}}%
     \ekvd at ifspace{#1}%
       {\ekvd at prefix\ekv at mark#1\ekv at stop{#2}}%
-      {\ekvd at err@missing at prefix{#1}}%
+      \ekvd at err@missing at type
   }
 \protected\def\ekvd at prefix#1 {\ekv at strip{#1}\ekvd at prefix@\ekv at mark}
 \protected\def\ekvd at prefix@#1#2\ekv at stop
@@ -67,7 +74,7 @@
       {\ekv at strip{#2}{\csname ekvd at t@#1\endcsname}}%
       {%
         \ekv at ifdefined{ekvd at p@#1}%
-          {\csname ekvd at p@#1\endcsname{#2}}%
+          {\csname ekvd at p@#1\endcsname\ekvd at prefix@after at p{#2}}%
           {\ekvd at err@undefined at prefix{#1}\@gobble}%
       }%
   }
@@ -75,33 +82,42 @@
   {%
     \ekvd at ifspace{#1}%
       {\ekvd at prefix#1\ekv at stop}%
-      {%
-        \expandafter\ekvd at err@missing at prefix\expandafter{\ekv at gobble@mark#1}%
-        \@gobble
-      }%
+      {\ekvd at err@missing at type\@gobble}%
   }
-\protected\def\ekvd at p@long{\let\ekvd at long\long\ekvd at prefix@after at p}
-\protected\def\ekvd at p@protected{\let\ekvd at prot\protected\ekvd at prefix@after at p}
+\protected\def\ekvd at p@long{\let\ekvd at long\long}
+\protected\def\ekvd at p@protected{\let\ekvd at prot\protected}
 \let\ekvd at p@protect\ekvd at p@protected
+\protected\def\ekvd at p@also{\let\ekvd at ifalso\@firstoftwo}
 \protected\def\ekvd at t@set#1#2%
   {%
-    \ekvd at assert@not at long{set #1}%
-    \ekvd at assert@not at protected{set #1}%
-    \ekvd at ifnoarg{#2}%
-      {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#1}}}%
+    \ekvd at assert@not at long
+    \ekvd at assert@not at protected
+    \ekv at ifempty{#2}%
+      {\ekvd at err@missing at definition}%
       {%
-        \ekv at ifempty{#2}%
-          {\ekvd at err@missing at definition{set #1}}%
-          {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#2}}}%
+        \ekvd at ifalso
+          {%
+            \ekvd at ifnoarg{#2}%
+              {\ekvd at add@noval{#1}{\ekvchangeset{#1}}}%
+              {\ekvd at add@noval{#1}{\ekvchangeset{#2}}}%
+              \ekvd at assert@not at protected@also
+          }%
+          {%
+            \ekvd at ifnoarg{#2}%
+              {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#1}}}%
+              {\ekvdefNoVal\ekvd at set{#1}{\ekvchangeset{#2}}}%
+          }%
       }%
   }
 \protected\long\def\ekvd at type@noval#1#2#3#4%
   {%
-    \ekvd at assert@arg{#1noval #3}{#4}%
+    \ekvd at assert@arg{#4}%
       {%
-        \ekvd at assert@not at long{#1noval #3}%
+        \ekvd at assert@not at long
         \ekvd at prot#2\ekvd at tmp{#4}%
-        \ekvletNoVal\ekvd at set{#3}\ekvd at tmp
+        \ekvd at ifalso
+          {\ekvd at exp@Nno\ekvd at add@noval{#3}\ekvd at tmp{}}%
+          {\ekvletNoVal\ekvd at set{#3}\ekvd at tmp}%
       }%
   }
 \protected\def\ekvd at t@noval{\ekvd at type@noval{}\def}
@@ -108,10 +124,12 @@
 \protected\def\ekvd at t@enoval{\ekvd at type@noval e\edef}
 \protected\long\def\ekvd at type@code#1#2#3#4%
   {%
-    \ekvd at assert@arg{#1code #3}{#4}
+    \ekvd at assert@arg{#4}
       {%
         \ekvd at prot\ekvd at long#2\ekvd at tmp##1{#4}%
-        \ekvlet\ekvd at set{#3}\ekvd at tmp
+        \ekvd at ifalso
+          {\ekvd at exp@Nno\ekvd at add@val{#3}{\ekvd at tmp{##1}}{}}%
+          {\ekvlet\ekvd at set{#3}\ekvd at tmp}%
       }%
   }
 \protected\def\ekvd at t@code{\ekvd at type@code{}\def}
@@ -118,17 +136,19 @@
 \protected\def\ekvd at t@ecode{\ekvd at type@code e\edef}
 \protected\long\def\ekvd at type@default#1#2#3#4%
   {%
-    \ekvd at assert@arg{#1default #3}{#4}%
+    \ekvd at assert@arg{#4}%
       {%
         \ekvifdefined\ekvd at set{#3}%
           {%
-            \ekvd at assert@not at long{#1default #3}%
+            \ekvd at assert@not at long
             \ekvd at prot\edef\ekvd at tmp
               {%
                 \unexpanded\expandafter#2%
                   {\csname\ekv at name\ekvd at set{#3}\endcsname{#4}}%
               }%
-            \ekvletNoVal\ekvd at set{#3}\ekvd at tmp
+            \ekvd at ifalso
+              {\ekvd at exp@Nno\ekvd at add@noval{#3}\ekvd at tmp{}}%
+              {\ekvletNoVal\ekvd at set{#3}\ekvd at tmp}%
           }%
           {\ekvd at err@undefined at key{#3}}%
       }%
@@ -137,14 +157,16 @@
 \protected\def\ekvd at t@qdefault{\ekvd at type@default q{\expandafter\expandafter}}
 \protected\long\def\ekvd at t@edefault#1#2%
   {%
-    \ekvd at assert@arg{edefault #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{edefault #1}%
+            \ekvd at assert@not at long
             \ekvd at prot\edef\ekvd at tmp
               {\csname\ekv at name\ekvd at set{#1}\endcsname{#2}}%
-            \ekvletNoVal\ekvd at set{#1}\ekvd at tmp
+            \ekvd at ifalso
+              {\ekvd at exp@Nno\ekvd at add@noval{#1}\ekvd at tmp{}}%
+              {\ekvletNoVal\ekvd at set{#1}\ekvd at tmp}%
           }%
           {\ekvd at err@undefined at key{#1}}%
       }%
@@ -151,12 +173,13 @@
   }
 \long\def\ekvd at t@initial#1#2%
   {%
-    \ekvd at assert@arg{initial #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{initial #1}%
-            \ekvd at assert@not at protected{initial #1}%
+            \ekvd at assert@not at also
+            \ekvd at assert@not at long
+            \ekvd at assert@not at protected
             \csname\ekv at name\ekvd at set{#1}\endcsname{#2}%
           }%
           {\ekvd at err@undefined at key{#1}}%
@@ -164,12 +187,13 @@
   }
 \long\def\ekvd at t@oinitial#1#2%
   {%
-    \ekvd at assert@arg{oinitial #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{oinitial #1}%
-            \ekvd at assert@not at protected{oinitial #1}%
+            \ekvd at assert@not at also
+            \ekvd at assert@not at long
+            \ekvd at assert@not at protected
             \csname\ekv at name\ekvd at set{#1}\expandafter\endcsname\expandafter{#2}%
           }%
           {\ekvd at err@undefined at key{#1}}%
@@ -177,12 +201,13 @@
   }
 \long\def\ekvd at t@einitial#1#2%
   {%
-    \ekvd at assert@arg{einitial #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvifdefined\ekvd at set{#1}%
           {%
-            \ekvd at assert@not at long{einitial #1}%
-            \ekvd at assert@not at protected{einitial #1}%
+            \ekvd at assert@not at also
+            \ekvd at assert@not at long
+            \ekvd at assert@not at protected
             \edef\ekvd at tmp{#2}%
             \csname\ekv at name\ekvd at set{#1}\expandafter\endcsname\expandafter
               {\ekvd at tmp}%
@@ -192,7 +217,7 @@
   }
 \protected\def\ekvd at type@bool#1#2#3#4#5#6#7%
   {%
-    \ekvd at assert@filledarg{#1bool#2 #6}{#7}%
+    \ekvd at assert@filledarg{#7}%
       {%
         \ekvd at newlet#7#5%
         \ekvd at type@choice{#1bool#2}{#6}%
@@ -210,29 +235,47 @@
 \protected\def\ekvd at t@boolTF{\ekvd at type@bool{}{TF}{}\@firstoftwo\@secondoftwo}
 \protected\def\ekvd at t@gboolTF
   {\ekvd at type@bool g{TF}\global\@firstoftwo\@secondoftwo}
-\protected\def\ekvd at type@data#1#2#3#4#5#6#7%
+\protected\def\ekvd at type@data#1#2#3#4#5#6#7#8%
   {%
-    \ekvd at assert@filledarg{#1data#2 #6}{#7}%
+    \ekvd at assert@filledarg{#8}%
       {%
-        \ekvd at newlet#7#3%
-        \protected\ekvd at long\ekvdef\ekvd at set{#6}{\long#4#7####1#5{####1{##1}}}%
+        \ekvd at newlet#8#3%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#7}{\long#4#8####1#5{####1{#6}}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#7}%
+              {\long#4#8####1#5{####1{#6}}}%
+          }%
       }%
   }
-\protected\def\ekvd at t@data{\ekvd at type@data{}{}\@secondoftwo\def{####2}}
-\protected\def\ekvd at t@edata{\ekvd at type@data e{}\@secondoftwo\edef{####2}}
-\protected\def\ekvd at t@gdata{\ekvd at type@data g{}\@secondoftwo\gdef{####2}}
-\protected\def\ekvd at t@xdata{\ekvd at type@data x{}\@secondoftwo\xdef{####2}}
-\protected\def\ekvd at t@dataT{\ekvd at type@data{}T\@gobble\def{}}
-\protected\def\ekvd at t@edataT{\ekvd at type@data eT\@gobble\edef{}}
-\protected\def\ekvd at t@gdataT{\ekvd at type@data gT\@gobble\gdef{}}
-\protected\def\ekvd at t@xdataT{\ekvd at type@data xT\@gobble\xdef{}}
+\protected\def\ekvd at t@data
+  {\ekvd at type@data{}{}\@secondoftwo\edef{####2}{\unexpanded{##1}}}
+\protected\def\ekvd at t@edata{\ekvd at type@data e{}\@secondoftwo\edef{####2}{##1}}
+\protected\def\ekvd at t@gdata
+  {\ekvd at type@data g{}\@secondoftwo\xdef{####2}{\unexpanded{##1}}}
+\protected\def\ekvd at t@xdata{\ekvd at type@data x{}\@secondoftwo\xdef{####2}{##1}}
+\protected\def\ekvd at t@dataT{\ekvd at type@data{}T\@gobble\edef{}{\unexpanded{##1}}}
+\protected\def\ekvd at t@edataT{\ekvd at type@data eT\@gobble\edef{}{##1}}
+\protected\def\ekvd at t@gdataT
+  {\ekvd at type@data gT\@gobble\xdef{}{\unexpanded{##1}}}
+\protected\def\ekvd at t@xdataT{\ekvd at type@data xT\@gobble\xdef{}{##1}}
 \protected\def\ekvd at type@box#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1box #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newreg#4{box}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}%
-          {#2\setbox#4\hbox{\begingroup##1\endgroup}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2\setbox#4\hbox{\begingroup##1\endgroup}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#3}%
+              {#2\setbox#4\hbox{\begingroup##1\endgroup}}%
+          }%
       }%
   }
 \protected\def\ekvd at t@box{\ekvd at type@box{}{}}
@@ -239,10 +282,15 @@
 \protected\def\ekvd at t@gbox{\ekvd at type@box g\global}
 \protected\def\ekvd at type@toks#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1toks #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newreg#4{toks}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4{##1}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}}%
       }%
   }
 \protected\def\ekvd at t@toks{\ekvd at type@toks{}{}}
@@ -249,10 +297,18 @@
 \protected\def\ekvd at t@gtoks{\ekvd at type@toks{g}\global}
 \protected\def\ekvd at type@apptoks#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1apptoks #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newreg#4{toks}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4\expandafter{\the#4##1}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4\expandafter{\the#4##1}}{}%
+          }%
+          {%
+            \protected\ekvd at long\ekvdef\ekvd at set{#3}%
+              {#2#4\expandafter{\the#4##1}}%
+          }%
       }%
   }
 \protected\def\ekvd at t@apptoks{\ekvd at type@apptoks{}{}}
@@ -259,10 +315,15 @@
 \protected\def\ekvd at t@gapptoks{\ekvd at type@apptoks{g}\global}
 \protected\def\ekvd at type@reg#1#2#3#4#5#6#7%
   {%
-    \ekvd at assert@filledarg{#1 #6}{#7}%
+    \ekvd at assert@filledarg{#7}%
       {%
         \ekvd at newreg#7{#2}%
-        \protected\ekvd at long\ekvdef\ekvd at set{#6}{#3#7=#4##1#5\relax}%
+        \ekvd at ifalso
+          {%
+            \let\evkd at prot\protected
+            \ekvd at add@val{#6}{#3#7=#4##1#5\relax}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#6}{#3#7=#4##1#5\relax}}%
       }%
   }
 \protected\def\ekvd at t@int{\ekvd at type@reg{int}{count}{}{}{}}
@@ -279,10 +340,15 @@
 \protected\def\ekvd at t@xskip{\ekvd at type@reg{xskip}{skip}\global\glueexpr\relax}
 \protected\def\ekvd at type@store#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1store #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
-        \unless\ifdefined#4\let#4\ekvd at empty\fi
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{\unexpanded{##1}}}%
+        \ekvd at newlet#4\ekvd at empty
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4{\unexpanded{##1}}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{\unexpanded{##1}}}}%
       }%
   }
 \protected\def\ekvd at t@store{\ekvd at type@store{}\edef}
@@ -289,21 +355,28 @@
 \protected\def\ekvd at t@gstore{\ekvd at type@store{g}\xdef}
 \protected\def\ekvd at type@estore#1#2#3#4%
   {%
-    \ekvd at assert@filledarg{#1store #3}{#4}%
+    \ekvd at assert@filledarg{#4}%
       {%
         \ekvd at newlet#4\ekvd at empty
-        \protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}%
+        \ekvd at ifalso
+          {%
+            \let\ekvd at prot\protected
+            \ekvd at add@val{#3}{#2#4{##1}}{}%
+          }%
+          {\protected\ekvd at long\ekvdef\ekvd at set{#3}{#2#4{##1}}}%
       }%
   }
 \protected\def\ekvd at t@estore{\ekvd at type@estore{e}\edef}
 \protected\def\ekvd at t@xstore{\ekvd at type@estore{x}\xdef}
-\protected\long\def\ekvd at type@meta#1#2#3#4#5%
+\protected\long\def\ekvd at type@meta#1#2#3#4#5#6#7#8%
   {%
-    \ekvd at assert@filledarg{#1meta #4}{#5}%
+    \ekvd at assert@filledarg{#8}%
       {%
         \edef\ekvd at tmp{\ekvd at set}%
-        \expandafter\ekvd at type@meta at a\expandafter{\ekvd at tmp}{#5}{#3}%
-        #2\ekvd at set{#4}\ekvd at tmp
+        \expandafter\ekvd at type@meta at a\expandafter{\ekvd at tmp}{#8}{#3}%
+        \ekvd at ifalso
+          {\ekvd at exp@Nno#4{#7}{\ekvd at tmp#5}{#6}}%
+          {#2\ekvd at set{#7}\ekvd at tmp}%
       }%
   }
 \protected\long\def\ekvd at type@meta at a#1#2%
@@ -318,34 +391,43 @@
   {%
     \ekvd at prot\ekvd at long\def\ekvd at tmp#2{#1}%
   }
-\protected\def\ekvd at t@meta{\ekvd at type@meta{}\ekvlet{##1}}
-\protected\long\def\ekvd at t@nmeta#1#2%
+\protected\def\ekvd at t@meta{\ekvd at type@meta{}\ekvlet{##1}\ekvd at add@val{{##1}}{}}
+\protected\def\ekvd at t@nmeta
   {%
-    \ekvd at assert@not at long{nmeta #1}%
-    \ekvd at type@meta n\ekvletNoVal{}{#1}{#2}%
+    \ekvd at assert@not at long
+    \ekvd at type@meta
+      n\ekvletNoVal{}\ekvd at add@noval{}\ekvd at assert@not at long@also
   }
-\protected\long\def\ekvd at type@smeta#1#2#3#4#5%
+\protected\long\def\ekvd at type@smeta#1#2#3#4#5#6#7#8%
   {%
-    \ekvd at assert@twoargs{s#1meta #4}{#5}%
+    \ekvd at assert@twoargs{#8}%
       {%
-        \ekvd at type@meta at a#5{#3}%
-        #2\ekvd at set{#4}\ekvd at tmp
+        \ekvd at type@meta at a#8{#3}%
+        \ekvd at ifalso
+          {\ekvd at exp@Nno#4{#7}{\ekvd at tmp#5}{#6}}%
+          {#2\ekvd at set{#7}\ekvd at tmp}%
       }%
   }
-\protected\def\ekvd at t@smeta{\ekvd at type@smeta{}\ekvlet{##1}}
-\protected\long\def\ekvd at t@snmeta#1#2%
+\protected\def\ekvd at t@smeta
+  {\ekvd at type@smeta{}\ekvlet{##1}\ekvd at add@val{{##1}}{}}
+\protected\def\ekvd at t@snmeta
   {%
-    \ekvd at assert@not at long{snmeta #1}%
-    \ekvd at type@smeta n\ekvletNoVal{}{#1}{#2}%
+    \ekvd at assert@not at long
+    \ekvd at type@smeta
+      n\ekvletNoVal{}\ekvd at add@noval{}\ekvd at assert@not at long@also
   }
 \protected\def\ekvd at type@choice#1#2%
   {%
-    \ekvd at assert@not at long{#1 #2}%
+    \ekvd at assert@not at long
     \ekvd at prot\edef\ekvd at tmp##1%
       {%
         \unexpanded{\ekvd at h@choice}{\ekvd at choice@name\ekvd at set{#2}{##1}}%
       }%
-    \ekvlet\ekvd at set{#2}\ekvd at tmp
+    \ekvd at ifalso
+      {%
+        \ekvd at exp@Nno\ekvd at add@val{#2}{\ekvd at tmp{##1}}\ekvd at assert@not at long@also
+      }%
+      {\ekvlet\ekvd at set{#2}\ekvd at tmp}%
   }
 \protected\def\ekvd at populate@choice
   {%
@@ -353,12 +435,12 @@
   }
 \protected\long\def\ekvd at populate@choice at noarg#1%
   {%
-    \expandafter\ekvd at err@missing at definition\expandafter{\ekvd at set@choice : #1}%
+    \expandafter\ekvd at err@missing at definition@msg\expandafter{\ekvd at cur : #1}%
   }
 \protected\long\def\ekvd at populate@choice@#1#2%
   {%
     \ekvd at clear@prefixes
-    \expandafter\ekvd at assert@arg\expandafter{\ekvd at set@choice : #1}{#2}%
+    \expandafter\ekvd at assert@arg at msg\expandafter{\ekvd at cur : #1}{#2}%
       {%
         \ekvd at ifspace{#1}%
           {\ekvd at choice@prefix\ekv at mark#1\ekv at stop}%
@@ -391,19 +473,20 @@
   }
 \protected\def\ekvd at choice@p at protected{\let\ekvd at prot\protected}
 \let\ekvd at choice@p at protect\ekvd at choice@p at protected
-\protected\def\ekvd at choice@p at long\ekvd at ifspace#1%
+\protected\def\ekvd at choice@invalid at p#1\ekvd at ifspace#2%
   {%
-    \expandafter\ekvd at choice@p at long@\expandafter{\ekv at gobble@mark#1}%
-    \ekvd at ifspace{#1}%
+    \expandafter\ekvd at choice@invalid at p@\expandafter{\ekv at gobble@mark#2}{#1}%
+    \ekvd at ifspace{#2}%
   }
-\protected\def\ekvd at choice@p at long@#1%
+\protected\def\ekvd at choice@invalid at p@#1#2%
   {%
-    \expandafter\ekvd at err@no at long\expandafter
-      {\ekvd at set@choice : long #1}%
+    \expandafter\ekvd at err@no at prefix@msg\expandafter{\ekvd at cur : #2 #1}{#2}%
   }
+\protected\def\ekvd at choice@p at long{\ekvd at choice@invalid at p{long}}%
+\protected\def\ekvd at choice@p at also{\ekvd at choice@invalid at p{also}}%
 \protected\long\def\ekvd at t@choice#1#2%
   {%
-    \ekvd at assert@arg{choice #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
         \ekvd at type@choice{choice}{#1}%
         \def\ekvd at set@choice{#1}%
@@ -412,9 +495,10 @@
   }
 \protected\long\expandafter\def\csname ekvd at t@unknown-choice\endcsname#1#2%
   {%
-    \ekvd at assert@arg{unknown-choice #1}{#2}%
+    \ekvd at assert@arg{#2}%
       {%
-        \ekvd at assert@not at long{unknown-choice #1}%
+        \ekvd at assert@not at long
+        \ekvd at assert@not at also
         \ekvd at prot\expandafter
         \def\csname\ekvd at unknown@choice at name\ekvd at set{#1}\endcsname##1{#2}%
       }%
@@ -433,18 +517,73 @@
     \fi
     #1%
   }
+\protected\long\def\ekvd at add@val#1#2#3%
+  {%
+    \ekvd at assert@val{#1}%
+      {%
+        \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}\endcsname{{##1}}%
+          {#1}{#2}{\ekvd at long\ekvdef}{#3}%
+      }%
+  }
+\protected\long\def\ekvd at add@noval#1#2#3%
+  {%
+    \ekvd at assert@noval{#1}%
+      {%
+        \expandafter\ekvd at add@aux\csname\ekv at name\ekvd at set{#1}N\endcsname{}%
+          {#1}{#2}\ekvdefNoVal{#3}%
+      }%
+  }
+\protected\long\def\ekvd at add@aux#1#2%
+  {%
+    \ekvd at extract@prefixes#1%
+    \expandafter\ekvd at add@aux@\expandafter{#1#2}%
+  }
+\protected\long\def\ekvd at add@aux@#1#2#3#4#5%
+  {%
+    #5%
+    \ekvd at prot#4\ekvd at set{#2}{#1#3}%
+  }
+\protected\def\ekvd at extract@prefixes#1%
+  {%
+    \expandafter\ekvd at extract@prefixes@\meaning#1\ekvd at stop
+  }
+\protected\def\ekvd at extract@prefixes@#1#2#3%
+  {%
+    \protected\def\ekvd at extract@prefixes@##1#1##2\ekvd at stop
+      {%
+        \ekvd at extract@prefixes at long
+          ##1\ekvd at mark\@firstofone#2\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at long\long}%
+        \ekvd at extract@prefixes at prot
+          ##1\ekvd at mark\@firstofone#3\ekvd at mark\@gobble\ekvd at stop
+          {\let\ekvd at prot\protected}%
+      }%
+    \protected\def\ekvd at extract@prefixes at long##1#2##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+    \protected\def\ekvd at extract@prefixes at prot##1#3##2\ekvd at mark##3##4\ekvd at stop
+      {##3}%
+  }
+\begingroup
+\edef\ekvd at tmp
+  {%
+    \endgroup
+    \ekvd at extract@prefixes@
+      {\detokenize{macro:}}%
+      {\string\long}%
+      {\string\protected}%
+  }
+\ekvd at tmp
 \protected\def\ekvd at newlet#1#2%
   {%
-    \unless\ifdefined#1\let#1#2\fi
+    \ifdefined#1\ekv at fi@gobble\fi\@firstofone{\let#1#2}%
   }
 \protected\def\ekvd at newreg#1#2%
   {%
-    \unless\ifdefined#1\csname new#2\endcsname#1\fi
+    \ifdefined#1\ekv at fi@gobble\fi\@firstofone{\csname new#2\endcsname#1}%
   }
-\long\def\ekvd at assert@twoargs#1#2%
+\long\def\ekvd at assert@twoargs#1%
   {%
-    \ekvd at ifnottwoargs{#2}%
-      {\ekvd at err@missing at definition{#1}}%
+    \ekvd at ifnottwoargs{#1}{\ekvd at err@missing at definition}%
   }
 \long\def\ekvd at ifnottwoargs#1%
   {%
@@ -452,11 +591,56 @@
       \ekv at ifempty@false\ekv at ifempty@A\ekv at ifempty@B\@firstoftwo
   }
 \long\def\ekvd at ifempty@gtwo#1#2{\ekv at ifempty@\ekv at ifempty@A}
-\long\def\ekvd at assert@arg#1#2%
+\protected\def\ekvd at assert@val#1%
   {%
-    \ekvd at ifnoarg{#2}%
-      {\ekvd at err@missing at definition{#1}}%
+    \ekvifdefined\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@val@\csname\ekv at name\ekvd at set{#1}\endcsname}%
+      {%
+        \ekvifdefinedNoVal\ekvd at set{#1}%
+          \ekvd at err@add at val@on at noval
+          {\ekvd at err@undefined at key{#1}}%
+        \@gobble
+      }%
   }
+\protected\def\ekvd at assert@val@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekvd at one@arg at string
+      \ekvd at err@unsupported at arg
+    \fi
+    \@firstofone
+  }%
+\protected\def\ekvd at assert@noval#1%
+  {%
+    \ekvifdefinedNoVal\ekvd at set{#1}%
+      {\expandafter\ekvd at assert@noval@\csname\ekv at name\ekvd at set{#1}N\endcsname}%
+      {%
+        \ekvifdefined\ekvd at set{#1}%
+          \ekvd at err@add at noval@on at val
+          {\ekvd at err@undefined at key{#1}}%
+        \@gobble
+      }%
+  }
+\protected\def\ekvd at assert@noval@#1%
+  {%
+    \expandafter\ekvd at extract@args\meaning#1\ekvd at stop
+    \unless\ifx\ekvd at extracted@args\ekvd at empty
+      \ekvd at err@unsupported at arg
+    \fi
+    \@firstofone
+  }
+\protected\def\ekvd at extract@args#1%
+  {%
+    \protected\def\ekvd at extract@args##1#1##2->##3\ekvd at stop
+      {\def\ekvd at extracted@args{##2}}%
+  }
+\expandafter\ekvd at extract@args\expandafter{\detokenize{macro:}}
+\edef\ekvd at one@arg at string{\string#1}
+\long\def\ekvd at assert@arg#1{\ekvd at ifnoarg{#1}\ekvd at err@missing at definition}
+\long\def\ekvd at assert@arg at msg#1#2%
+  {%
+    \ekvd at ifnoarg{#2}{\ekvd at err@missing at definition@msg{#1}}%
+  }
 \long\def\ekvd at ifnoarg#1%
   {%
     \ekvd at ifnoarg@\ekvd at ifnoarg@mark#1\ekvd at ifnoarg@mark\ekvd at ifnoarg@t
@@ -468,10 +652,9 @@
   {%
     #1%
   }
-\long\def\ekvd at assert@filledarg#1#2%
+\long\def\ekvd at assert@filledarg#1%
   {%
-    \ekvd at ifnoarg@or at empty{#2}%
-      {\ekvd at err@missing at definition{#1}}%
+    \ekvd at ifnoarg@or at empty{#1}\ekvd at err@missing at definition
   }
 \long\def\ekvd at ifnoarg@or at empty#1%
   {%
@@ -479,14 +662,20 @@
       \@firstoftwo
       {\ekv at ifempty{#1}}%
   }
-\long\def\ekvd at assert@not at long#1%
+\def\ekvd at assert@not at long{\ifx\ekvd at long\long\ekvd at err@no at prefix{long}\fi}
+\def\ekvd at assert@not at protected
   {%
-    \ifx\ekvd at long\long\ekvd at err@no at long{#1}\fi
+    \ifx\ekvd at prot\protected\ekvd at err@no at prefix{protected}\fi
   }
-\long\def\ekvd at assert@not at protected#1%
+\def\ekvd at assert@not at also{\ekvd at ifalso{\ekvd at err@no at prefix{also}}{}}
+\def\ekvd at assert@not at long@also
   {%
-    \ifx\ekvd at prot\protected\ekvd at err@no at protected{#1}\fi
+    \ifx\ekvd at long\long\ekvd at err@no at prefix@also{long}\fi
   }
+\def\ekvd at assert@not at protected@also
+  {%
+    \ifx\ekvd at prot\protected\ekvd at err@no at prefix@also{protected}\fi
+  }
 \long\def\ekvd at ifspace#1%
   {%
     \ekvd at ifspace@#1 \ekv at ifempty@B
@@ -496,23 +685,41 @@
   {%
     \ekv at ifempty@\ekv at ifempty@A
   }
-\protected\def\ekvd at err@missing at definition#1%
-  {\errmessage{expkv-def Error: Missing definition for key `\unexpanded{#1}'}}
-\protected\def\ekvd at err@missing at prefix#1%
-  {\errmessage{expkv-def Error: Missing prefix for key `\unexpanded{#1}'}}
+\protected\def\ekvd at errm#1{\errmessage{expkv-def Error: #1}}
+\protected\def\ekvd at err@missing at definition
+  {\ekvd at errm{Missing definition for key `\ekvd at cur'}}
+\protected\def\ekvd at err@missing at definition@msg#1%
+  {\ekvd at errm{Missing definition for key `\unexpanded{#1}'}}
+\protected\def\ekvd at err@missing at type
+  {\ekvd at errm{Missing type prefix for key `\ekvd at cur'}}
 \protected\def\ekvd at err@undefined at prefix#1%
-  {\errmessage{expkv-def Error: Undefined prefix `\unexpanded{#1}'}}
+  {%
+    \ekvd at errm
+      {Undefined prefix `\unexpanded{#1}' found while processing `\ekvd at cur'}%
+  }
 \protected\def\ekvd at err@undefined at key#1%
-  {\errmessage{expkv-def Error: Undefined key `\unexpanded{#1}'}}
-\protected\def\ekvd at err@no at protected#1%
   {%
-    \errmessage
-      {expkv-def Error: prefix `protected' not accepted for `\unexpanded{#1}'}%
+    \ekvd at errm
+      {Undefined key `\unexpanded{#1}' found while processing `\ekvd at cur'}%
   }
-\protected\def\ekvd at err@no at long#1%
+\protected\def\ekvd at err@no at prefix#1%
+  {\ekvd at errm{prefix `#1' not accepted in `\ekvd at cur'}}
+\protected\def\ekvd at err@no at prefix@msg#1#2%
+  {\ekvd at errm{prefix `#2' not accepted in `\unexpanded{#1}'}}
+\protected\def\ekvd at err@no at prefix@also#1%
+  {\ekvd at errm{`\ekvd at cur' not allowed with a `#1' key}}
+\protected\def\ekvd at err@add at val@on at noval
+  {\ekvd at errm{`\ekvd at cur' not allowed with a NoVal key}}
+\protected\def\ekvd at err@add at noval@on at val
+  {\ekvd at errm{`\ekvd at cur' not allowed with a value taking key}}
+\protected\def\ekvd at err@unsupported at arg\fi\@firstofone#1%
   {%
-    \errmessage
-      {expkv-def Error: prefix `long' not accepted for `\unexpanded{#1}'}%
+    \fi
+    \ekvd at errm
+      {%
+        Existing key-macro has the unsupported argument string
+        `\ekvd at extracted@args' for key `\ekvd at cur'%
+      }%
   }
 \def\ekvd at err@choice at invalid#1%
   {%



More information about the tex-live-commits mailing list.