texlive[58852] Master/texmf-dist: expkv-cs (12apr21)

commits+karl at tug.org commits+karl at tug.org
Mon Apr 12 22:04:05 CEST 2021


Revision: 58852
          http://tug.org/svn/texlive?view=revision&revision=58852
Author:   karl
Date:     2021-04-12 22:04:05 +0200 (Mon, 12 Apr 2021)
Log Message:
-----------
expkv-cs (12apr21)

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

Modified: trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md	2021-04-12 18:16:16 UTC (rev 58851)
+++ trunk/Master/texmf-dist/doc/latex/expkv-cs/README.md	2021-04-12 20:04:05 UTC (rev 58852)
@@ -1,7 +1,7 @@
 -------------------------------------------------------------------------------
 # expkv-cs -- define expandable key=val macros using expkv
 
-Version 2020-10-18 v0.6
+Version 2021-04-12 v0.8
 
 Released under the LaTeX Project Public License v1.3c or later
 See http://www.latex-project.org/lppl.txt
@@ -10,7 +10,7 @@
 
 -------------------------------------------------------------------------------
 
-Copyright (C) 2020 Jonathan P. Spratte
+Copyright (C) 2020-2021 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

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

Modified: trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx	2021-04-12 18:16:16 UTC (rev 58851)
+++ trunk/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx	2021-04-12 20:04:05 UTC (rev 58852)
@@ -1,6 +1,6 @@
 % \iffalse meta-comment
 %
-% File: expkv-cs.dtx Copyright (C) 2020 Jonathan P. Spratte
+% File: expkv-cs.dtx Copyright (C) 2020-2021 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 @@
 See http://www.latex-project.org/lppl.txt
 --------------------------------------------------------------
 
-Copyright (C) 2020 Jonathan P. Spratte
+Copyright (C) 2020-2021 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
@@ -164,7 +164,7 @@
   }
 \hypersetup{linkcolor=red!80!black,urlcolor=purple!80!black}
 \DoNotIndex{\def,\edef,\,,\=,\begingroup,\catcode,\chardef,\csname,\endcsname}
-\DoNotIndex{\endgroup,\endinput,\errmessage,\expandafter,\input,\let,\long}
+\DoNotIndex{\endgroup,\endinput,\errmessage,\expandafter,\input,\let,\long,\z@}
 \DoNotIndex{\protected,\ProvidesFile,\ProvidesPackage,\relax,\space,\advance}
 \DoNotIndex{\@,\unexpanded,\string,\expanded,\dimexpr,\global,\glueexpr,\hbox}
 \DoNotIndex{\numexpr,\RequirePackage,\setbox,\the,\unless,\xdef,\gdef,\newcount}
@@ -529,7 +529,152 @@
 %   secondary key.
 % \end{function}
 %
+% \begin{function}{flag-bool}
+%   \begin{syntax}
+%     flag-bool \key\ = \meta{cs} \prefixes3
+%   \end{syntax}
+%   This is a secondary key that doesn't directly involve any of the primary or
+%   secondary keys.
+%   This defines \key\ to take a value, which should be either |true| or
+%   |false|, and set the flag called \meta{cs} accordingly as a boolean.
+%   If \meta{cs} isn't defined yet it will be initialised as a flag.
+%   Please also read \autoref{sec:flags}.
+% \end{function}
 %
