From 01b69c78ff33854f7f28149e8167cb4219fcb416 Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 14 Feb 2022 03:01:43 +0000
Subject: CTAN sync 202202140301

---
 macros/generic/expkv-cs/expkv-cs.dtx | 186 +++++++++++++++++++++++++++++++++--
 1 file changed, 180 insertions(+), 6 deletions(-)

(limited to 'macros/generic/expkv-cs/expkv-cs.dtx')

diff --git a/macros/generic/expkv-cs/expkv-cs.dtx b/macros/generic/expkv-cs/expkv-cs.dtx
index c975e4931c..561dec7af9 100644
--- a/macros/generic/expkv-cs/expkv-cs.dtx
+++ b/macros/generic/expkv-cs/expkv-cs.dtx
@@ -1,6 +1,6 @@
 % \iffalse meta-comment
 %
-% File: expkv-cs.dtx Copyright (C) 2020-2021 Jonathan P. Spratte
+% File: expkv-cs.dtx Copyright (C) 2020-2022 Jonathan P. Spratte
 %
 % This work  may be  distributed and/or  modified under  the conditions  of the
 % LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
@@ -27,7 +27,7 @@ Released under the LaTeX Project Public License v1.3c or later
 See http://www.latex-project.org/lppl.txt
 --------------------------------------------------------------
 
-Copyright (C) 2020-2021 Jonathan P. Spratte
+Copyright (C) 2020-2022 Jonathan P. Spratte
 
 This  work may be  distributed and/or  modified under  the conditions  of the
 LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
@@ -729,7 +729,7 @@ and the derived files           expkv-cs.pdf
 %
 % \begin{function}{alias}
 %   \begin{syntax}
-%     alias \key\ = \meta{key_2} \prefixes3
+%     alias \key\ = \marg{key_2} \prefixes3
 %   \end{syntax}
 %   This assigns the definition of \meta{key_2} to \key. As a result \key\ is an
 %   alias for \meta{key_2} behaving just the same. Both the value taking and the
@@ -749,6 +749,74 @@ and the derived files           expkv-cs.pdf
 %   \autoref{sec:change} for this). \key\ can be a primary or secondary key.
 % \end{function}
 %
