[latex3-commits] [l3svn] r6874 - E-type arguments for expandable commands (fixes #331, see #281)

noreply at latex-project.org noreply at latex-project.org
Fri Feb 10 03:29:56 CET 2017


Author: bruno
Date: 2017-02-10 03:29:55 +0100 (Fri, 10 Feb 2017)
New Revision: 6874

Modified:
   trunk/l3packages/xparse/testfiles/xparse004.luatex.tlg
   trunk/l3packages/xparse/testfiles/xparse004.lvt
   trunk/l3packages/xparse/testfiles/xparse004.tlg
   trunk/l3packages/xparse/xparse.dtx
Log:
E-type arguments for expandable commands (fixes #331, see #281)

This commit implements the (experimental) embellishment argument type
for expandable commands (#331), and default values can refer to other
arguments (see #281).


Modified: trunk/l3packages/xparse/testfiles/xparse004.luatex.tlg
===================================================================
--- trunk/l3packages/xparse/testfiles/xparse004.luatex.tlg	2017-02-09 23:08:07 UTC (rev 6873)
+++ trunk/l3packages/xparse/testfiles/xparse004.luatex.tlg	2017-02-10 02:29:55 UTC (rev 6874)
@@ -1512,3 +1512,45 @@
 \A \B \C 
 \A \B \C 
 ============================================================
+============================================================
+TEST 20: Expandable e-type argument definitions
+============================================================
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'e{^_}m' on line ....
+.................................................
+({-NoValue-}{-NoValue-})(\the re)
+({\u p}{-NoValue-})(\he re)
+({-NoValue-}{\do wn})(\he re)
+({\u p}{\do wn})(\he re)
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'E{^_}{{\U P}}m' on line ....
+.................................................
+({\U P}{-NoValue-})(\the re)
+({\u p}{-NoValue-})(\he re)
+({\U P}{\do wn})(\he re)
+({\u p}{\do wn})(\he re)
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'E{^_}{{\U P}{\DO WN}}m' on line ....
+.................................................
+({\U P}{\DO WN})(\the re)
+({\u p}{\DO WN})(\he re)
+({\U P}{\do wn})(\he re)
+({\u p}{\do wn})(\he re)
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'E{^_}{{##2}{\DO WN}}O{####}m' on line
+. 379.
+.................................................
+({##}{\DO WN})(##)(\A )
+({\A }{\DO WN})(\A )(\B )
+({\A }{\DO WN})(\B )(\C )
+({##}{\A })(##)(\B )
+({\B }{\A })(\C )(\D )
+============================================================

Modified: trunk/l3packages/xparse/testfiles/xparse004.lvt
===================================================================
--- trunk/l3packages/xparse/testfiles/xparse004.lvt	2017-02-09 23:08:07 UTC (rev 6873)
+++ trunk/l3packages/xparse/testfiles/xparse004.lvt	2017-02-10 02:29:55 UTC (rev 6874)
@@ -349,4 +349,33 @@
     \end{foo}
   }
 
+\TEST { Expandable~e-type~argument~definitions }
+  {
+    \DeclareExpandableDocumentCommand \foo { e { ^ _ } m }
+      { \exp_not:n { (#1) (#2) } }
+    \TYPE { \foo { \the re } }
+    \TYPE { \foo ^ { \u p } { \he re } }
+    \TYPE { \foo _ { \do wn } { \he re } }
+    \TYPE { \foo ^ { \u p } _ { \do wn } { \he re } }
+    \DeclareExpandableDocumentCommand \foo { E { ^ _ } { { \U P } } m }
+      { \exp_not:n { (#1) (#2) } }
+    \TYPE { \foo { \the re } }
+    \TYPE { \foo ^ { \u p } { \he re } }
+    \TYPE { \foo _ { \do wn } { \he re } }
+    \TYPE { \foo ^ { \u p } _ { \do wn } { \he re } }
+    \DeclareExpandableDocumentCommand \foo { E { ^ _ } { { \U P } { \DO WN } } m }
+      { \exp_not:n { (#1) (#2) } }
+    \TYPE { \foo { \the re } }
+    \TYPE { \foo ^ { \u p } { \he re } }
+    \TYPE { \foo _ { \do wn } { \he re } }
+    \TYPE { \foo ^ { \u p } _ { \do wn } { \he re } }
+    \DeclareExpandableDocumentCommand \foo { E { ^ _ } { {#2} { \DO WN } } O{##} m }
+      { \exp_not:n { (#1) (#2) (#3) } }
+    \TYPE { \foo { \A } }
+    \TYPE { \foo [ \A ] { \B } }
+    \TYPE { \foo ^ { \A } [ \B ] { \C } }
+    \TYPE { \foo _ { \A } { \B } }
+    \TYPE { \foo _ { \A } ^ { \B } [ \C ] { \D } }
+  }
+
 \END

Modified: trunk/l3packages/xparse/testfiles/xparse004.tlg
===================================================================
--- trunk/l3packages/xparse/testfiles/xparse004.tlg	2017-02-09 23:08:07 UTC (rev 6873)
+++ trunk/l3packages/xparse/testfiles/xparse004.tlg	2017-02-10 02:29:55 UTC (rev 6874)
@@ -1512,3 +1512,45 @@
 \A \B \C 
 \A \B \C 
 ============================================================
+============================================================
+TEST 20: Expandable e-type argument definitions
+============================================================
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'e{^_}m' on line ....
+.................................................
+({-NoValue-}{-NoValue-})(\the re)
+({\u p}{-NoValue-})(\he re)
+({-NoValue-}{\do wn})(\he re)
+({\u p}{\do wn})(\he re)
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'E{^_}{{\U P}}m' on line ....
+.................................................
+({\U P}{-NoValue-})(\the re)
+({\u p}{-NoValue-})(\he re)
+({\U P}{\do wn})(\he re)
+({\u p}{\do wn})(\he re)
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'E{^_}{{\U P}{\DO WN}}m' on line ....
+.................................................
+({\U P}{\DO WN})(\the re)
+({\u p}{\DO WN})(\he re)
+({\U P}{\do wn})(\he re)
+({\u p}{\do wn})(\he re)
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'E{^_}{{##2}{\DO WN}}O{####}m' on line
+. 379.
+.................................................
+({##}{\DO WN})(##)(\A )
+({\A }{\DO WN})(\A )(\B )
+({\A }{\DO WN})(\B )(\C )
+({##}{\A })(##)(\B )
+({\B }{\A })(\C )(\D )
+============================================================

Modified: trunk/l3packages/xparse/xparse.dtx
===================================================================
--- trunk/l3packages/xparse/xparse.dtx	2017-02-09 23:08:07 UTC (rev 6873)
+++ trunk/l3packages/xparse/xparse.dtx	2017-02-10 02:29:55 UTC (rev 6874)
@@ -689,7 +689,7 @@
 %       to mix short and long argument types.
 %     \item The mandatory argument types \texttt{l} and \texttt{u} are
 %       not available.
-%     \item The optional argument types \texttt{e}, \texttt{E}, \texttt{g}
+%     \item The optional argument types \texttt{g}
 %       and \texttt{G} are not available.
 %     \item The \enquote{verbatim} argument type \texttt{v} is not available.
 %     \item Argument processors (using \texttt{>}) are not available.
@@ -1364,10 +1364,12 @@
 % \end{macro}
 %
 % \begin{macro}[EXP]{\@@_end_expandable:NNw}
-% \begin{macro}[EXP,aux]{\@@_end_expandable_aux:w,
-%   \@@_end_expandable_aux:nNNN, \@@_end_expandable_defaults:nnnNNn}
-% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nnw,
-%   \@@_end_expandable_defaults:nw}
+% \begin{macro}[EXP,aux]{\@@_end_expandable_aux:w}
+% \begin{macro}[EXP,aux]{\@@_end_expandable_aux:nNNN}
+% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nnnNNn}
+% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nnw}
+% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nw}
+% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults_E:nnw}
 %   Followed by a function |#1| to determine default values, the code
 %   |#2|, arguments that have been grabbed, then \cs{q_@@} and a generic
 %   grabber.  The idea to find default values is similar to the
@@ -1409,10 +1411,29 @@
   }
 \cs_new:Npn \@@_end_expandable_defaults:nnw #1#2
   {
-    \@@_if_no_value:nTF {#2}
-      { \exp_args:No \@@_end_expandable_defaults:nw { \use_none:n #1 } }
-      { \@@_end_expandable_defaults:nw {#2} }
+    \tl_if_head_is_group:nTF {#1}
+      {
+        \@@_end_expandable_defaults_E:nnw { }
+          #1 \q_nil \q_mark
+          #2 \q_nil
+      }
+      {
+        \@@_if_no_value:nTF {#2}
+          { \exp_args:No \@@_end_expandable_defaults:nw { \use_none:n #1 } }
+          { \@@_end_expandable_defaults:nw {#2} }
+      }
   }
+\cs_new:Npn \@@_end_expandable_defaults_E:nnw #1#2#3 \q_mark #4
+  {
+    \quark_if_nil:nTF {#2}
+      { \@@_end_expandable_defaults:nw {#1} }
+      {
+        \@@_if_no_value:nTF {#4}
+          { \@@_end_expandable_defaults_E:nnw { #1 {#2} } }
+          { \@@_end_expandable_defaults_E:nnw { #1 {#4} } }
+        #3 \q_mark
+      }
+  }
 \cs_new:Npn \@@_end_expandable_defaults:nw
     #1#2 \@@_end_expandable_defaults:nnnNNn #3
   { #2 \@@_end_expandable_defaults:nnnNNn { #3 {#1} } }
@@ -1420,6 +1441,10 @@
 % \end{macro}
 % \end{macro}
 % \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
 %
 % \subsection{Normalizing the argument specifications}
 %
@@ -1438,7 +1463,7 @@
 % must be followed by arguments.
 %
 % The third is to check for forbidden types for expandable commands,
-% namely \texttt{e}, \texttt{E} (could be implemented), \texttt{g},
+% namely \texttt{g},
 % \texttt{G}, \texttt{l} (as the next left brace may have been inserted
 % by \pkg{xparse} due to a failed search for an optional argument),
 % \texttt{u} (any preceding optional argument may wrap part of the
@@ -1614,7 +1639,6 @@
     \tl_map_function:nN {#1} \@@_single_token_check:n
     \int_compare:nNnT { \tl_count:n {#2} } > { \tl_count:n {#1} }
       { \@@_bad_arg_spec:wn }
-    \@@_normalize_error_if_expandable:N E
     \tl_put_right:Nn \l_@@_arg_spec_tl { E {#1} {#2} }
     \tl_put_right:Nn \l_@@_last_delimiters_tl {#1}
     \@@_normalize_arg_spec_loop:n
@@ -1883,36 +1907,19 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_add_type_E:w}
-% \begin{macro}[aux]{\@@_add_type_E_aux:n}
-%   Pad the optional arguments with |-NoValue-| markers (and for
-%   technical reasons ensure the first optional argument is braced).
+%   The \texttt{E}-type argument needs a special handling of default
+%   values.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_add_type_E:w #1#2
   {
     \@@_flush_m_args:
-    \bool_set_true:N \l_@@_defaults_bool
-    \tl_set:Nx \l_@@_tmpa_tl
-      {
-        \exp_not:n {#2}
-        \prg_replicate:nn
-          { \tl_count:n {#1} - \tl_count:n {#2} }
-          { { \c_@@_no_value_tl } }
-      }
-    \tl_put_right:Nx \l_@@_defaults_tl
-      {
-        {
-          \exp_not:f
-            { \exp_after:wN \@@_add_type_E_aux:n \l_@@_tmpa_tl }
-        }
-      }
+    \@@_add_default_E:nn {#1} {#2}
     \@@_add_grabber_optional:N E
     \tl_put_right:Nn \l_@@_signature_tl { {#1} }
     \@@_prepare_signature:N
   }
-\cs_new:Npn \@@_add_type_E_aux:n #1 { {#1} }
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
 %
 % \begin{macro}{\@@_add_type_G:w}
 %   For the \texttt{G} type, the grabber and the default are added to the
@@ -2087,12 +2094,16 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\@@_add_default:n, \@@_add_default:}
+% \begin{macro}{\@@_add_default:n, \@@_add_default:, \@@_add_default_E:nn}
+% \begin{macro}[aux]{\@@_add_default_E_aux:n}
 %   Store the default value of an argument, or rather code that gives
 %   that default value (it may involve other arguments).  Defaults are
 %   always stored with a leading |.| except for \texttt{E}-type
-%   arguments, to distinguish them.
-%   This is also used by expandable functions.
+%   arguments, to distinguish them.  For \texttt{E}-type arguments, pad
+%   the defaults |#2| with some |{-NoValue-}| until there are the same
+%   numbers as embellishments~|#1|.  Then for technical reasons make
+%   sure the first default is wrapped in braces.  These functions are
+%   also used when defining expandable commands.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_add_default:n #1
   {
@@ -2101,8 +2112,28 @@
   }
 \cs_new_protected:Npn \@@_add_default:
   { \tl_put_right:Nn \l_@@_defaults_tl { . } }
+\cs_new_protected:Npn \@@_add_default_E:nn #1#2
+  {
+    \bool_set_true:N \l_@@_defaults_bool
+    \tl_set:Nx \l_@@_tmpa_tl
+      {
+        \exp_not:n {#2}
+        \prg_replicate:nn
+          { \tl_count:n {#1} - \tl_count:n {#2} }
+          { { \c_@@_no_value_tl } }
+      }
+    \tl_put_right:Nx \l_@@_defaults_tl
+      {
+        {
+          \exp_not:f
+            { \exp_after:wN \@@_add_default_E_aux:n \l_@@_tmpa_tl }
+        }
+      }
+  }
+\cs_new:Npn \@@_add_default_E_aux:n #1 { {#1} }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \subsection{Setting up expandable types}
 %
@@ -2183,6 +2214,42 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\@@_add_expandable_type_E:w}
+% \begin{macro}[aux]{\@@_add_expandable_type_E_aux:n}
+%   For each embellishment, use \cs{@@_get_grabber:NN} to obtain an
+%   auxiliary delimited by that token and store a pair constituted of
+%   the auxiliary and the token in \cs{l_@@_tmpb_tl}, before appending
+%   the whole set of these pairs to the signature, and an equal number
+%   of |-NoValue-| markers (regardless of the default values of
+%   arguments).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_E:w #1#2
+  {
+    \@@_add_default_E:nn {#1} {#2}
+    \@@_add_expandable_grabber:n { E }
+    \tl_clear:N \l_@@_tmpb_tl
+    \tl_map_function:nN {#1} \@@_add_expandable_type_E_aux:n
+    \tl_put_right:Nx \l_@@_signature_tl
+      {
+        { \exp_not:o \l_@@_tmpb_tl }
+        {
+          \prg_replicate:nn { \tl_count:n {#1} }
+            { { \c_@@_no_value_tl } }
+        }
+      }
+    \bool_set_false:N \l_@@_long_bool
+    \@@_prepare_signature:N
+  }
+\cs_new_protected:Npn \@@_add_expandable_type_E_aux:n #1
+  {
+    \@@_get_grabber:NN #1 \l_@@_tmpa_tl
+    \tl_put_right:Nx \l_@@_tmpb_tl
+      { \exp_not:o \l_@@_tmpa_tl \exp_not:N #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \begin{macro}{\@@_add_expandable_type_m:w}
 %   Unlike the standard case, when working expandably each argument is always
 %   grabbed separately.
@@ -3255,6 +3322,74 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}[EXP]{\@@_expandable_grab_E:w}
+% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_test:nnwn}
+% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_loop:nnnNNw}
+% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_aux:nnw}
+% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_aux:nnnnn}
+% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_end:nnw}
+%   The function will be called repeatedly with two arguments: the set
+%   of pairs \meta{parser} \meta{token}, and the set of arguments found
+%   so far (initially all |{-NoValue-}|).  At each step, grab what
+%   follows in the input stream then call the \texttt{loop:nnnNNwn}
+%   auxiliary to compare it with each possible embellishment in turn.
+%   This auxiliary's |#1| is what was found in the input, |#2| collects
+%   \meta{parser} \meta{token} pairs that did not match, |#3| collects
+%   the corresponding arguments found previously, |#4| and |#5| is the
+%   current pair, |#6| is the remaining pairs, |#7| is empty or two
+%   \cs{q_nil}, and |#8| is the current argument.  If none of the pairs
+%   matched (determined by \cs{quark_if_nil:NTF}) then call the
+%   \texttt{end} auxiliary to stop looking for embellishments,
+%   remembering to put what was grabbed in the input back where it
+%   belongs, and storing the arguments found just before \cs{q_@@}.  If
+%   the current argument |#8| is not |-NoValue-| or if the input |#1|
+%   does not match |#5| (see \texttt{t}-type arguments below for a
+%   similar \cs{str_if_eq:onTF} test) then carry on the loop.
+%   Otherwise, we found a new embellishment: grab the corresponding
+%   argument in the input using the \texttt{:w} auxiliary.  To avoid
+%   losing braces around that auxiliary's argument |#4| we include a
+%   space, which will be eliminated in the next loop through
+%   embellishments.
+%    \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_E:w #1 \q_@@ #2
+  { #2 { \@@_expandable_grab_E_test:nnwn #1 \q_@@ #2 } }
+\cs_new:Npn \@@_expandable_grab_E_test:nnwn #1#2#3 \q_@@ #4#5
+  {
+    \@@_expandable_grab_E_loop:nnnNNw {#5} { } { }
+      #1 \q_nil \q_nil \q_nil \q_mark #2 \q_nil
+    #3 \q_@@ #4
+  }
+\cs_new:Npn \@@_expandable_grab_E_loop:nnnNNw
+    #1#2#3#4#5#6 \q_nil #7 \q_mark #8
+  {
+    \quark_if_nil:NTF #4
+      { \@@_expandable_grab_E_end:nnw {#1} {#3} }
+      {
+        \@@_if_no_value:nTF {#8}
+          { \str_if_eq:onTF { #4 { } #1 #5 } {#5} }
+          { \use_ii:nn }
+            { \@@_expandable_grab_E_aux:w { #2 #4 #5 #6 } {#3} ~ }
+            {
+              \@@_expandable_grab_E_loop:nnnNNw
+                {#1} { #2 #4 #5 } { #3 {#8} }
+                #6 \q_nil #7 \q_mark
+            }
+      }
+  }
+\cs_new:Npn \@@_expandable_grab_E_aux:w #1 \q_@@ #2
+  { #2 { \@@_expandable_grab_E_aux:nnw #1 \q_@@ #2 } }
+\cs_new:Npn \@@_expandable_grab_E_aux:nnw #1#2#3 \q_nil #4 \q_@@ #5#6
+  { \@@_expandable_grab_E:w {#1} { #2 {#6} #3 } #4 \q_@@ #5 }
+\cs_new:Npn \@@_expandable_grab_E_end:nnw #1#2#3 \q_@@ #4
+  { #3 {#2} \q_@@ #4 {#1} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
 % \begin{macro}[EXP]{\@@_expandable_grab_m:w}
 % \begin{macro}[EXP, aux]{\@@_expandable_grab_m_aux:wNn}
 %   The mandatory case is easy: find the auxiliary after the \cs{q_@@}, and



More information about the latex3-commits mailing list