+% \begin{function}{flag-true,flag-false}
+%   \begin{syntax}
+%     flag-true \key\ = \meta{cs} \prefixes3
+%   \end{syntax}
+%   This is a secondary key that doesn't directly involve any of the primary or
+%   secondary keys.
+%   This defines \key\ to take no value and set the flag called \meta{cs} to
+%   |true| or |false|, respectively.
+%   If \meta{cs} isn't defined yet it will be initialised as a flag.
+%   Please also read \autoref{sec:flags}.
+% \end{function}
+%
+% \begin{function}{flag-raise}
+%   \begin{syntax}
+%     flag-raise \key\ = \meta{cs} \prefixes3
+%   \end{syntax}
+%   This is a secondary key that doesn't directly involve any of the primary or
+%   secondary keys.
+%   This defines \key\ to take no value and raise the flag called \meta{cs}.
+%   If \meta{cs} isn't defined yet it will be initialised as a flag.
+%   Please also read \autoref{sec:flags}.
+% \end{function}
+%
+%
+% \subsection{Flags}\label{sec:flags}
+%
+% The idea of flags is taken from \pkg{expl3}. They provide a way to store
+% numerical information expandably, however only incrementing and accessing
+% works expandably, decrementing is unexpandable. A flag has a height, which
+% is a numerical value, and which can be raised by $1$. Flags come at a high
+% computational cost (accessing them is slow and they require more memory than
+% normal \TeX\ data types like registers, both getting linearly worse with the
+% height), so don't use them if not necessary.
+%
+% The state of flags is always changed locally to the current group, but not to
+% the current macro, so if you're using one of the |t|-types involving flags
+% bear in mind that they can affect other macros at the current group level!
+%
+% \expkvc\ provides some macros to access, alter, and use flags. Flags of
+% \expkvc\ don't share a name space with the flags of \pkg{expl3}.
+%
+% \begin{function}{\ekvcFlagNew}
+%   \begin{syntax}
+%     \cs{ekvcFlagNew}\meta{flag}
+%   \end{syntax}
+%   This initialises the macro \meta{flag} as a new flag. It isn't checked
+%   whether the macro \meta{flag} is currently undefined.  A \meta{flag} will
+%   expand to the flag's current height with a trailing space (so you can use it
+%   directly with |\ifnum| for example and it will terminate the number scanning
+%   itself).
+% \end{function}
+%
+%  All other macros dealing with flags take as a parameter a macro defined as a
+%  \meta{flag} with |\ekvcFlagNew|.
+%
+% \begin{function}{\ekvcFlagHeight}
+%   \begin{syntax}
+%     \cs{ekvcFlagHeight}\meta{flag}
+%   \end{syntax}
+%   This expands to the current height of \meta{flag} in a single step of
+%   expansion (without a trailing space).
+% \end{function}
+%
+% \begin{function}{\ekvcFlagRaise}
+%   \begin{syntax}
+%     \cs{ekvcFlagRaise}\meta{flag}
+%   \end{syntax}
+%   This expandably raises the height of \meta{flag} by $1$.
+% \end{function}
+%
+% \begin{function}{\ekvcFlagSetTrue,\ekvcFlagSetFalse}
+%   \begin{syntax}
+%     \cs{ekvcFlagSetTrue}\meta{flag}
+%   \end{syntax}
+%   By interpreting an even value as false and an odd value as true we can use a
+%   flag as a boolean. This expandably sets \meta{flag} to true or false,
+%   respectively, by raising it if necessary.
+% \end{function}
+%
+% \begin{function}{\ekvcFlagIf}
+%   \begin{syntax}
+%     \cs{ekvcFlagIf}\meta{flag}\marg{true}\marg{false}
+%   \end{syntax}
+%   This interprets a \meta{flag} as a boolean and expands to either \meta{true}
+%   or \meta{false}.
+% \end{function}
+%
+% \begin{function}{\ekvcFlagIfRaised}
+%   \begin{syntax}
+%     \cs{ekvcFlagIfRaised}\meta{flag}\marg{true}\marg{false}
+%   \end{syntax}
+%   This tests whether the \meta{flag} is raised, meaning it has a height
+%   greater than zero, and if so expands to \meta{true} else to \meta{false}.
+% \end{function}
+%
+% \begin{function}{\ekvcFlagReset}
+%   \begin{syntax}
+%     \cs{ekvcFlagReset}\meta{flag}
+%   \end{syntax}
+%   This resets a flag (so restores its height to $0$). This operation is
+%   \emph{not} expandable and done locally. If you really intend to use flags
+%   you can reset them every now and then to keep the performance hit low.
+% \end{function}
+%
+% \begin{function}{\ekvcFlagGetHeight}
+%   \begin{syntax}
+%     \cs{ekvcFlagGetHeight}\meta{flag}\marg{next}
+%   \end{syntax}
+%   This retrieves the current height of the \meta{flag} and provides it as a
+%   braced argument to \meta{next}, leaving \meta{next}\marg{height} in the
+%   input stream.
+% \end{function}
+%
+% \begin{function}{\ekvcFlagGetHeights}
+%   \begin{syntax}
+%     \cs{ekvcFlagGetHeights}\marg{flag-list}\marg{next}
+%   \end{syntax}
+%   This retrieves the current height of each \meta{flag} in the
+%   \meta{flag-list} and provides them as a single argument to \meta{next}.
+%   Inside that argument each height is enclosed in a set of braces
+%   individually. The \meta{flag-list} is just a single argument containing the
+%   \meta{flag}s.
+%   So a usage like
+%   \texttt
+%     {^^A
+%       \cs[no-index]{ekvcFlagGetHeights}\hskip0pt^^A
+%       \{\cs[no-index]{myflagA}\cs[no-index]{myflagB}\}\hskip0pt^^A
+%       \{\cs[no-index]{stuff}\}^^A
+%     }
+%   will expand to
+%   \texttt{\cs[no-index]{stuff}\{\marg{height-A}\marg{height-B}\}}.
+% \end{function}
+%
+%
 % \subsection{Example}
 %
 % How could a documentation be a good documentation without some basic examples?
