texlive[59949] Master/texmf-dist: expkv (16jul21)

commits+karl at tug.org commits+karl at tug.org
Fri Jul 16 21:56:18 CEST 2021


Revision: 59949
          http://tug.org/svn/texlive?view=revision&revision=59949
Author:   karl
Date:     2021-07-16 21:56:17 +0200 (Fri, 16 Jul 2021)
Log Message:
-----------
expkv (16jul21)

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

Modified: trunk/Master/texmf-dist/doc/latex/expkv/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/expkv/README.md	2021-07-15 23:48:36 UTC (rev 59948)
+++ trunk/Master/texmf-dist/doc/latex/expkv/README.md	2021-07-16 19:56:17 UTC (rev 59949)
@@ -1,7 +1,7 @@
 -------------------------------------------------------------------------------
 # expkv -- an expandable key=val implementation
 
-Version 2021-06-03 v1.8a
+Version 2021-07-15 v1.9
 
 Released under the LaTeX Project Public License v1.3c or later
 See http://www.latex-project.org/lppl.txt

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

Modified: trunk/Master/texmf-dist/source/latex/expkv/expkv.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/expkv/expkv.dtx	2021-07-15 23:48:36 UTC (rev 59948)
+++ trunk/Master/texmf-dist/source/latex/expkv/expkv.dtx	2021-07-16 19:56:17 UTC (rev 59949)
@@ -421,7 +421,7 @@
 % \end{function}
 % \example Define |text| in |foo| to store the value inside |\foo at text|:
 % \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
