[latex3-commits] [git/LaTeX3-latex3-latex2e] gh639: Replicate argument processors for all embellishments (ba7cf4c8)

PhelypeOleinik phelype.oleinik at latex-project.org
Sat Aug 7 05:41:42 CEST 2021


Repository : https://github.com/latex3/latex2e
On branch  : gh639
Link       : https://github.com/latex3/latex2e/commit/ba7cf4c82323d766cd29396671f9290f8f2186d5

>---------------------------------------------------------------

commit ba7cf4c82323d766cd29396671f9290f8f2186d5
Author: PhelypeOleinik <phelype.oleinik at latex-project.org>
Date:   Sat Aug 7 00:41:42 2021 -0300

    Replicate argument processors for all embellishments
    
    Fixes #639


>---------------------------------------------------------------

ba7cf4c82323d766cd29396671f9290f8f2186d5
 base/changes.txt                    |  5 +++
 base/doc/ltnews34.tex               | 22 +++++++++++++
 base/doc/usrguide3.tex              | 12 +++++++
 base/ltcmd.dtx                      | 66 ++++++++++++++++++++++++++++++++++---
 base/testfiles-ltcmd/github-639.lvt | 52 +++++++++++++++++++++++++++++
 base/testfiles-ltcmd/github-639.tlg | 38 +++++++++++++++++++++
 6 files changed, 191 insertions(+), 4 deletions(-)

diff --git a/base/changes.txt b/base/changes.txt
index 2c7c7a34..1da8af29 100644
--- a/base/changes.txt
+++ b/base/changes.txt
@@ -6,6 +6,11 @@ completeness or accuracy and it contains some references to files that
 are not part of the distribution.
 ================================================================================
 
+2021-08-07  Phelype Oleinik  <phelype.oleinik at latex-project.org>
+
+	* ltcmd.dtx (subsection{Setting up a standard signature}):
+	Replicate argument processors for all embellishments (gh/639).
+
 2021-07-31  Frank Mittelbach  <Frank.Mittelbach at latex-project.org>
 
 	* ltoutput.dtx (subsubsection{Float control}):
diff --git a/base/doc/ltnews34.tex b/base/doc/ltnews34.tex
index 4f94269c..bd80eee4 100644
--- a/base/doc/ltnews34.tex
+++ b/base/doc/ltnews34.tex
@@ -332,6 +332,28 @@ that it can be used by \pkg{hyperref}.
 
 
 