@@ -692,7 +837,7 @@
 % Just in case you're wondering now, a simple macro taking seven arguments is
 % $30$ to $40$ times faster than any of those in the argument grabbing and \kv\
 % parsing part and only $1.5$ to $2.8$ times faster if the typesetting part is
-% factored in. So the real choke isn't the parsing. 
+% factored in. So the real choke isn't the parsing.
 %
 % So to summarize this, if you have a reasonable use case for expandable \kv\
 % parsing macros you should go on and define them using \expkvc. If you have a
@@ -800,8 +945,8 @@
 % \begin{macro}{\ekvcVersion,\ekvcDate}
 % We're on our first input, so lets store the version and date in a macro.
 %    \begin{macrocode}
-\def\ekvcVersion{0.6}
-\def\ekvcDate{2020-10-18}
+\def\ekvcVersion{0.8}
+\def\ekvcDate{2021-04-12}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -824,17 +969,16 @@
 % \begin{macro}[internal]{\ekvc at zero}
 %   There are different ways to define a |\romannumeral| expansion. If the
 %   control is never given to user input, the fastest way is to just execute
-%   your code and use a |\chardef|ed zero to end it afterwards.  If the control
+%   your code and use a |\dimendef|ed zero to end it afterwards.  If the control
 %   is given to user input (so user input should be expanded) the fastest and
 %   best way is to use |\romannumeral`\^^@|, this will expand the user input
 %   until something unexpandable is found or a space (which would then be
 %   gobbled). However, we want to use the former approach since we don't want to
 %   expand any user input, just make sure own code is expanded in two steps.
-%   Since we want to use the |\chardef| variant, we have to actually provide
-%   such a token.
-%    \begin{macrocode}
-\chardef\ekvc at zero0
-%    \end{macrocode}
+%   Since we want to use the |\dimendef| variant, we have to actually provide
+%   such a token. Since both plain \TeX\ and \LaTeX\ define |\z@| we can use
+%   that (but we use a private name for it). Luckily, \expkv\ already contains
+%   |\ekv at zero|, which we can use in \expkvc.
 % \end{macro}
 %
 % \begin{macro}[internal]{\ekvc at keycount}
@@ -856,9 +1000,9 @@
 %
 % \begin{macro}[internal]
 %   {
-%     \ekvc at ekvset@per at expander,
-%     \ekvc at ekvset@per at expander@a,
-%     \ekvc at ekvset@per at expander@b
+%     \ekvc at ekvset@pre at expander,
+%     \ekvc at ekvset@pre at expander@a,
+%     \ekvc at ekvset@pre at expander@b
 %   }
 %   This macro expands |\ekvset| twice so that the first two steps of expansion
 %   don't have to be made every time the \expkvc\ macros are used. We have to do
@@ -1394,10 +1538,10 @@
                   ####1%
                 {%
                   \unexpanded\expandafter{\csname ekvc@@safehash@#1\endcsname}%
-                  ####1\unexpanded{\ekvc at mark\ekvc at zero}%
+                  ####1\unexpanded{\ekvc at mark\ekv at zero}%
                   \unexpanded\expandafter
                     {%
-                      \csname ekvc at hashmark@#1\endcsname\ekvc at zero
+                      \csname ekvc at hashmark@#1\endcsname\ekv at zero
                       \ekvc at mark{\ekvc at err@missing at hash{#1}}\ekvc at stop
                     }%
                 }%
@@ -1458,7 +1602,7 @@
     \romannumeral
     \ekv at ifdefined{ekvc at safehash@#1}%
       {\csname ekvc at safehash@#1\endcsname}%
-      {\ekvc at err@unknown at hash{#1}\@firstoftwo\ekvc at zero}%
+      {\ekvc at err@unknown at hash{#1}\@firstoftwo\ekv at zero}%
   }
 %    \end{macrocode}
 % \end{macro}
@@ -1524,7 +1668,7 @@
 %   thrown by |\ekvcValueFast| in three expansion steps. The safe hash variant
 %   has to also stop the |\romannumeral| expansion.
 %    \begin{macrocode}
-\long\def\ekvc at safehash@#1{\ekvc at err@empty at hash\ekvc at zero}
+\long\def\ekvc at safehash@#1{\ekvc at err@empty at hash\ekv at zero}
 \long\def\ekvc at fasthash@#1\ekvc at stop{\ekvc at err@empty at hash}
 \long\def\ekvc at safesplithash@#1#2{\ekvc at err@empty at hash#2{#1}{}}
 \long\def\ekvc at fastsplithash@#1\ekvc at stop#2{\ekvc at err@empty at hash#2{#1}{}}
@@ -1668,7 +1812,259 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}[internal]{\ekvc at t@flag-bool}
+%    \begin{macrocode}
+\protected\expandafter\def\csname ekvc at t@flag-bool\endcsname#1#2%
+  {%
+    \ekvc at assert@not at long{flag-bool #1}%
+    \unless\ifdefined#2\ekvcFlagNew#2\fi
+    \ekvdef\ekvc at set{#1}%
+      {%
+        \ekv at ifdefined{ekvc at flag@set@##1}%
+          {%
+            \csname ekvc at flag@set@##1\expandafter\endcsname
+              \ekvcFlagHeight#2\ekv at stop#2%
+          }%
+          {\ekvc at err@invalid at bool{##1}}%
+      }%
+  }
+%    \end{macrocode}
+% \end{macro}
 %
+% \begin{macro}[internal]
+%   {\ekvc at t@flag-true,\ekvc at t@flag-false,\ekvc at t@flag-raise,\ekvc at type@flag}
+%    \begin{macrocode}
+\protected\def\ekvc at type@flag#1#2#3#4%
+  {%
+    \ekvc at assert@not at long{flag-#1 #3}%
+    \unless\ifdefined#4\ekvcFlagNew#4\fi
+    \ekv at exparg{\ekvdefNoVal\ekvc at set{#3}}{#2#4}%
+  }
+\protected\expandafter\def\csname ekvc at t@flag-true\endcsname
+  {\ekvc at type@flag{true}\ekvcFlagSetTrue}
+\protected\expandafter\def\csname ekvc at t@flag-false\endcsname
+  {\ekvc at type@flag{false}\ekvcFlagSetFalse}
+\protected\expandafter\def\csname ekvc at t@flag-raise\endcsname
+  {\ekvc at type@flag{raise}\ekvcFlagRaise}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Flags}
+%
+% The basic idea of flags is to store information by the fact that \TeX\
+% expandably assigns the meaning |\relax| to undefined control sequences which
+% were built with |\csname|. This mechanism is borrowed from \pkg{expl3}.
+%
+% \begin{macro}[internal]{\ekvc at flag@name,\ekvc at flag@namescheme}
+%   Flags follow a simple naming scheme which we define here. |\ekvc at flag@name|
+%   will store the name of an internal function that is used to build names of
+%   the second naming scheme defined by |\ekvc at flag@namescheme|.
+%    \begin{macrocode}
+\def\ekvc at flag@name{ekvcf\string}
+\def\ekvc at flag@namescheme#1#2{ekvch#2#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagHeight}
+%   For semantic reasons we use |\number| with another name.
+%    \begin{macrocode}
+\let\ekvcFlagHeight\number
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagNew}
+%   This macro defines a new flag. It stores the function build with the
+%   |\ekvc at flag@name| naming scheme after the internal function
+%   |\ekvc at flag@height| that'll determine the current flag height. It'll also
+%   define the macro named via |\ekvc at flag@name| to build names according to
+%   |\ekvc at flag@namescheme|.
+%    \begin{macrocode}
+\protected\def\ekvcFlagNew#1%
+  {%
+    \edef#1%
+      {%
+        \unexpanded{\ekvc at flag@height}%
+          \unexpanded\expandafter{\csname\ekvc at flag@name#1\endcsname}%
+      }%
+    \ekv at expargtwice
+      {\expandafter\def\csname\ekvc at flag@name#1\endcsname##1}%
+      {\expandafter\ekvc at flag@namescheme\expandafter{\string#1}{##1}}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc at flag@height,\ekvc at flag@height@}
+%   This macro gets the height of a flag by a simple loop. The first loop
+%   iteration differs a bit from the following in that it doesn't have to get
+%   the current iteration count. The space at the end of |\ekvc at flag@height|
+%   ends the |\number| evaluation.
+%    \begin{macrocode}
+\def\ekvc at flag@height#1%
+  {%
+    \ifcsname#10\endcsname
+      \ekvc at flag@height at 1\ekv at stop#1%
+    \fi
+    \@firstofone{0} % leave this space
+  }
+\def\ekvc at flag@height@#1\ekv at stop#2\fi\@firstofone#3%
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      \expandafter\ekvc at flag@height@\the\numexpr#1+1\relax\ekv at stop#2%
+    \fi
+    \@firstofone{#1}%
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagRaise}
+%   Raising a flag simply means letting the |\ekvc at flag@namescheme| macro for
+%   the current height to relax. The result of raising a flag is that its height
+%   is bigger by $1$.
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvcFlagRaise#1}%
+  {%
+    \expandafter\expandafter\expandafter\@gobble\expandafter
+      \csname\ekvc at flag@namescheme{\string#1}{\ekvcFlagHeight#1}\endcsname
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagSetTrue,\ekvcFlagSetFalse}
+% \begin{macro}[internal]{\ekvc at flag@set at true,\ekvc at flag@set at false}
+%   A flag is considered true if its current height is odd, and as false if it
+%   is even. Therefore |\ekvcFlagSetTrue| and |\ekvcFlagSetFalse| only need to
+%   raise the flag if the opposing boolean value is the current one.
+%    \begin{macrocode}
+\def\ekvcFlagSetTrue#1%
+  {\expandafter\ekvc at flag@set at true\ekvcFlagHeight#1\ekv at stop#1}
+\def\ekvcFlagSetFalse#1%
+  {\expandafter\ekvc at flag@set at false\ekvcFlagHeight#1\ekv at stop#1}
+%    \end{macrocode}
+%   We can expand |\ekvc at flag@namescheme| at definition time here, which is why
+%   we're using a temporary definition to set up |\ekvc at flag@set at true| and
+%   |\ekvc at flag@set at false|.
+%    \begin{macrocode}
+\def\ekvc at flag@set at true#1%
+  {%
+    \def\ekvc at flag@set at true##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@gobble
+        \fi
+        \@firstofone{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+    \def\ekvc at flag@set at false##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@firstofone
+        \fi
+        \@gobble{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+  }
+\expandafter\ekvc at flag@set at true\expandafter
+  {\ekvc at flag@namescheme{\string#2}{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagIf}
+%   As already explained, truthiness is defined as a flag's height is odd, so we
+%   just branch accordingly here.
+%    \begin{macrocode}
+\def\ekvcFlagIf#1%
+  {%
+    \ifodd#1%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagIfRaised}
+%   This macro uses flags as a switch, if a flag's current height is bigger than
+%   $0$ this test yields true.
+%    \begin{macrocode}
+\ekv at exparg{\def\ekvcFlagIfRaised#1}%
+  {%
+    \expandafter\ifcsname\ekvc at flag@namescheme{\string#1}0\endcsname
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagReset}
+% \begin{macro}[internal]{\ekvc at flag@reset,\ekvc at flag@reset@}
+%   Resetting works by locally letting all the defined internal macros named
+%   after |\ekvc at flag@namescheme| to undefined.
+%    \begin{macrocode}
+\protected\def\ekvcFlagReset#1%
+  {\expandafter\ekvc at flag@reset\csname\ekvc at flag@name#1\endcsname}
+\protected\def\ekvc at flag@reset#1%
+  {%
+    \ifcsname#10\endcsname
+      \expandafter\let\csname#10\endcsname\ekvc at undefined
+      \ekvc at flag@reset at 1\ekv at stop#1%
+    \fi
+  }
+\protected\def\ekvc at flag@reset@#1\ekv at stop#2\fi
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      \expandafter\let\csname#2{#1}\endcsname\ekvc at undefined
+      \expandafter\ekvc at flag@reset@\the\numexpr#1+1\relax\ekv at stop#2%
+    \fi
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagGetHeight}
+% \begin{macro}[internal]{\ekvc at flag@get at height@single}
+%   These are just small helpers, first getting the height of the flag and then
+%   passing it on to the user supplied code.
+%    \begin{macrocode}
+\def\ekvcFlagGetHeight#1%
+  {\expandafter\ekvc at flag@get at height@single\ekvcFlagHeight#1\ekv at stop}
+\long\def\ekvc at flag@get at height@single#1\ekv at stop#2{#2{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagGetHeights}
+% \begin{macro}[internal]
+%   {\ekvc at flag@get at heights,\ekvc at flag@get at heights@,\ekvc at flag@get at heights@done}
+%   This works by a simple loop that stops at |\ekv at stop|. As long as that
+%   marker isn't hit, get the next flags height and put it into a list after
+%   |\ekv at stop|. |\ekvc at flag@get at heights@| uses the same marker name for the
+%   end of the height, which shouldn't clash in any case. Once we're done we
+%   remove the remainder of the current iteration and leave the user supplied
+%   code in the input stream with all the flags' heights as a single argument.
+%    \begin{macrocode}
+\def\ekvcFlagGetHeights#1%
+  {%
+    \ekvc at flag@get at heights#1\ekv at stop{}%
+  }
+\def\ekvc at flag@get at heights#1%
+  {%
+    \ekv at gobbleto@stop#1\ekvc at flag@get at heights@done\ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight#1\ekv at stop
+  }
+\def\ekvc at flag@get at heights@#1\ekv at stop#2\ekv at stop#3%
+  {\ekvc at flag@get at heights#2\ekv at stop{#3{#1}}}
+\long\def\ekvc at flag@get at heights@done
+    \ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight\ekv at stop\ekv at stop#1#2%
+  {#2{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
 % \subsubsection{Helper Macros}
 %
 % \begin{macro}[internal]{\ekvc at ifspace,\ekvc at ifspace@}
@@ -1744,29 +2140,26 @@
 % \begin{macro}[internal]{\ekvc at err,\ekvc at err@}
 %   We need a way to throw error messages expandably in some contexts.
 %    \begin{macrocode}
-\begingroup
-\edef\ekvc at err
+\def\ekvc at err#1%
   {%
-    \endgroup
-    \unexpanded{\long\def\ekvc at err}##1%
-      {%
-        \unexpanded{\expandafter\ekvc at err@\@firstofone}%
-        {\unexpanded\expandafter{\csname ! expkv-cs Error:\endcsname}##1.}%
-        \unexpanded{\ekv at stop}%
-      }%
+    \long\def\ekvc at err##1{\expandafter\ekv at err@\@firstofone{#1##1.}\ekv at stop}%
   }
-\ekvc at err
-\def\ekvc at err@{\expandafter\ekv at gobbleto@stop}
+\begingroup\expandafter\endgroup
+\expandafter\ekvc at err\csname ! expkv-cs Error:\endcsname
 %    \end{macrocode}
 % \end{macro}
 %
 % \begin{macro}[internal]
-%   {\ekvc at err@unknown at hash,\ekvc at err@empty at hash,\ekvc at err@missing at hash}
+%   {
+%     \ekvc at err@unknown at hash,\ekvc at err@empty at hash,\ekvc at err@missing at hash,
+%     \ekvc at err@invalid at bool
+%   }
 %   And here are the expandable error messages.
 %    \begin{macrocode}
 \long\def\ekvc at err@unknown at hash#1{\ekvc at err{unknown hash `#1'}}
 \long\def\ekvc at err@missing at hash#1{\ekvc at err{hash `#1' not found}}
 \long\def\ekvc at err@empty at hash{\ekvc at err{empty hash}}
