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.