+\section{Bug fixes}
+
+\subsection{Replicate argument processors for all embellishments}
+
+There was a bug in \pkg{ltcmd} (former \pkg{xparse}) that caused
+commands to misbehave if they were defined with embellishments and
+argument processors.  In that case, only one (possibly void) argument
+processor would be added to the full set of embellishment arguments,
+resulting in too few processors in some cases, leading to unpredictable
+behavior.  This bug has been fixed by applying the same argument
+processors to all the embellishments in a set, so a declaration like:
+\begin{verbatim}
+\NewDocumentCommand \foo { >{\TrimSpaces} e{_^} } { (#1)[#2] }
+\foo^{ a }_{ b }
+\end{verbatim}
+will now correctly apply \cs{TrimSpaces} to both arguments.
+%
+\githubissue{639}
+
+
+
+
 
 \section{Changes to packages in the \pkg{graphics} category}
 
diff --git a/base/doc/usrguide3.tex b/base/doc/usrguide3.tex
index e14bf94f..82c1c068 100644
--- a/base/doc/usrguide3.tex
+++ b/base/doc/usrguide3.tex
@@ -454,6 +454,18 @@ category code $13$ (active) character matching the \meta{token} will
 be replaced before the split takes place.
 Spaces are trimmed at each end of each item parsed.
 
+The \texttt{E} argument type is somewhat special, because with a single
+\texttt{E} in the command declaration you may end up with several
+arguments in a command (one formal argument per embellishment token).
+Therefore, when an argument processor is applied to an \texttt{E}-type
+argument, all the arguments pass through that processor before being fed
+to the \meta{code}.  For example, this command
+\begin{verbatim}
+  \NewDocumentCommand \foo { >{\TrimSpaces} e{_^} }
+    { [#1](#2) }
+\end{verbatim}
+applies \cs{TrimSpaces} to both arguments.
+
 \begin{decl}
   |\SplitList| \arg{token(s)}
 \end{decl}
diff --git a/base/ltcmd.dtx b/base/ltcmd.dtx
index 6f2153c6..2a442297 100644
--- a/base/ltcmd.dtx
+++ b/base/ltcmd.dtx
@@ -34,8 +34,8 @@
 %%% From File: ltcmd.dtx
 %
 %    \begin{macrocode}
-\def\ltcmdversion{v1.0f}
-\def\ltcmddate{2021-06-04}
+\def\ltcmdversion{v1.0g}
+\def\ltcmddate{2021-08-07}
 %    \end{macrocode}
 %
 %<*driver>
@@ -1505,12 +1505,21 @@
 %
 % \begin{macro}{\@@_add_type_E:w}
 %   The \texttt{E}-type argument needs a special handling of default
-%   values.
+%   values.  It also needs, since each embellishment is a separate
+%   argument, to replicate the argument processors to each embellishment
+%   argument so the number of arguments and processors remains in sync.
+% \changes{v1.0g}{2021/08/07}
+%         {Replicate argument processors for all embellishments (gh/639)}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_add_type_E:w #1#2
   {
     \@@_flush_m_args:
     \@@_add_default_E:nn {#1} {#2}
+    \use:x
+      {
+        \@@_replicate_processor:nn { \tl_count:n {#1} }
+          { \exp_not:o \l_@@_process_one_tl }
+      }
     \@@_add_grabber:N E
     \tl_put_right:Nn \l_@@_signature_tl { {#1} }
     \@@_prepare_signature:N
@@ -1518,6 +1527,48 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_replicate_processor:nn}
+%   In the command's argument processor signature (the final argument of
+%   \cs{@@_start:nNNnnn}) there is one braced item for each formal
+%   argument (up to nine), and in each of these items there is one
+%   braced item for each processor (as many as there were processors
+%   declared for a given argument).  Something like this:
+%   \begin{quote}
+%     \ttfamily \obeylines
+%     \{ \% argument processors
+%     \ \ \{ \% argument 1
+%     \ \ \ \ \{ processor 1 \} \{ processor 2 \} \ldots\ \{ processor n \}
+%     \ \ \} \% end argument 1
+%     \ \ \{ \ldots\ \} \% argument 2
+%     \ \ \ \ \ \vdots
+%     \ \ \{ \ldots\ \} \% argument n
+%     \} \% end argument processors
+%   \end{quote}
+%
+%   The function \cs{@@_add_grabber:N} adds one single grabber for an
+%   argument, and adds the braced item for that one argument.  However,
+%   in an |E|-type argument each embellishment requires its own formal
+%   argument, so we need to break out of one layer of braces in
+%   \cs{l_@@_process_one_tl}, add copies of the processor as necessary,
+%   and then return the removed brace.  The function below does just
+%   that:  it defines \cs{l_@@_process_one_tl} starting with a |}|$_2$
+%   and ending with a |{|$_11$, so that it adds as many processors as
+%   needed when |x|-expanded.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_replicate_processor:nn #1 #2
+  {
+    \int_compare:nNnF {#1} > { 1 } { \use_none:nnn }
+    \tl_set:Nx \l_@@_process_one_tl
+      {
+        \exp_not:n { \exp_not:n {#2} \if_false: { \fi: } }
+        \prg_replicate:nn { #1 - 2 }
+          { \exp_not:n { \exp_not:n { {#2} } } }
+        \exp_not:n { { \if_false: } \fi: \exp_not:n {#2} }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\@@_add_type_m:w}
 %   The \texttt{m} type is special as short arguments which are not
 %   post-processed are simply counted at this stage. Thus there is a check
@@ -1608,6 +1659,8 @@
 %   \cs{l_@@_obey_spaces_bool} boolean can only be \texttt{true} for
 %   trailing optional arguments.  In that case spaces will not be
 %   ignored when looking for that optional argument.
+% \changes{v1.0g}{2021/08/07}
+%         {Replicate argument processors for all embellishments (gh/639)}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_add_grabber:N #1
   {
@@ -1624,7 +1677,12 @@
     \bool_set_false:N \l_@@_long_bool
     \bool_set_false:N \l_@@_obey_spaces_bool
     \tl_put_right:Nx \l_@@_process_all_tl
-      { { \exp_not:o \l_@@_process_one_tl } }
+      {
+        {
+          \if_charcode:w E #1 \use_i:nn \fi:
+          \exp_not:o \l_@@_process_one_tl
+        }
+      }
     \tl_clear:N \l_@@_process_one_tl
   }
 %    \end{macrocode}
diff --git a/base/testfiles-ltcmd/github-639.lvt b/base/testfiles-ltcmd/github-639.lvt
new file mode 100644
index 00000000..755e950a
--- /dev/null
+++ b/base/testfiles-ltcmd/github-639.lvt
@@ -0,0 +1,52 @@
+\input{test2e}
+\START
+
+\def\AAAA#1{\def\ProcessedArgument{(#1)}}
+\def\BBBB#1{\def\ProcessedArgument{[#1]}}
+
+\ExplSyntaxOn
+%
+\DeclareDocumentCommand \foo { e{_} >{\SplitList{;}}o }
+  { \typeout {#1^^J#2^^J} }
+\typeout{\meaning\foo}
+\foo _d[h;i;j]
+                    \use_none:n \wrong
+%
+\DeclareDocumentCommand \foo { e{_^} >{\SplitList{;}}o }
+  { \typeout {#1^^J#2^^J#3^^J} }
+\typeout{\meaning\foo}
+\foo _d^e[h;i;j]
+                    \use_none:n \wrong
+%
+\DeclareDocumentCommand \foo { e{_^+} >{\SplitList{;}}o }
+  { \typeout {#1^^J#2^^J#3^^J#4^^J} }
+\typeout{\meaning\foo}
+\foo _d^e+f[h;i;j]
+                    \use_none:nn \more\wrong
+%
+\DeclareDocumentCommand \foo { e{_^+-} >{\SplitList{;}}o }
+  { \typeout {#1^^J#2^^J#3^^J#4^^J#5^^J} }
+\typeout{\meaning\foo}
+\foo _d^e+f-g[h;i;j]
+                    \use_none:nnn \even\more\wrong
+%
+\DeclareDocumentCommand \foo { >{\BBBB}>{\AAAA}e{_^+-} >{\SplitList{;}}o }
+  { \typeout {#1^^J#2^^J#3^^J#4^^J#5^^J} }
+\typeout{\meaning\foo}
+\foo _d^e+f-g[h;i;j]
+                    \use_none:nnn \even\more\wrong
+%
+\DeclareDocumentCommand \foo { >{\AAAA}e{_^+-} >{\SplitList{;}}o }
+  { \typeout {#1^^J#2^^J#3^^J#4^^J#5^^J} }
+\typeout{\meaning\foo}
+\foo _d^e+f-g[h;i;j]
+                    \use_none:nnn \even\more\wrong
+%
+\DeclareDocumentCommand \foo { e{_^+-} >{\SplitList{;}}o }
+  { \typeout {#1^^J#2^^J#3^^J#4^^J#5^^J} }
+\typeout{\meaning\foo}
+\foo _d^e+f-g[h;i;j]
+                    \use_none:nnn \even\more\wrong
+%
+
+\END
diff --git a/base/testfiles-ltcmd/github-639.tlg b/base/testfiles-ltcmd/github-639.tlg
new file mode 100644
index 00000000..8bb40731
--- /dev/null
+++ b/base/testfiles-ltcmd/github-639.tlg
@@ -0,0 +1,38 @@
+This is a generated file for the LaTeX2e validation system.
+Don't change this file in any respect.
+\protected macro:->\__cmd_start:nNNnnn {e{_}>{\SplitList {;}}o}\foo  \foo code {\__cmd_grab_E:w {_}\__cmd_grab_D:w []}{}{{}{{\SplitList {;}}}}
+d
+{h}{i}{j}
+\protected macro:->\__cmd_start:nNNnnn {e{_^}>{\SplitList {;}}o}\foo  \foo code {\__cmd_grab_E:w {_^}\__cmd_grab_D:w []}{}{{}{}{{\SplitList {;}}}}
+d
+e
+{h}{i}{j}
+\protected macro:->\__cmd_start:nNNnnn {e{_^+}>{\SplitList {;}}o}\foo  \foo code {\__cmd_grab_E:w {_^+}\__cmd_grab_D:w []}{}{{}{}{}{{\SplitList {;}}}}
+d
+e
+f
+{h}{i}{j}
+\protected macro:->\__cmd_start:nNNnnn {e{_^+-}>{\SplitList {;}}o}\foo  \foo code {\__cmd_grab_E:w {_^+-}\__cmd_grab_D:w []}{}{{}{}{}{}{{\SplitList {;}}}}
+d
+e
+f
+g
+{h}{i}{j}
+\protected macro:->\__cmd_start:nNNnnn {>{\BBBB }>{\AAAA }e{_^+-}>{\SplitList {;}}o}\foo  \foo code {\__cmd_grab_E:w {_^+-}\__cmd_grab_D:w []}{}{{{\AAAA }{\BBBB }}{{\AAAA }{\BBBB }}{{\AAAA }{\BBBB }}{{\AAAA }{\BBBB }}{{\SplitList {;}}}}
+[(d)]
+[(e)]
+[(f)]
+[(g)]
+{h}{i}{j}
+\protected macro:->\__cmd_start:nNNnnn {>{\AAAA }e{_^+-}>{\SplitList {;}}o}\foo  \foo code {\__cmd_grab_E:w {_^+-}\__cmd_grab_D:w []}{}{{{\AAAA }}{{\AAAA }}{{\AAAA }}{{\AAAA }}{{\SplitList {;}}}}
+(d)
+(e)
+(f)
+(g)
+{h}{i}{j}
+\protected macro:->\__cmd_start:nNNnnn {e{_^+-}>{\SplitList {;}}o}\foo  \foo code {\__cmd_grab_E:w {_^+-}\__cmd_grab_D:w []}{}{{}{}{}{}{{\SplitList {;}}}}
+d
+e
+f
+g
+{h}{i}{j}





More information about the latex3-commits mailing list.