+\def\ekvc at err@invalid at bool#1{\ekvc at err{invalid boolean value `#1'}}
 %    \end{macrocode}
 % \end{macro}
 %

Modified: trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex	2021-04-12 18:16:16 UTC (rev 58851)
+++ trunk/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex	2021-04-12 20:04:05 UTC (rev 58852)
@@ -13,7 +13,7 @@
 %% See http://www.latex-project.org/lppl.txt
 %% --------------------------------------------------------------
 %% 
-%% Copyright (C) 2020 Jonathan P. Spratte
+%% Copyright (C) 2020-2021 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
@@ -35,12 +35,11 @@
 \else
   \expandafter\endinput
 \fi
-\def\ekvcVersion{0.6}
-\def\ekvcDate{2020-10-18}
+\def\ekvcVersion{0.8}
+\def\ekvcDate{2021-04-12}
 \csname ekvc at tmp\endcsname
 \expandafter\chardef\csname ekvc at tmp\endcsname=\catcode`\@
 \catcode`\@=11
-\chardef\ekvc at zero0
 \newcount\ekvc at keycount
 \def\ekvc at long{}
 \def\ekvc at any@long{}
@@ -398,10 +397,10 @@
                   ####1%
                 {%
                   \unexpanded\expandafter{\csname ekvc@@safehash@#1\endcsname}%
-                  ####1\unexpanded{\ekvc at mark\ekvc at zero}%
+                  ####1\unexpanded{\ekvc at mark\ekv at zero}%
                   \unexpanded\expandafter
                     {%
-                      \csname ekvc at hashmark@#1\endcsname\ekvc at zero
+                      \csname ekvc at hashmark@#1\endcsname\ekv at zero
                       \ekvc at mark{\ekvc at err@missing at hash{#1}}\ekvc at stop
                     }%
                 }%
@@ -454,7 +453,7 @@
     \romannumeral
     \ekv at ifdefined{ekvc at safehash@#1}%
       {\csname ekvc at safehash@#1\endcsname}%
-      {\ekvc at err@unknown at hash{#1}\@firstoftwo\ekvc at zero}%
+      {\ekvc at err@unknown at hash{#1}\@firstoftwo\ekv at zero}%
   }
 \long\def\ekvcValueFast#1#2{\csname ekvc at fasthash@#1\endcsname#2\ekvc at stop}
 \long\def\ekvcValueSplit#1%
@@ -479,7 +478,7 @@
   {%
     \csname ekvc at fastsplithash@#1\endcsname#2\ekvc at stop
   }
-\long\def\ekvc at safehash@#1{\ekvc at err@empty at hash\ekvc at zero}
+\long\def\ekvc at safehash@#1{\ekvc at err@empty at hash\ekv at zero}
 \long\def\ekvc at fasthash@#1\ekvc at stop{\ekvc at err@empty at hash}
 \long\def\ekvc at safesplithash@#1#2{\ekvc at err@empty at hash#2{#1}{}}
 \long\def\ekvc at fastsplithash@#1\ekvc at stop#2{\ekvc at err@empty at hash#2{#1}{}}
@@ -577,6 +576,138 @@
       }%
       {\ekvc at err@unknown at key{#1}}%
   }
+\protected\expandafter\def\csname ekvc at t@flag-bool\endcsname#1#2%
+  {%
+    \ekvc at assert@not at long{flag-bool #1}%
+    \unless\ifdefined#2\ekvcFlagNew#2\fi
+    \ekvdef\ekvc at set{#1}%
+      {%
+        \ekv at ifdefined{ekvc at flag@set@##1}%
+          {%
+            \csname ekvc at flag@set@##1\expandafter\endcsname
+              \ekvcFlagHeight#2\ekv at stop#2%
+          }%
+          {\ekvc at err@invalid at bool{##1}}%
+      }%
+  }
+\protected\def\ekvc at type@flag#1#2#3#4%
+  {%
+    \ekvc at assert@not at long{flag-#1 #3}%
+    \unless\ifdefined#4\ekvcFlagNew#4\fi
+    \ekv at exparg{\ekvdefNoVal\ekvc at set{#3}}{#2#4}%
+  }
+\protected\expandafter\def\csname ekvc at t@flag-true\endcsname
+  {\ekvc at type@flag{true}\ekvcFlagSetTrue}
+\protected\expandafter\def\csname ekvc at t@flag-false\endcsname
+  {\ekvc at type@flag{false}\ekvcFlagSetFalse}
+\protected\expandafter\def\csname ekvc at t@flag-raise\endcsname
+  {\ekvc at type@flag{raise}\ekvcFlagRaise}
+\def\ekvc at flag@name{ekvcf\string}
+\def\ekvc at flag@namescheme#1#2{ekvch#2#1}
+\let\ekvcFlagHeight\number
+\protected\def\ekvcFlagNew#1%
+  {%
+    \edef#1%
+      {%
+        \unexpanded{\ekvc at flag@height}%
+          \unexpanded\expandafter{\csname\ekvc at flag@name#1\endcsname}%
+      }%
+    \ekv at expargtwice
+      {\expandafter\def\csname\ekvc at flag@name#1\endcsname##1}%
+      {\expandafter\ekvc at flag@namescheme\expandafter{\string#1}{##1}}%
+  }
+\def\ekvc at flag@height#1%
+  {%
+    \ifcsname#10\endcsname
+      \ekvc at flag@height at 1\ekv at stop#1%
+    \fi
+    \@firstofone{0} % leave this space
+  }
+\def\ekvc at flag@height@#1\ekv at stop#2\fi\@firstofone#3%
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      \expandafter\ekvc at flag@height@\the\numexpr#1+1\relax\ekv at stop#2%
+    \fi
+    \@firstofone{#1}%
+  }
+\ekv at exparg{\def\ekvcFlagRaise#1}%
+  {%
+    \expandafter\expandafter\expandafter\@gobble\expandafter
+      \csname\ekvc at flag@namescheme{\string#1}{\ekvcFlagHeight#1}\endcsname
+  }
+\def\ekvcFlagSetTrue#1%
+  {\expandafter\ekvc at flag@set at true\ekvcFlagHeight#1\ekv at stop#1}
+\def\ekvcFlagSetFalse#1%
+  {\expandafter\ekvc at flag@set at false\ekvcFlagHeight#1\ekv at stop#1}
+\def\ekvc at flag@set at true#1%
+  {%
+    \def\ekvc at flag@set at true##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@gobble
+        \fi
+        \@firstofone{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+    \def\ekvc at flag@set at false##1\ekv at stop##2%
+      {%
+        \ifodd##1
+          \ekv at fi@firstofone
+        \fi
+        \@gobble{\expandafter\@gobble\csname#1\endcsname}%
+      }%
+  }
+\expandafter\ekvc at flag@set at true\expandafter
+  {\ekvc at flag@namescheme{\string#2}{#1}}
+\def\ekvcFlagIf#1%
+  {%
+    \ifodd#1%
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+\ekv at exparg{\def\ekvcFlagIfRaised#1}%
+  {%
+    \expandafter\ifcsname\ekvc at flag@namescheme{\string#1}0\endcsname
+      \ekv at fi@firstoftwo
+    \fi
+    \@secondoftwo
+  }
+\protected\def\ekvcFlagReset#1%
+  {\expandafter\ekvc at flag@reset\csname\ekvc at flag@name#1\endcsname}
+\protected\def\ekvc at flag@reset#1%
+  {%
+    \ifcsname#10\endcsname
+      \expandafter\let\csname#10\endcsname\ekvc at undefined
+      \ekvc at flag@reset at 1\ekv at stop#1%
+    \fi
+  }
+\protected\def\ekvc at flag@reset@#1\ekv at stop#2\fi
+  {%
+    \fi
+    \ifcsname#2{#1}\endcsname
+      \expandafter\let\csname#2{#1}\endcsname\ekvc at undefined
+      \expandafter\ekvc at flag@reset@\the\numexpr#1+1\relax\ekv at stop#2%
+    \fi
+  }
+\def\ekvcFlagGetHeight#1%
+  {\expandafter\ekvc at flag@get at height@single\ekvcFlagHeight#1\ekv at stop}
+\long\def\ekvc at flag@get at height@single#1\ekv at stop#2{#2{#1}}
+\def\ekvcFlagGetHeights#1%
+  {%
+    \ekvc at flag@get at heights#1\ekv at stop{}%
+  }
+\def\ekvc at flag@get at heights#1%
+  {%
+    \ekv at gobbleto@stop#1\ekvc at flag@get at heights@done\ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight#1\ekv at stop
+  }
+\def\ekvc at flag@get at heights@#1\ekv at stop#2\ekv at stop#3%
+  {\ekvc at flag@get at heights#2\ekv at stop{#3{#1}}}
+\long\def\ekvc at flag@get at heights@done
+    \ekv at stop
+    \expandafter\ekvc at flag@get at heights@\ekvcFlagHeight\ekv at stop\ekv at stop#1#2%
+  {#2{#1}}
 \long\def\ekvc at ifspace#1%
   {%
     \ekvc at ifspace@#1 \ekv at ifempty@B
@@ -618,22 +749,16 @@
     \errmessage
       {expkv-cs Error: Unknown key `\unexpanded{#1}' for macro `\ekvc at set'}%
   }
-\begingroup
-\edef\ekvc at err
+\def\ekvc at err#1%
   {%
-    \endgroup
-    \unexpanded{\long\def\ekvc at err}##1%
-      {%
-        \unexpanded{\expandafter\ekvc at err@\@firstofone}%
-        {\unexpanded\expandafter{\csname ! expkv-cs Error:\endcsname}##1.}%
-        \unexpanded{\ekv at stop}%
-      }%
+    \long\def\ekvc at err##1{\expandafter\ekv at err@\@firstofone{#1##1.}\ekv at stop}%
   }
-\ekvc at err
-\def\ekvc at err@{\expandafter\ekv at gobbleto@stop}
+\begingroup\expandafter\endgroup
+\expandafter\ekvc at err\csname ! expkv-cs Error:\endcsname
 \long\def\ekvc at err@unknown at hash#1{\ekvc at err{unknown hash `#1'}}
 \long\def\ekvc at err@missing at hash#1{\ekvc at err{hash `#1' not found}}
 \long\def\ekvc at err@empty at hash{\ekvc at err{empty hash}}
+\def\ekvc at err@invalid at bool#1{\ekvc at err{invalid boolean value `#1'}}
 \catcode`\@=\ekvc at tmp
 %% 
 %%

Modified: trunk/Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty	2021-04-12 18:16:16 UTC (rev 58851)
+++ trunk/Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty	2021-04-12 20:04:05 UTC (rev 58852)
@@ -13,7 +13,7 @@
 %% See http://www.latex-project.org/lppl.txt
 %% --------------------------------------------------------------
 %% 
-%% Copyright (C) 2020 Jonathan P. Spratte
+%% Copyright (C) 2020-2021 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



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