-% \protected\long\ekvdef{foo}{text}{\def\foo at width{#1}}
+% \protected\long\ekvdef{foo}{text}{\def\foo at text{#1}}
 % \end{lstlisting}
 %
 % \begin{function}{\ekvdefNoVal}
@@ -440,7 +440,8 @@
 %     \cs{ekvlet}\marg{set}\marg{key}\meta{cs}
 %   \end{syntax}
 %   Let the value taking \key\ in \set\ to \meta{cs}, there are no checks on
-%   \meta{cs} enforced.
+%   \meta{cs} enforced, but the code should expect the value as a single braced
+%   argument directly following it.
 % \end{function}
 % \example Let |cmd| in |foo| do the same as |\foo at cmd|:
 % \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
@@ -811,7 +812,8 @@
 %   argument will be wrapped in braces, the mandatory argument will be
 %   untouched). If there was no optional argument the result will be
 %   \meta{next}\marg{default}\marg{mandatory} (so the default will be used and
-%   the mandatory argument will be wrapped in braces).
+%   the mandatory argument will be wrapped in braces after being read once -- if
+%   it was already wrapped it is effectively unchanged).
 % \end{function}
 % |\ekvoptarg| expands in exactly two steps, grabs all the arguments only at the
 % second expansion step, and is alignment safe. It has its limitations however.
@@ -845,6 +847,43 @@
 % \newcommand\foo at b[1]{Mandatory: #1\par No optional.}
 % \end{lstlisting}
 %
+% \begin{function}{\ekvcsvloop}
+%   \begin{syntax}
+%     \cs{ekvcsvloop}\marg{code}\marg{csv-list}
+%   \end{syntax}
+%   This loops over the comma separated items in \meta{csv-list} and, after
+%   stripping spaces from either end of \meta{item} and removing at most one set
+%   of outer braces, leaves
+%   \texttt
+%     {^^A
+%       \cs[no-index]{unexpanded}\hskip0pt
+%       \{\hskip0pt
+%         \meta{code}\hskip0pt
+%         \marg{item}\hskip0pt
+%       \}^^A
+%     }
+%   for each list item in the input stream. Blank elements are ignored (if you
+%   need a blank element it should be given as |{}|). It supports both active
+%   commas and commas of category other. You could consider it as a watered down
+%   version of |\ekvparse|. However it is not alignment safe, which you could
+%   achieve by nesting it in |\expanded| (since the braces around the argument
+%   of |\expanded| will hide |&|s from \TeX's alignment parsing).
+% \end{function}
+% \example The following splits a comma separated list and prints it in a
+% typewriter font with parentheses around each element.\\
+% \begin{minipage}{.75\linewidth}
+% \begin{lstlisting}
+% \newcommand*\myprocessor[1]{\texttt{(#1)}}
+% \ekvcsvloop\myprocessor{abc,def,ghi}\par
+% \ekvcsvloop\myprocessor{1,,2,,3,,4}\par
+% \end{lstlisting}
+% \end{minipage}^^A
+% \begin{exresult}[nobeforeafter,box align=center]{.25\linewidth}
+%   \newcommand*\myprocessor[1]{\texttt{(#1)}}
+%   \ekvcsvloop\myprocessor{abc,def,ghi}\par
+%   \ekvcsvloop\myprocessor{1,,2,,3,,4}\par
+% \end{exresult}
+%
 % \begin{function}{\ekverr}
 %   \begin{syntax}
 %     \cs{ekverr}\marg{package}\marg{message}
@@ -1554,8 +1593,8 @@
 % \begin{macro}{\ekvVersion,\ekvDate}
 % We're on our first input, so lets store the version and date in a macro.
 %    \begin{macrocode}
-\def\ekvVersion{1.8a}
-\def\ekvDate{2021-06-03}
+\def\ekvVersion{1.9}
+\def\ekvDate{2021-07-15}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1762,35 +1801,73 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\ekvcsvloop}
+% \begin{macro}[internal]{\ekv at csv@loop at active,\ekv at csv@loop at active@end}
+%   An |\ekvcsvloop| will just loop over a csv list in a simple manner. First we
+%   split at active commas (gives better performance this way), next we have to
+%   check whether we're at the end of the list (checking for |\ekv at stop|). If
+%   not we go on splitting at commas of category other.
+%    \begin{macrocode}
+\begingroup
+\def\ekvcsvloop#1{%
+\endgroup
+\long\def\ekvcsvloop##1##2%
+  {\ekv at csv@loop at active{##1}\ekv at mark##2#1\ekv at stop#1}
+%    \end{macrocode}
+%   This does the same as |\ekv at csv@loop| but for active commas.
+%    \begin{macrocode}
+\long\def\ekv at csv@loop at active##1##2#1%
+  {%
+    \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at active@end\ekv at stop
+    \ekv at csv@loop{##1}##2,\ekv at stop,%
+  }%
+\long\def\ekv at csv@loop at active@end
+    \ekv at stop
+    \ekv at csv@loop##1\ekv at mark\ekv at stop,\ekv at stop,%
+  {}%
+}
+%    \end{macrocode}
+%   Do the definitions with the weird catcode.
+%    \begin{macrocode}
+\catcode`\,=13
+\ekvcsvloop,
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \begin{macro}[internal]{\ekv at csv@loop,\ekv at csv@loop at do,\ekv at csv@loop at end}
-%   This is just a very simple loop over a list of comma separated values,
-%   leaving each element as the argument to a specified function inside of
-%   |\unravel|. It should be used as
-%   \texttt
-%     {^^A
-%       \cs[no-index]{ekv at csv@loop}\hskip0pt^^A
-%       \marg{function}\hskip0pt^^A
-%       \cs[no-index]{ekv at mark}\hskip0pt^^A
-%       \meta{csv-list}\hskip0pt^^A
-%       ,\cs[no-index]{ekv at stop},^^A
-%     }.
-%   We use some |\expandafter| chain to preexpand |\ekv at strip| here.
+%   We use temporary macros and an |\expandafter| chain to preexpand
+%   |\ekv at strip| here. After splitting at other commas we check again for end
+%   the end of the sublist, check for blank elements which should be ignored,
+%   and else strip spaces and execute the user code (protecting it from further
+%   expanding with |\unexpanded|).
 %    \begin{macrocode}
-\ekv at exparg{\long\def\ekv at csv@loop#1#2,}%
+\def\ekv at csv@loop#1%
   {%
-    \expandafter
-    \ekv at gobble@from at mark@to at stop
-      \expandafter#\expandafter2\expandafter\ekv at csv@loop at end\expandafter
-    \ekv at stop
-    \ekv at strip{#2}{\ekv at csv@loop at do{#1}}%
-    \ekv at csv@loop{#1}\ekv at mark
+    \long\def\ekv at csv@loop##1##2,%
+      {%
+        \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at end\ekv at stop
+        \ekv at ifblank@##2\ekv at nil\ekv at ifempty@B\ekv at csv@loop at blank
+          \ekv at ifempty@A\ekv at ifempty@B
+        #1\ekv at csv@loop at do{##1}%
+      }%
   }
-\long\def\ekv at csv@loop at do#1#2{\unexpanded{#1{#2}}}
-\long\expandafter\def\expandafter\ekv at csv@loop at end
-    \expandafter\ekv at stop
-    \ekv at strip{#1}#2%
-    \ekv at csv@loop#3\ekv at mark
-  {}
+\expandafter\ekv at csv@loop\expandafter{\ekv at strip{#2}}
+\long\def\ekv at csv@loop at do#1#2{\unexpanded{#2{#1}}\ekv at csv@loop{#2}\ekv at mark}
+\def\ekv at csv@loop at end#1%
+  {%
+    \long\def\ekv at csv@loop at end
+        \ekv at stop
+        \ekv at ifblank@\ekv at mark\ekv at stop\ekv at nil\ekv at ifempty@B\ekv at csv@loop at blank
+        \ekv at ifempty@A\ekv at ifempty@B
+        #1\ekv at csv@loop at do##1%
+      {\ekv at csv@loop at active{##1}\ekv at mark}%
+  }
+\expandafter\ekv at csv@loop at end\expandafter{\ekv at strip{\ekv at mark\ekv at stop}}
+\long\expandafter\def\expandafter\ekv at csv@loop at blank
+    \expandafter\ekv at ifempty@A\expandafter\ekv at ifempty@B
+    \ekv at strip{\ekv at mark#1}\ekv at csv@loop at do#2%
+  {\ekv at csv@loop{#2}\ekv at mark}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1969,9 +2046,9 @@
     \begingroup
     \edef\ekv at tmp
       {%
-        \ekv at csv@loop#1\ekv at mark#6,\ekv at stop,%
+        \ekvcsvloop#1{#6}%
         \unexpanded{#2}%
-        {\ekv at csv@loop{}\ekv at mark#5,#6,\ekv at stop,}%
+        {\ekvcsvloop{}{#5,#6}}%
       }%
     \ekv at expargtwice
       {\endgroup#3{#5}}%
@@ -2690,7 +2767,10 @@
 % possibilities (they don't care for nested bracket levels).
 %
 % We start with a temporary definition to pre-expand |\ekv at alignsafe| (will be
-% |#1|) and |\ekv at endalignsafe| (will be |#2|).
+% |#1|) and |\ekv at endalignsafe| (will be |#2|). As |\ekv at alignsafe| starts with
+% a |\romannumeral| we use that to also control the number of steps needed
+% instead of adding another |\romannumeral|. For this we have to remove the
+% space token from the end of |\ekv at alignsafe|'s definition.
 %    \begin{macrocode}
 \begingroup
 \def\ekvoptarg#1#2{%
@@ -2702,12 +2782,12 @@
 % bracket, if it is found grab the optional argument, else leave |#1{#2}| in the
 % input stream after ending the expansion context.
 %    \begin{macrocode}
-\def\ekvoptarg{\romannumeral#1\ekv at optarg@a}
+\def\ekvoptarg{#1\ekv at optarg@a}
 \long\def\ekv at optarg@a##1##2##3%
   {%
     \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optarg@b\ekv at mark[\ekv at mark
     #2%
-    \@firstofone{\ekv at zero##1}{##2}{##3}%
+    \@firstofone{ ##1}{##2}{##3}%
   }%
 %    \end{macrocode}
 % The other variant of this will do roughly the same. Here, |#1| will be the
@@ -2714,12 +2794,12 @@
 % next step if an optional argument is found, |#2| the next step else, and |#3|
 % might be the opening bracket or mandatory argument.
 %    \begin{macrocode}
-\def\ekvoptargTF{\romannumeral#1\ekv at optargTF@a}
+\def\ekvoptargTF{#1\ekv at optargTF@a}
 \long\def\ekv at optargTF@a##1##2##3%
   {%
     \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optargTF@b{##1}\ekv at mark[\ekv at mark
     #2%
-    \@firstofone{\ekv at zero##2}{##3}%
+    \@firstofone{ ##2}{##3}%
   }
 %    \end{macrocode}
 % The two macros to grab the optional argument have to remove the remainder of
@@ -2729,12 +2809,19 @@
   {#2##2{##5}}
 \long\def\ekv at optargTF@b
     ##1\ekv at mark[\ekv at mark\ifnum`##2\fi\@firstofone##3##4##5]%
-  {#2\ekv at zero##1{##5}}
+  {#2 ##1{##5}}
 }
 %    \end{macrocode}
-% Do the definitions and add the test macro.
+% Do the definitions and add the test macro. We use |\ekv at strip| to remove the
+% trailing space from the definition of |\ekv at alignsafe|.
 %    \begin{macrocode}
-\ekv at exparg{\expandafter\ekvoptarg\expandafter{\ekv at alignsafe}}\ekv at endalignsafe
+\ekv at exparg
+  {%
+    \expandafter\ekv at strip\expandafter
+      {\expandafter\ekv at mark\ekv at alignsafe}%
+      \ekvoptarg
+  }%
+  \ekv at endalignsafe
 \long\def\ekv at optarg@if#1\ekv at mark[\ekv at mark{}
 %    \end{macrocode}
 % \end{macro}

Modified: trunk/Master/texmf-dist/tex/generic/expkv/expkv.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/expkv/expkv.tex	2021-07-15 23:48:36 UTC (rev 59948)
+++ trunk/Master/texmf-dist/tex/generic/expkv/expkv.tex	2021-07-16 19:56:17 UTC (rev 59949)
@@ -44,8 +44,8 @@
   \errmessage{expkv Error: e-TeX and \noexpand\expanded required}
   \expandafter\endinput
 \fi
-\def\ekvVersion{1.8a}
-\def\ekvDate{2021-06-03}
+\def\ekvVersion{1.9}
+\def\ekvDate{2021-07-15}
 \csname ekv at tmp\endcsname
 \expandafter\chardef\csname ekv at tmp\endcsname=\catcode`\@
 \catcode`\@=11
@@ -136,21 +136,49 @@
 \long\def\ekv at exparg@#1#2{#2{#1}}%
 \long\def\ekv at expargtwice#1#2{\expandafter\ekv at expargtwice@\expandafter{#2}{#1}}
 \def\ekv at expargtwice@{\expandafter\ekv at exparg@\expandafter}
-\ekv at exparg{\long\def\ekv at csv@loop#1#2,}%
+\begingroup
+\def\ekvcsvloop#1{%
+\endgroup
+\long\def\ekvcsvloop##1##2%
+  {\ekv at csv@loop at active{##1}\ekv at mark##2#1\ekv at stop#1}
+\long\def\ekv at csv@loop at active##1##2#1%
   {%
-    \expandafter
-    \ekv at gobble@from at mark@to at stop
-      \expandafter#\expandafter2\expandafter\ekv at csv@loop at end\expandafter
+    \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at active@end\ekv at stop
+    \ekv at csv@loop{##1}##2,\ekv at stop,%
+  }%
+\long\def\ekv at csv@loop at active@end
     \ekv at stop
-    \ekv at strip{#2}{\ekv at csv@loop at do{#1}}%
-    \ekv at csv@loop{#1}\ekv at mark
+    \ekv at csv@loop##1\ekv at mark\ekv at stop,\ekv at stop,%
+  {}%
+}
+\catcode`\,=13
+\ekvcsvloop,
+\def\ekv at csv@loop#1%
+  {%
+    \long\def\ekv at csv@loop##1##2,%
+      {%
+        \ekv at gobble@from at mark@to at stop##2\ekv at csv@loop at end\ekv at stop
+        \ekv at ifblank@##2\ekv at nil\ekv at ifempty@B\ekv at csv@loop at blank
+          \ekv at ifempty@A\ekv at ifempty@B
+        #1\ekv at csv@loop at do{##1}%
+      }%
   }
-\long\def\ekv at csv@loop at do#1#2{\unexpanded{#1{#2}}}
-\long\expandafter\def\expandafter\ekv at csv@loop at end
-    \expandafter\ekv at stop
-    \ekv at strip{#1}#2%
-    \ekv at csv@loop#3\ekv at mark
-  {}
+\expandafter\ekv at csv@loop\expandafter{\ekv at strip{#2}}
+\long\def\ekv at csv@loop at do#1#2{\unexpanded{#2{#1}}\ekv at csv@loop{#2}\ekv at mark}
+\def\ekv at csv@loop at end#1%
+  {%
+    \long\def\ekv at csv@loop at end
+        \ekv at stop
+        \ekv at ifblank@\ekv at mark\ekv at stop\ekv at nil\ekv at ifempty@B\ekv at csv@loop at blank
+        \ekv at ifempty@A\ekv at ifempty@B
+        #1\ekv at csv@loop at do##1%
+      {\ekv at csv@loop at active{##1}\ekv at mark}%
+  }
+\expandafter\ekv at csv@loop at end\expandafter{\ekv at strip{\ekv at mark\ekv at stop}}
+\long\expandafter\def\expandafter\ekv at csv@loop at blank
+    \expandafter\ekv at ifempty@A\expandafter\ekv at ifempty@B
+    \ekv at strip{\ekv at mark#1}\ekv at csv@loop at do#2%
+  {\ekv at csv@loop{#2}\ekv at mark}
 \def\ekv at name@set#1{ekv#1(}
 \def\ekv at name@key#1{#1)}
 \edef\ekv at name
@@ -269,9 +297,9 @@
     \begingroup
     \edef\ekv at tmp
       {%
-        \ekv at csv@loop#1\ekv at mark#6,\ekv at stop,%
+        \ekvcsvloop#1{#6}%
         \unexpanded{#2}%
-        {\ekv at csv@loop{}\ekv at mark#5,#6,\ekv at stop,}%
+        {\ekvcsvloop{}{#5,#6}}%
       }%
     \ekv at expargtwice
       {\endgroup#3{#5}}%
@@ -658,27 +686,33 @@
 \begingroup
 \def\ekvoptarg#1#2{%
 \endgroup
-\def\ekvoptarg{\romannumeral#1\ekv at optarg@a}
+\def\ekvoptarg{#1\ekv at optarg@a}
 \long\def\ekv at optarg@a##1##2##3%
   {%
     \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optarg@b\ekv at mark[\ekv at mark
     #2%
-    \@firstofone{\ekv at zero##1}{##2}{##3}%
+    \@firstofone{ ##1}{##2}{##3}%
   }%
-\def\ekvoptargTF{\romannumeral#1\ekv at optargTF@a}
+\def\ekvoptargTF{#1\ekv at optargTF@a}
 \long\def\ekv at optargTF@a##1##2##3%
   {%
     \ekv at optarg@if\ekv at mark##3\ekv at mark\ekv at optargTF@b{##1}\ekv at mark[\ekv at mark
     #2%
-    \@firstofone{\ekv at zero##2}{##3}%
+    \@firstofone{ ##2}{##3}%
   }
 \long\def\ekv at optarg@b\ekv at mark[\ekv at mark\ifnum`##1\fi\@firstofone##2##3##4##5]%
   {#2##2{##5}}
 \long\def\ekv at optargTF@b
     ##1\ekv at mark[\ekv at mark\ifnum`##2\fi\@firstofone##3##4##5]%
-  {#2\ekv at zero##1{##5}}
+  {#2 ##1{##5}}
 }
-\ekv at exparg{\expandafter\ekvoptarg\expandafter{\ekv at alignsafe}}\ekv at endalignsafe
+\ekv at exparg
+  {%
+    \expandafter\ekv at strip\expandafter
+      {\expandafter\ekv at mark\ekv at alignsafe}%
+      \ekvoptarg
+  }%
+  \ekv at endalignsafe
 \long\def\ekv at optarg@if#1\ekv at mark[\ekv at mark{}
 \def\ekv at err@cleanup\par{}
 \def\ekv at err@collect#1%



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