summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-04-12 20:04:05 +0000
committerKarl Berry <karl@freefriends.org>2021-04-12 20:04:05 +0000
commit6c15c4fc80a80df5104f2e9214a877d5da3a3284 (patch)
treec19f73126e8851f04258a4d24831f35ae8fdf008
parenteed1d7f91a0e98822a578b11eb0319fc4d5c3f3e (diff)
expkv-cs (12apr21)
git-svn-id: svn://tug.org/texlive/trunk@58852 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/expkv-cs/README.md4
-rw-r--r--Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdfbin321681 -> 346046 bytes
-rw-r--r--Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx455
-rw-r--r--Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex163
-rw-r--r--Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty2
5 files changed, 571 insertions, 53 deletions
diff --git a/Master/texmf-dist/doc/latex/expkv-cs/README.md b/Master/texmf-dist/doc/latex/expkv-cs/README.md
index 704f877adf1..5b56601a5db 100644
--- a/Master/texmf-dist/doc/latex/expkv-cs/README.md
+++ b/Master/texmf-dist/doc/latex/expkv-cs/README.md
@@ -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 @@ Hosted at https://github.com/Skillmon/tex_expkv-cs
-------------------------------------------------------------------------------
-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
diff --git a/Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdf b/Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdf
index d8b76f5514b..f498bcb2989 100644
--- a/Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdf
+++ b/Master/texmf-dist/doc/latex/expkv-cs/expkv-cs.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx b/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
index 7dd4c6aad6f..5847a4980be 100644
--- a/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
+++ b/Master/texmf-dist/source/latex/expkv-cs/expkv-cs.dtx
@@ -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 @@ Released under the LaTeX Project Public License v1.3c or later
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 @@ and the derived files expkv-cs.pdf
}
\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,6 +529,151 @@ and the derived files expkv-cs.pdf
% 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}
%
@@ -692,7 +837,7 @@ and the derived files expkv-cs.pdf
% 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 @@ 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{0.6}
-\def\ekvcDate{2020-10-18}
+\def\ekvcVersion{0.8}
+\def\ekvcDate{2021-04-12}
% \end{macrocode}
% \end{macro}
%
@@ -824,17 +969,16 @@ and the derived files expkv-cs.pdf
% \begin{macro}[internal]{\ekvc@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@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@zero|, which we can use in \expkvc.
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@keycount}
@@ -856,9 +1000,9 @@ and the derived files expkv-cs.pdf
%
% \begin{macro}[internal]
% {
-% \ekvc@ekvset@per@expander,
-% \ekvc@ekvset@per@expander@a,
-% \ekvc@ekvset@per@expander@b
+% \ekvc@ekvset@pre@expander,
+% \ekvc@ekvset@pre@expander@a,
+% \ekvc@ekvset@pre@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 @@ and the derived files expkv-cs.pdf
####1%
{%
\unexpanded\expandafter{\csname ekvc@@safehash@#1\endcsname}%
- ####1\unexpanded{\ekvc@mark\ekvc@zero}%
+ ####1\unexpanded{\ekvc@mark\ekv@zero}%
\unexpanded\expandafter
{%
- \csname ekvc@hashmark@#1\endcsname\ekvc@zero
+ \csname ekvc@hashmark@#1\endcsname\ekv@zero
\ekvc@mark{\ekvc@err@missing@hash{#1}}\ekvc@stop
}%
}%
@@ -1458,7 +1602,7 @@ and the derived files expkv-cs.pdf
\romannumeral
\ekv@ifdefined{ekvc@safehash@#1}%
{\csname ekvc@safehash@#1\endcsname}%
- {\ekvc@err@unknown@hash{#1}\@firstoftwo\ekvc@zero}%
+ {\ekvc@err@unknown@hash{#1}\@firstoftwo\ekv@zero}%
}
% \end{macrocode}
% \end{macro}
@@ -1524,7 +1668,7 @@ and the derived files expkv-cs.pdf
% thrown by |\ekvcValueFast| in three expansion steps. The safe hash variant
% has to also stop the |\romannumeral| expansion.
% \begin{macrocode}
-\long\def\ekvc@safehash@#1{\ekvc@err@empty@hash\ekvc@zero}
+\long\def\ekvc@safehash@#1{\ekvc@err@empty@hash\ekv@zero}
\long\def\ekvc@fasthash@#1\ekvc@stop{\ekvc@err@empty@hash}
\long\def\ekvc@safesplithash@#1#2{\ekvc@err@empty@hash#2{#1}{}}
\long\def\ekvc@fastsplithash@#1\ekvc@stop#2{\ekvc@err@empty@hash#2{#1}{}}
@@ -1668,6 +1812,258 @@ and the derived files expkv-cs.pdf
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[internal]{\ekvc@t@flag-bool}
+% \begin{macrocode}
+\protected\expandafter\def\csname ekvc@t@flag-bool\endcsname#1#2%
+ {%
+ \ekvc@assert@not@long{flag-bool #1}%
+ \unless\ifdefined#2\ekvcFlagNew#2\fi
+ \ekvdef\ekvc@set{#1}%
+ {%
+ \ekv@ifdefined{ekvc@flag@set@##1}%
+ {%
+ \csname ekvc@flag@set@##1\expandafter\endcsname
+ \ekvcFlagHeight#2\ekv@stop#2%
+ }%
+ {\ekvc@err@invalid@bool{##1}}%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvc@t@flag-true,\ekvc@t@flag-false,\ekvc@t@flag-raise,\ekvc@type@flag}
+% \begin{macrocode}
+\protected\def\ekvc@type@flag#1#2#3#4%
+ {%
+ \ekvc@assert@not@long{flag-#1 #3}%
+ \unless\ifdefined#4\ekvcFlagNew#4\fi
+ \ekv@exparg{\ekvdefNoVal\ekvc@set{#3}}{#2#4}%
+ }
+\protected\expandafter\def\csname ekvc@t@flag-true\endcsname
+ {\ekvc@type@flag{true}\ekvcFlagSetTrue}
+\protected\expandafter\def\csname ekvc@t@flag-false\endcsname
+ {\ekvc@type@flag{false}\ekvcFlagSetFalse}
+\protected\expandafter\def\csname ekvc@t@flag-raise\endcsname
+ {\ekvc@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@flag@name,\ekvc@flag@namescheme}
+% Flags follow a simple naming scheme which we define here. |\ekvc@flag@name|
+% will store the name of an internal function that is used to build names of
+% the second naming scheme defined by |\ekvc@flag@namescheme|.
+% \begin{macrocode}
+\def\ekvc@flag@name{ekvcf\string}
+\def\ekvc@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@flag@name| naming scheme after the internal function
+% |\ekvc@flag@height| that'll determine the current flag height. It'll also
+% define the macro named via |\ekvc@flag@name| to build names according to
+% |\ekvc@flag@namescheme|.
+% \begin{macrocode}
+\protected\def\ekvcFlagNew#1%
+ {%
+ \edef#1%
+ {%
+ \unexpanded{\ekvc@flag@height}%
+ \unexpanded\expandafter{\csname\ekvc@flag@name#1\endcsname}%
+ }%
+ \ekv@expargtwice
+ {\expandafter\def\csname\ekvc@flag@name#1\endcsname##1}%
+ {\expandafter\ekvc@flag@namescheme\expandafter{\string#1}{##1}}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvc@flag@height,\ekvc@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@flag@height|
+% ends the |\number| evaluation.
+% \begin{macrocode}
+\def\ekvc@flag@height#1%
+ {%
+ \ifcsname#10\endcsname
+ \ekvc@flag@height@1\ekv@stop#1%
+ \fi
+ \@firstofone{0} % leave this space
+ }
+\def\ekvc@flag@height@#1\ekv@stop#2\fi\@firstofone#3%
+ {%
+ \fi
+ \ifcsname#2{#1}\endcsname
+ \expandafter\ekvc@flag@height@\the\numexpr#1+1\relax\ekv@stop#2%
+ \fi
+ \@firstofone{#1}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagRaise}
+% Raising a flag simply means letting the |\ekvc@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@exparg{\def\ekvcFlagRaise#1}%
+ {%
+ \expandafter\expandafter\expandafter\@gobble\expandafter
+ \csname\ekvc@flag@namescheme{\string#1}{\ekvcFlagHeight#1}\endcsname
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagSetTrue,\ekvcFlagSetFalse}
+% \begin{macro}[internal]{\ekvc@flag@set@true,\ekvc@flag@set@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@flag@set@true\ekvcFlagHeight#1\ekv@stop#1}
+\def\ekvcFlagSetFalse#1%
+ {\expandafter\ekvc@flag@set@false\ekvcFlagHeight#1\ekv@stop#1}
+% \end{macrocode}
+% We can expand |\ekvc@flag@namescheme| at definition time here, which is why
+% we're using a temporary definition to set up |\ekvc@flag@set@true| and
+% |\ekvc@flag@set@false|.
+% \begin{macrocode}
+\def\ekvc@flag@set@true#1%
+ {%
+ \def\ekvc@flag@set@true##1\ekv@stop##2%
+ {%
+ \ifodd##1
+ \ekv@fi@gobble
+ \fi
+ \@firstofone{\expandafter\@gobble\csname#1\endcsname}%
+ }%
+ \def\ekvc@flag@set@false##1\ekv@stop##2%
+ {%
+ \ifodd##1
+ \ekv@fi@firstofone
+ \fi
+ \@gobble{\expandafter\@gobble\csname#1\endcsname}%
+ }%
+ }
+\expandafter\ekvc@flag@set@true\expandafter
+ {\ekvc@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@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@exparg{\def\ekvcFlagIfRaised#1}%
+ {%
+ \expandafter\ifcsname\ekvc@flag@namescheme{\string#1}0\endcsname
+ \ekv@fi@firstoftwo
+ \fi
+ \@secondoftwo
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagReset}
+% \begin{macro}[internal]{\ekvc@flag@reset,\ekvc@flag@reset@}
+% Resetting works by locally letting all the defined internal macros named
+% after |\ekvc@flag@namescheme| to undefined.
+% \begin{macrocode}
+\protected\def\ekvcFlagReset#1%
+ {\expandafter\ekvc@flag@reset\csname\ekvc@flag@name#1\endcsname}
+\protected\def\ekvc@flag@reset#1%
+ {%
+ \ifcsname#10\endcsname
+ \expandafter\let\csname#10\endcsname\ekvc@undefined
+ \ekvc@flag@reset@1\ekv@stop#1%
+ \fi
+ }
+\protected\def\ekvc@flag@reset@#1\ekv@stop#2\fi
+ {%
+ \fi
+ \ifcsname#2{#1}\endcsname
+ \expandafter\let\csname#2{#1}\endcsname\ekvc@undefined
+ \expandafter\ekvc@flag@reset@\the\numexpr#1+1\relax\ekv@stop#2%
+ \fi
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagGetHeight}
+% \begin{macro}[internal]{\ekvc@flag@get@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@flag@get@height@single\ekvcFlagHeight#1\ekv@stop}
+\long\def\ekvc@flag@get@height@single#1\ekv@stop#2{#2{#1}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ekvcFlagGetHeights}
+% \begin{macro}[internal]
+% {\ekvc@flag@get@heights,\ekvc@flag@get@heights@,\ekvc@flag@get@heights@done}
+% This works by a simple loop that stops at |\ekv@stop|. As long as that
+% marker isn't hit, get the next flags height and put it into a list after
+% |\ekv@stop|. |\ekvc@flag@get@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@flag@get@heights#1\ekv@stop{}%
+ }
+\def\ekvc@flag@get@heights#1%
+ {%
+ \ekv@gobbleto@stop#1\ekvc@flag@get@heights@done\ekv@stop
+ \expandafter\ekvc@flag@get@heights@\ekvcFlagHeight#1\ekv@stop
+ }
+\def\ekvc@flag@get@heights@#1\ekv@stop#2\ekv@stop#3%
+ {\ekvc@flag@get@heights#2\ekv@stop{#3{#1}}}
+\long\def\ekvc@flag@get@heights@done
+ \ekv@stop
+ \expandafter\ekvc@flag@get@heights@\ekvcFlagHeight\ekv@stop\ekv@stop#1#2%
+ {#2{#1}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
%
% \subsubsection{Helper Macros}
%
@@ -1744,29 +2140,26 @@ and the derived files expkv-cs.pdf
% \begin{macro}[internal]{\ekvc@err,\ekvc@err@}
% We need a way to throw error messages expandably in some contexts.
% \begin{macrocode}
-\begingroup
-\edef\ekvc@err
+\def\ekvc@err#1%
{%
- \endgroup
- \unexpanded{\long\def\ekvc@err}##1%
- {%
- \unexpanded{\expandafter\ekvc@err@\@firstofone}%
- {\unexpanded\expandafter{\csname ! expkv-cs Error:\endcsname}##1.}%
- \unexpanded{\ekv@stop}%
- }%
+ \long\def\ekvc@err##1{\expandafter\ekv@err@\@firstofone{#1##1.}\ekv@stop}%
}
-\ekvc@err
-\def\ekvc@err@{\expandafter\ekv@gobbleto@stop}
+\begingroup\expandafter\endgroup
+\expandafter\ekvc@err\csname ! expkv-cs Error:\endcsname
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
-% {\ekvc@err@unknown@hash,\ekvc@err@empty@hash,\ekvc@err@missing@hash}
+% {
+% \ekvc@err@unknown@hash,\ekvc@err@empty@hash,\ekvc@err@missing@hash,
+% \ekvc@err@invalid@bool
+% }
% And here are the expandable error messages.
% \begin{macrocode}
\long\def\ekvc@err@unknown@hash#1{\ekvc@err{unknown hash `#1'}}
\long\def\ekvc@err@missing@hash#1{\ekvc@err{hash `#1' not found}}
\long\def\ekvc@err@empty@hash{\ekvc@err{empty hash}}
+\def\ekvc@err@invalid@bool#1{\ekvc@err{invalid boolean value `#1'}}
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex b/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex
index 38f5d3af810..8bcce4fcee5 100644
--- a/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex
+++ b/Master/texmf-dist/tex/generic/expkv-cs/expkv-cs.tex
@@ -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@tmp\endcsname
\expandafter\chardef\csname ekvc@tmp\endcsname=\catcode`\@
\catcode`\@=11
-\chardef\ekvc@zero0
\newcount\ekvc@keycount
\def\ekvc@long{}
\def\ekvc@any@long{}
@@ -398,10 +397,10 @@
####1%
{%
\unexpanded\expandafter{\csname ekvc@@safehash@#1\endcsname}%
- ####1\unexpanded{\ekvc@mark\ekvc@zero}%
+ ####1\unexpanded{\ekvc@mark\ekv@zero}%
\unexpanded\expandafter
{%
- \csname ekvc@hashmark@#1\endcsname\ekvc@zero
+ \csname ekvc@hashmark@#1\endcsname\ekv@zero
\ekvc@mark{\ekvc@err@missing@hash{#1}}\ekvc@stop
}%
}%
@@ -454,7 +453,7 @@
\romannumeral
\ekv@ifdefined{ekvc@safehash@#1}%
{\csname ekvc@safehash@#1\endcsname}%
- {\ekvc@err@unknown@hash{#1}\@firstoftwo\ekvc@zero}%
+ {\ekvc@err@unknown@hash{#1}\@firstoftwo\ekv@zero}%
}
\long\def\ekvcValueFast#1#2{\csname ekvc@fasthash@#1\endcsname#2\ekvc@stop}
\long\def\ekvcValueSplit#1%
@@ -479,7 +478,7 @@
{%
\csname ekvc@fastsplithash@#1\endcsname#2\ekvc@stop
}
-\long\def\ekvc@safehash@#1{\ekvc@err@empty@hash\ekvc@zero}
+\long\def\ekvc@safehash@#1{\ekvc@err@empty@hash\ekv@zero}
\long\def\ekvc@fasthash@#1\ekvc@stop{\ekvc@err@empty@hash}
\long\def\ekvc@safesplithash@#1#2{\ekvc@err@empty@hash#2{#1}{}}
\long\def\ekvc@fastsplithash@#1\ekvc@stop#2{\ekvc@err@empty@hash#2{#1}{}}
@@ -577,6 +576,138 @@
}%
{\ekvc@err@unknown@key{#1}}%
}
+\protected\expandafter\def\csname ekvc@t@flag-bool\endcsname#1#2%
+ {%
+ \ekvc@assert@not@long{flag-bool #1}%
+ \unless\ifdefined#2\ekvcFlagNew#2\fi
+ \ekvdef\ekvc@set{#1}%
+ {%
+ \ekv@ifdefined{ekvc@flag@set@##1}%
+ {%
+ \csname ekvc@flag@set@##1\expandafter\endcsname
+ \ekvcFlagHeight#2\ekv@stop#2%
+ }%
+ {\ekvc@err@invalid@bool{##1}}%
+ }%
+ }
+\protected\def\ekvc@type@flag#1#2#3#4%
+ {%
+ \ekvc@assert@not@long{flag-#1 #3}%
+ \unless\ifdefined#4\ekvcFlagNew#4\fi
+ \ekv@exparg{\ekvdefNoVal\ekvc@set{#3}}{#2#4}%
+ }
+\protected\expandafter\def\csname ekvc@t@flag-true\endcsname
+ {\ekvc@type@flag{true}\ekvcFlagSetTrue}
+\protected\expandafter\def\csname ekvc@t@flag-false\endcsname
+ {\ekvc@type@flag{false}\ekvcFlagSetFalse}
+\protected\expandafter\def\csname ekvc@t@flag-raise\endcsname
+ {\ekvc@type@flag{raise}\ekvcFlagRaise}
+\def\ekvc@flag@name{ekvcf\string}
+\def\ekvc@flag@namescheme#1#2{ekvch#2#1}
+\let\ekvcFlagHeight\number
+\protected\def\ekvcFlagNew#1%
+ {%
+ \edef#1%
+ {%
+ \unexpanded{\ekvc@flag@height}%
+ \unexpanded\expandafter{\csname\ekvc@flag@name#1\endcsname}%
+ }%
+ \ekv@expargtwice
+ {\expandafter\def\csname\ekvc@flag@name#1\endcsname##1}%
+ {\expandafter\ekvc@flag@namescheme\expandafter{\string#1}{##1}}%
+ }
+\def\ekvc@flag@height#1%
+ {%
+ \ifcsname#10\endcsname
+ \ekvc@flag@height@1\ekv@stop#1%
+ \fi
+ \@firstofone{0} % leave this space
+ }
+\def\ekvc@flag@height@#1\ekv@stop#2\fi\@firstofone#3%
+ {%
+ \fi
+ \ifcsname#2{#1}\endcsname
+ \expandafter\ekvc@flag@height@\the\numexpr#1+1\relax\ekv@stop#2%
+ \fi
+ \@firstofone{#1}%
+ }
+\ekv@exparg{\def\ekvcFlagRaise#1}%
+ {%
+ \expandafter\expandafter\expandafter\@gobble\expandafter
+ \csname\ekvc@flag@namescheme{\string#1}{\ekvcFlagHeight#1}\endcsname
+ }
+\def\ekvcFlagSetTrue#1%
+ {\expandafter\ekvc@flag@set@true\ekvcFlagHeight#1\ekv@stop#1}
+\def\ekvcFlagSetFalse#1%
+ {\expandafter\ekvc@flag@set@false\ekvcFlagHeight#1\ekv@stop#1}
+\def\ekvc@flag@set@true#1%
+ {%
+ \def\ekvc@flag@set@true##1\ekv@stop##2%
+ {%
+ \ifodd##1
+ \ekv@fi@gobble
+ \fi
+ \@firstofone{\expandafter\@gobble\csname#1\endcsname}%
+ }%
+ \def\ekvc@flag@set@false##1\ekv@stop##2%
+ {%
+ \ifodd##1
+ \ekv@fi@firstofone
+ \fi
+ \@gobble{\expandafter\@gobble\csname#1\endcsname}%
+ }%
+ }
+\expandafter\ekvc@flag@set@true\expandafter
+ {\ekvc@flag@namescheme{\string#2}{#1}}
+\def\ekvcFlagIf#1%
+ {%
+ \ifodd#1%
+ \ekv@fi@firstoftwo
+ \fi
+ \@secondoftwo
+ }
+\ekv@exparg{\def\ekvcFlagIfRaised#1}%
+ {%
+ \expandafter\ifcsname\ekvc@flag@namescheme{\string#1}0\endcsname
+ \ekv@fi@firstoftwo
+ \fi
+ \@secondoftwo
+ }
+\protected\def\ekvcFlagReset#1%
+ {\expandafter\ekvc@flag@reset\csname\ekvc@flag@name#1\endcsname}
+\protected\def\ekvc@flag@reset#1%
+ {%
+ \ifcsname#10\endcsname
+ \expandafter\let\csname#10\endcsname\ekvc@undefined
+ \ekvc@flag@reset@1\ekv@stop#1%
+ \fi
+ }
+\protected\def\ekvc@flag@reset@#1\ekv@stop#2\fi
+ {%
+ \fi
+ \ifcsname#2{#1}\endcsname
+ \expandafter\let\csname#2{#1}\endcsname\ekvc@undefined
+ \expandafter\ekvc@flag@reset@\the\numexpr#1+1\relax\ekv@stop#2%
+ \fi
+ }
+\def\ekvcFlagGetHeight#1%
+ {\expandafter\ekvc@flag@get@height@single\ekvcFlagHeight#1\ekv@stop}
+\long\def\ekvc@flag@get@height@single#1\ekv@stop#2{#2{#1}}
+\def\ekvcFlagGetHeights#1%
+ {%
+ \ekvc@flag@get@heights#1\ekv@stop{}%
+ }
+\def\ekvc@flag@get@heights#1%
+ {%
+ \ekv@gobbleto@stop#1\ekvc@flag@get@heights@done\ekv@stop
+ \expandafter\ekvc@flag@get@heights@\ekvcFlagHeight#1\ekv@stop
+ }
+\def\ekvc@flag@get@heights@#1\ekv@stop#2\ekv@stop#3%
+ {\ekvc@flag@get@heights#2\ekv@stop{#3{#1}}}
+\long\def\ekvc@flag@get@heights@done
+ \ekv@stop
+ \expandafter\ekvc@flag@get@heights@\ekvcFlagHeight\ekv@stop\ekv@stop#1#2%
+ {#2{#1}}
\long\def\ekvc@ifspace#1%
{%
\ekvc@ifspace@#1 \ekv@ifempty@B
@@ -618,22 +749,16 @@
\errmessage
{expkv-cs Error: Unknown key `\unexpanded{#1}' for macro `\ekvc@set'}%
}
-\begingroup
-\edef\ekvc@err
+\def\ekvc@err#1%
{%
- \endgroup
- \unexpanded{\long\def\ekvc@err}##1%
- {%
- \unexpanded{\expandafter\ekvc@err@\@firstofone}%
- {\unexpanded\expandafter{\csname ! expkv-cs Error:\endcsname}##1.}%
- \unexpanded{\ekv@stop}%
- }%
+ \long\def\ekvc@err##1{\expandafter\ekv@err@\@firstofone{#1##1.}\ekv@stop}%
}
-\ekvc@err
-\def\ekvc@err@{\expandafter\ekv@gobbleto@stop}
+\begingroup\expandafter\endgroup
+\expandafter\ekvc@err\csname ! expkv-cs Error:\endcsname
\long\def\ekvc@err@unknown@hash#1{\ekvc@err{unknown hash `#1'}}
\long\def\ekvc@err@missing@hash#1{\ekvc@err{hash `#1' not found}}
\long\def\ekvc@err@empty@hash{\ekvc@err{empty hash}}
+\def\ekvc@err@invalid@bool#1{\ekvc@err{invalid boolean value `#1'}}
\catcode`\@=\ekvc@tmp
%%
%%
diff --git a/Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty b/Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty
index e70dbab33ed..e712098dee4 100644
--- a/Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty
+++ b/Master/texmf-dist/tex/latex/expkv-cs/expkv-cs.sty
@@ -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