+% \begin{function}{enum}
+%   \begin{syntax}
+%     enum \key\ = \marg{key_2}\{\val, \ldots\} \prefixes2
+%   \end{syntax}
+%   This defines \key\ to only accept the values given in the list of the second
+%   argument of its definition. It forwards the position of \val\ in that list
+%   to \meta{key_2} (zero-based). The \meta{key_2} has to already be defined
+%   by the time an |enum| key is set up. Each \val\ in the list (and at use
+%   time) is treated as a string, so no expansion takes place here.
+%
+%   If you use |enum| twice on the same \key\ the new values will again start at
+%   zero (so it is possible to define multiple values with the same outcome),
+%   however since you can't skip values you'll have to use the same as in the
+%   first call for values with just a single variant. There is no interface to
+%   delete existing values.
+% \end{function}
+% \example First a small example that might give you an idea of what the
+% description above could mean:\\
+% \begin{minipage}[c]{.75\linewidth}
+% \begin{lstlisting}
+% \ekvcSplit\foo{k-internal=-1}{#1}
+% \ekvcSecondaryKeys\foo
+%   {enum k = {k-internal}{a,b,c}}
+% \foo{}\foo{k=a}\foo{k=b}\foo{k=c}
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \ekvcSplit\foo{k-internal=-1}{#1}
+%   \ekvcSecondaryKeys\foo
+%     {enum k = {k-internal}{a,b,c}}
+%   \foo{}\foo{k=a}\foo{k=b}\foo{k=c}
+% \end{exresult}
+% \example We can define a choice setup that might do different things based on
+% the choice encountered, and the numeric value is easy to parse using
+% |\ifcase|:\\
+% \begin{minipage}[c]{.75\linewidth}
+% \begin{lstlisting}
+% \ekvcSplit\foo{k-internal=-1}
+%   {%
+%     \ifcase#1
+%       is\or
+%       This\or
+%       easy%
+%     \else
+%       .%
+%     \fi
+%   }
+% \ekvcSecondaryKeys\foo
+%   {enum k = {k-internal}{a,b,c}}
+% \foo{k=b} \foo{k=a} \foo{k=c}\foo{}
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \ekvcSplit\foo{k-internal=-1}
+%     {^^A
+%       \ifcase#1
+%         is\or
+%         This\or
+%         easy^^A
+%       \else
+%         .^^A
+%       \fi
+%     }
+%   \ekvcSecondaryKeys\foo
+%     {enum k = {k-internal}{a,b,c}}
+%   \foo{k=b} \foo{k=a} \foo{k=c}\foo{}
+% \end{exresult}
+%
 % \begin{function}{aggregate}
 %   \begin{syntax}
 %     aggregate \key\ = \marg{primary}\marg{definition} \prefixes3
@@ -1568,8 +1636,8 @@ and the derived files           expkv-cs.pdf
 % \begin{macro}{\ekvcVersion,\ekvcDate}
 % We're on our first input, so lets store the version and date in a macro.
 %    \begin{macrocode}
-\def\ekvcVersion{1.1b}
-\def\ekvcDate{2021-11-21}
+\def\ekvcVersion{1.2}
+\def\ekvcDate{2022-02-13}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -2656,6 +2724,110 @@ and the derived files           expkv-cs.pdf
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}[internal]{\ekvc@t@enum}
+% \begin{macro}[internal]
+%   {\ekvc@type@enum,\ekvc@h@enum,\ekvc@h@enum@,\ekvc@enum@name}
+%   Enums don't need to apply special trickery to make the parts of the names
+%   retrievable, so unlike in \expkvd\ we don't need catcode juggling.
+%   The setup of an |enum| requires unpacking the value in two different
+%   arguments so we need an auxiliary here.
+%    \begin{macrocode}
+\def\ekvc@enum@name#1#2#3{ekvc#1(#2)#3}
+\protected\long\def\ekvc@t@enum#1#2%
+  {\ekvc@assert@twoargs{#2}{enum #1}{\ekvc@type@enum{#1}#2}}
+\protected\long\def\ekvc@type@enum#1#2%
+  {%
+    \ekvifdefined\ekvc@set{#2}%
+      {%
+%    \end{macrocode}
+%   At run time we need another helper and we need to expand the current
+%   |\ekvc@set| now. The helper will build a control sequence from each given
+%   value, those will be set up in the |\ekvcsvloop|.
+%    \begin{macrocode}
+        \ekvc@long\edef\ekvc@tmp##1%
+          {%
+            \ekv@unexpanded{\expandafter\ekvc@h@enum\detokenize}{##1}%
+            \ekv@unexpanded{\ekvc@stop}%
+            {\ekvc@set}{#1}%
+          }%
+        \ekvlet\ekvc@set{#1}\ekvc@tmp
+        \def\ekvc@tmp{0}%
+        \expandafter\ekvcsvloop\expandafter
+          {%
+            \expandafter\ekvc@type@enum@
+              \csname\ekv@name\ekvc@set{#2}\endcsname
+              {#1}%
+          }%
+      }%
+      {%
+        \ekvc@err@unknown@key{#2}%
+        \@gobble
+      }%
+  }
+%    \end{macrocode}
+%   Here |#1| will be the key-macro of the underlying primary or secondary key,
+%   |#2| is the |enum| key's name, and |#3| will be the choice. The rest is
+%   pretty obvious.
+%    \begin{macrocode}
+\ekv@exparg{\protected\long\def\ekvc@type@enum@#1#2#3}%
+  {%
+    \expandafter\expandafter\expandafter\edef\expandafter
+        \csname\ekvc@enum@name\ekvc@set{#2}{\detokenize{#3}}\endcsname
+      {\ekv@unexpanded{#1}{\ekvc@tmp}}%
+    \edef\ekvc@tmp{\the\numexpr\ekvc@tmp+1\relax}%
+  }
+%    \end{macrocode}
+%   The use-time helper will check if the macro for the passed in choice exists,
+%   if it doesn't throws an error, else calls that macro which will set the
+%   correct value.
+%    \begin{macrocode}
+\ekv@if@lastnamedcs
+  {%
+    \ekv@exparg{\def\ekvc@h@enum#1\ekvc@stop#2#3}%
+      {%
+        \expandafter\ifcsname\ekvc@enum@name{#2}{#3}{#1}\endcsname
+          \expandafter\ekvc@h@enum@\lastnamedcs
+        \fi
+        \ekvc@err@unknown@enum{#2}{#3}{#1}%
+      }
+    \def\ekvc@h@enum@#1\fi\ekvc@err@unknown@enum#2#3#4%
+      {%
+        \fi
+        \ifx#1\relax
+          \ekvc@err@unknown@enum{#2}{#3}{#4}%
+          \expandafter\@gobble
+        \fi
+        #1%
+      }
+  }
+  {%
+    \def\ekvc@h@enum#1%
+      {%
+        \def\ekvc@h@enum##1\ekvc@stop##2##3%
+          {%
+            \expandafter\ekvc@h@enum@
+              \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
+              {##2}{##3}{##1}%
+          }%
+      }
+    \expandafter\ekvc@h@enum\expandafter{\ekvc@enum@name{#2}{#3}{#1}}
+    \def\ekvc@h@enum@#1#2#3#4%
+      {%
+        \ifx#1\relax
+          \ekvc@err@unknown@enum{#2}{#3}{#4}%
+          \expandafter\@gobble
+        \fi
+        #1%
+      }
+  }
+%    \end{macrocode}
+%   We don't need |\ekvc@enum@name| anymore, so let's undefine it.
+%    \begin{macrocode}
+\let\ekvc@enum@name\ekvc@undefined
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \begin{macro}[internal]{\ekvc@t@aggregate}
 %   Aggregating isn't easy to define. We'll have to extract the correct mark for
 %   the specified key, branch correctly for short and long keys, and use a small
@@ -3222,7 +3394,7 @@ and the derived files           expkv-cs.pdf
 % \begin{macro}[internal]
 %   {
 %     \ekvc@err@unknown@hash,\ekvc@err@empty@hash,\ekvc@err@missing@hash,
-%     \ekvc@err@invalid@bool
+%     \ekvc@err@invalid@bool,\ekvc@err@unknown@enum
 %   }
 %   And here are the expandable error messages.
 %    \begin{macrocode}
@@ -3232,6 +3404,8 @@ and the derived files           expkv-cs.pdf
 \def\ekvc@err@invalid@bool#1{\ekvc@err{invalid boolean value `#1'}}
 \long\def\ekvc@err@unknown@key@or@macro#1#2%
   {\ekvc@err{unknown key `#2' for macro #1}}
+\def\ekvc@err@unknown@enum#1#2#3%
+  {\ekvc@err{unknown value `#3' for enum `#2' in macro #1}}
 %    \end{macrocode}
 % \end{macro}
 %
-- 
cgit v1.2.3

