[latex3-commits] [git/LaTeX3-latex3-latex3] master: xparse: Allow spaces before trailing optionals (63d4fba)

Joseph Wright joseph.wright at morningstar2.co.uk
Tue Apr 17 18:48:03 CEST 2018


Repository : https://github.com/latex3/latex3
On branch  : master
Link       : https://github.com/latex3/latex3/commit/63d4fba4e16fa6b0bae0dcfcd22be19c2650f14f

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

commit 63d4fba4e16fa6b0bae0dcfcd22be19c2650f14f
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Tue Apr 17 17:48:03 2018 +0100

    xparse: Allow spaces before trailing optionals
    
    This adds a new "!" modifier to the syntax which applies to optional
    arguments. At present, it only does anything if the optional argument is
    also trailing: others are left alone. The logic of that is something
    like
    
        \DeclareDocumentCommand{\foo}{mom}{...}
        \foo{bar} [baz] {bop}
    
    has to find a second mandatory, and grabbing "[" here as #3 would be
    pretty strange.
    
    What happens with multiple trailing optionals is not entirely clear.
    I've gone for "!" applying on a per-argument basis, but that is only one
    way of setting it up.


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

63d4fba4e16fa6b0bae0dcfcd22be19c2650f14f
 l3packages/xparse/testfiles/xparse001.ptex.tlg   |    8 +-
 l3packages/xparse/testfiles/xparse001.tlg        |    8 +-
 l3packages/xparse/testfiles/xparse001.uptex.tlg  |    8 +-
 l3packages/xparse/testfiles/xparse002.luatex.tlg |   94 +++++++++++++++++---
 l3packages/xparse/testfiles/xparse002.lvt        |   64 ++++++++++++++
 l3packages/xparse/testfiles/xparse002.tlg        |   94 +++++++++++++++++---
 l3packages/xparse/xparse.dtx                     |  100 ++++++++++++++++------
 7 files changed, 316 insertions(+), 60 deletions(-)

diff --git a/l3packages/xparse/testfiles/xparse001.ptex.tlg b/l3packages/xparse/testfiles/xparse001.ptex.tlg
index 448ac5f..c654f5e 100644
--- a/l3packages/xparse/testfiles/xparse001.ptex.tlg
+++ b/l3packages/xparse/testfiles/xparse001.ptex.tlg
@@ -592,7 +592,7 @@ l. ...}
 .................................................
 > \foo=\protected macro:->\__xparse_start:nNNnnn {momo}\foo  \foo code
 {\__xparse_grab_m_1:w \__xparse_grab_D:w []\__xparse_grab_m_1:w
-\__xparse_grab_D_trailing:w []}{}{}.
+\__xparse_grab_D:w []}{}{}.
 <recently read> }
 l. ...}
 > \foo code=\protected\long macro:#1#2#3#4->(#1)(#2)(#3)(#4).
@@ -1006,8 +1006,8 @@ l. ...}
 . Redefining environment 'foo' with sig. 'moo' on line ....
 .................................................
 > \environment foo=\protected macro:->\__xparse_start:nNNnnn {moo}\environment
-foo  \environment foo code {\__xparse_grab_m_1:w \__xparse_grab_D_trailing:w
-[]\__xparse_grab_D_trailing:w []}{}{}.
+foo  \environment foo code {\__xparse_grab_m_1:w \__xparse_grab_D:w
+[]\__xparse_grab_D:w []}{}{}.
 <recently read> }
 l. ...}
 > \environment foo code=\protected\long macro:#1#2#3->\cs_set_nopar:Npx
@@ -1228,7 +1228,7 @@ TEST 19: (ab)using xparse commands in csnames
 l. ...  }
 The control sequence marked <to be read again> should
 not appear between \csname and \endcsname.
-\test- \xparse function is not expandable \__xparse_start_aux:nNNnnn {D...}\foo code {\__xparse_grab_D_trailing:w ..}{{.}}{}....\cs_end: 
+\test- \xparse function is not expandable \__xparse_start_aux:nNNnnn {D...}\foo code {\__xparse_grab_D:w ..}{{.}}{}....\cs_end: 
 ============================================================
 ============================================================
 TEST 20: Checking for existing expandable definitions
diff --git a/l3packages/xparse/testfiles/xparse001.tlg b/l3packages/xparse/testfiles/xparse001.tlg
index 6b29e6b..2b00ced 100644
--- a/l3packages/xparse/testfiles/xparse001.tlg
+++ b/l3packages/xparse/testfiles/xparse001.tlg
@@ -592,7 +592,7 @@ l. ...}
 .................................................
 > \foo=\protected macro:->\__xparse_start:nNNnnn {momo}\foo  \foo code
 {\__xparse_grab_m_1:w \__xparse_grab_D:w []\__xparse_grab_m_1:w
-\__xparse_grab_D_trailing:w []}{}{}.
+\__xparse_grab_D:w []}{}{}.
 <recently read> }
 l. ...}
 > \foo code=\protected\long macro:#1#2#3#4->(#1)(#2)(#3)(#4).
@@ -1006,8 +1006,8 @@ l. ...}
 . Redefining environment 'foo' with sig. 'moo' on line ....
 .................................................
 > \environment foo=\protected macro:->\__xparse_start:nNNnnn {moo}\environment
-foo  \environment foo code {\__xparse_grab_m_1:w \__xparse_grab_D_trailing:w
-[]\__xparse_grab_D_trailing:w []}{}{}.
+foo  \environment foo code {\__xparse_grab_m_1:w \__xparse_grab_D:w
+[]\__xparse_grab_D:w []}{}{}.
 <recently read> }
 l. ...}
 > \environment foo code=\protected\long macro:#1#2#3->\cs_set_nopar:Npx
@@ -1218,7 +1218,7 @@ TEST 19: (ab)using xparse commands in csnames
 l. ...  }
 The control sequence marked <to be read again> should
 not appear between \csname and \endcsname.
-\test- \xparse function is not expandable \__xparse_start_aux:nNNnnn {D...}\foo code {\__xparse_grab_D_trailing:w ..}{{.}}{}....\cs_end: 
+\test- \xparse function is not expandable \__xparse_start_aux:nNNnnn {D...}\foo code {\__xparse_grab_D:w ..}{{.}}{}....\cs_end: 
 ============================================================
 ============================================================
 TEST 20: Checking for existing expandable definitions
diff --git a/l3packages/xparse/testfiles/xparse001.uptex.tlg b/l3packages/xparse/testfiles/xparse001.uptex.tlg
index 448ac5f..c654f5e 100644
--- a/l3packages/xparse/testfiles/xparse001.uptex.tlg
+++ b/l3packages/xparse/testfiles/xparse001.uptex.tlg
@@ -592,7 +592,7 @@ l. ...}
 .................................................
 > \foo=\protected macro:->\__xparse_start:nNNnnn {momo}\foo  \foo code
 {\__xparse_grab_m_1:w \__xparse_grab_D:w []\__xparse_grab_m_1:w
-\__xparse_grab_D_trailing:w []}{}{}.
+\__xparse_grab_D:w []}{}{}.
 <recently read> }
 l. ...}
 > \foo code=\protected\long macro:#1#2#3#4->(#1)(#2)(#3)(#4).
@@ -1006,8 +1006,8 @@ l. ...}
 . Redefining environment 'foo' with sig. 'moo' on line ....
 .................................................
 > \environment foo=\protected macro:->\__xparse_start:nNNnnn {moo}\environment
-foo  \environment foo code {\__xparse_grab_m_1:w \__xparse_grab_D_trailing:w
-[]\__xparse_grab_D_trailing:w []}{}{}.
+foo  \environment foo code {\__xparse_grab_m_1:w \__xparse_grab_D:w
+[]\__xparse_grab_D:w []}{}{}.
 <recently read> }
 l. ...}
 > \environment foo code=\protected\long macro:#1#2#3->\cs_set_nopar:Npx
@@ -1228,7 +1228,7 @@ TEST 19: (ab)using xparse commands in csnames
 l. ...  }
 The control sequence marked <to be read again> should
 not appear between \csname and \endcsname.
-\test- \xparse function is not expandable \__xparse_start_aux:nNNnnn {D...}\foo code {\__xparse_grab_D_trailing:w ..}{{.}}{}....\cs_end: 
+\test- \xparse function is not expandable \__xparse_start_aux:nNNnnn {D...}\foo code {\__xparse_grab_D:w ..}{{.}}{}....\cs_end: 
 ============================================================
 ============================================================
 TEST 20: Checking for existing expandable definitions
diff --git a/l3packages/xparse/testfiles/xparse002.luatex.tlg b/l3packages/xparse/testfiles/xparse002.luatex.tlg
index c4e966d..92a916f 100644
--- a/l3packages/xparse/testfiles/xparse002.luatex.tlg
+++ b/l3packages/xparse/testfiles/xparse002.luatex.tlg
@@ -42,7 +42,7 @@ TEST 1: Basic definitions with valid arguments (types s, o m)
 . Redefining command \foo with sig. 'mmo' on line ....
 .................................................
 (j)(k)(opt)
-(j)(k)(-NoValue-)
+(j)(k)(not-opt)
 (j)(k)(-NoValue-)
 .................................................
 . LaTeX info: "xparse/redefine-command"
@@ -167,7 +167,7 @@ TEST 4: More variation of type with valid arguments
 .................................................
 (d)(e)(default)
 (d)(e)(text)
-(d)(e)(default)
+(d)(e)(text)
 .................................................
 . LaTeX info: "xparse/redefine-command"
 . 
@@ -300,10 +300,84 @@ FALSE
 .................................................
 FALSE
 TRUE
+TRUE
+============================================================
+============================================================
+TEST 7: Trailing optional arguments
+============================================================
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \foo with sig. 'mo' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'm!o' on line ....
+.................................................
+FALSE
+TRUE
+FALSE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'm!oo' on line ....
+.................................................
+FALSE FALSE
+TRUE FALSE
+TRUE TRUE
+TRUE TRUE
+FALSE TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'mo!o' on line ....
+.................................................
+FALSE FALSE
+TRUE FALSE
+TRUE TRUE
+TRUE FALSE
+TRUE FALSE
+TRUE TRUE
+TRUE FALSE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'o' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. '!o' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \\ with sig. 'o' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \\ with sig. '!o' on line ....
+.................................................
+FALSE
+TRUE
 FALSE
 ============================================================
 ============================================================
-TEST 7: Awkward `NoValue' checks (expect T/F/F/F/F)
+TEST 8: Awkward `NoValue' checks (expect T/F/F/F/F)
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -317,7 +391,7 @@ FALSE
 FALSE
 ============================================================
 ============================================================
-TEST 8: Nested optional arguments
+TEST 9: Nested optional arguments
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -353,7 +427,7 @@ l. ...}
 l. ...}
 ============================================================
 ============================================================
-TEST 9: Processing arguments
+TEST 10: Processing arguments
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -367,14 +441,14 @@ TEST 9: Processing arguments
 . LaTeX info: "xparse/redefine-command"
 . 
 . Redefining command \foo with sig. '>{\SplitArgument {1}{,}}D(){0,0}' on line
-. 179.
+. 243.
 .................................................
 1,2
 0,0
 3,-NoValue-
 ============================================================
 ============================================================
-TEST 10: Optional argument tests expand (expect T/F/F/F/T)
+TEST 11: Optional argument tests expand (expect T/F/F/F/T)
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -403,7 +477,7 @@ l. ...}
 l. ...}
 ============================================================
 ============================================================
-TEST 11: Fully expandable functions
+TEST 12: Fully expandable functions
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -433,7 +507,7 @@ TEST 11: Fully expandable functions
 (a)(b)(c)(d)
 ============================================================
 ============================================================
-TEST 12: Fully expandable long functions
+TEST 13: Fully expandable long functions
 ============================================================
 (\par )(b)
 (-NoValue-)(\par )
@@ -448,7 +522,7 @@ TEST 12: Fully expandable long functions
 (\par )(\par )(\par )(\par )
 ============================================================
 ============================================================
-TEST 13: More tricky expandable tests
+TEST 14: More tricky expandable tests
 ============================================================
 ()(b)
 ()(b)
diff --git a/l3packages/xparse/testfiles/xparse002.lvt b/l3packages/xparse/testfiles/xparse002.lvt
index 5b39987..db8d18a 100644
--- a/l3packages/xparse/testfiles/xparse002.lvt
+++ b/l3packages/xparse/testfiles/xparse002.lvt
@@ -132,6 +132,70 @@
   \foo { foo } ~ +
 }
 
+\TEST { Trailing~optional~arguments }
+  {
+    \DeclareDocumentCommand \foo { m o }
+      { \IfNoValueTF {#2} \FALSE \TRUE  }
+    \foo { foo }
+    \foo { foo } [ more ]
+    \foo { foo } ~ [ more ]
+    \DeclareDocumentCommand \foo { m !o }
+      { \IfNoValueTF {#2} \FALSE \TRUE }
+    \foo { foo }
+    \foo { foo } [ more ]
+    \foo { foo } ~ [ more ]
+    \DeclareDocumentCommand \foo { m !o o }
+      {
+        \LONGTYPEOUT
+          {
+            \IfNoValueTF {#2} { FALSE } { TRUE }
+            \c_space_tl
+            \IfNoValueTF {#3} { FALSE } { TRUE }
+          }
+      }
+    \foo { foo }
+    \foo { foo } [ more ]
+    \foo { foo } [ more ] [ more ]
+    \foo { foo } [ more ] ~ [ more ]
+    \foo { foo } ~ [ more ]
+    \DeclareDocumentCommand \foo { m o !o }
+      {
+        \LONGTYPEOUT
+          {
+            \IfNoValueTF {#2} { FALSE } { TRUE }
+            \c_space_tl
+            \IfNoValueTF {#3} { FALSE } { TRUE }
+          }
+      }
+    \foo { foo }
+    \foo { foo } [ more ]
+    \foo { foo } [ more ] [ more ]
+    \foo { foo } [ more ] ~ [ more ]
+    \foo { foo } ~ [ more ]
+    \foo { foo } ~ [ more ] [ more ]
+    \foo { foo } ~ [ more ] ~ [ more ]
+    \DeclareDocumentCommand \foo { o }
+      { \IfNoValueTF {#1} \FALSE \TRUE }
+    \foo
+    \foo [ more ]
+    \foo ~ [ more ]
+    \DeclareDocumentCommand \foo { !o }
+      { \IfNoValueTF {#1} \FALSE \TRUE }
+    \foo
+    \foo [ more ]
+    \foo ~ [ more ]
+    \DeclareDocumentCommand \\ { o }
+      { \IfNoValueTF {#1} \FALSE \TRUE }
+    \\
+    \\ [ more ]
+    \\ ~ [ more ]
+    \DeclareDocumentCommand \\ { !o }
+      { \IfNoValueTF {#1} \FALSE \TRUE }
+    \\
+    \\ [ more ]
+    \\ ~ [ more ]
+  }
+
 \TEST{Awkward~`NoValue'~checks~(expect~T/F/F/F/F)}{
   \DeclareDocumentCommand \foo { o m }
     { \IfNoValueTF {#1} \TRUE \FALSE }
diff --git a/l3packages/xparse/testfiles/xparse002.tlg b/l3packages/xparse/testfiles/xparse002.tlg
index d91856f..f9bb4e1 100644
--- a/l3packages/xparse/testfiles/xparse002.tlg
+++ b/l3packages/xparse/testfiles/xparse002.tlg
@@ -42,7 +42,7 @@ TEST 1: Basic definitions with valid arguments (types s, o m)
 . Redefining command \foo with sig. 'mmo' on line ....
 .................................................
 (j)(k)(opt)
-(j)(k)(-NoValue-)
+(j)(k)(not-opt)
 (j)(k)(-NoValue-)
 .................................................
 . LaTeX info: "xparse/redefine-command"
@@ -167,7 +167,7 @@ TEST 4: More variation of type with valid arguments
 .................................................
 (d)(e)(default)
 (d)(e)(text)
-(d)(e)(default)
+(d)(e)(text)
 .................................................
 . LaTeX info: "xparse/redefine-command"
 . 
@@ -300,10 +300,84 @@ FALSE
 .................................................
 FALSE
 TRUE
+TRUE
+============================================================
+============================================================
+TEST 7: Trailing optional arguments
+============================================================
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \foo with sig. 'mo' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'm!o' on line ....
+.................................................
+FALSE
+TRUE
+FALSE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'm!oo' on line ....
+.................................................
+FALSE FALSE
+TRUE FALSE
+TRUE TRUE
+TRUE TRUE
+FALSE TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'mo!o' on line ....
+.................................................
+FALSE FALSE
+TRUE FALSE
+TRUE TRUE
+TRUE FALSE
+TRUE FALSE
+TRUE TRUE
+TRUE FALSE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. 'o' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \foo with sig. '!o' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \\ with sig. 'o' on line ....
+.................................................
+FALSE
+TRUE
+TRUE
+.................................................
+. LaTeX info: "xparse/redefine-command"
+. 
+. Redefining command \\ with sig. '!o' on line ....
+.................................................
+FALSE
+TRUE
 FALSE
 ============================================================
 ============================================================
-TEST 7: Awkward `NoValue' checks (expect T/F/F/F/F)
+TEST 8: Awkward `NoValue' checks (expect T/F/F/F/F)
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -317,7 +391,7 @@ FALSE
 FALSE
 ============================================================
 ============================================================
-TEST 8: Nested optional arguments
+TEST 9: Nested optional arguments
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -353,7 +427,7 @@ l. ...}
 l. ...}
 ============================================================
 ============================================================
-TEST 9: Processing arguments
+TEST 10: Processing arguments
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -367,14 +441,14 @@ TEST 9: Processing arguments
 . LaTeX info: "xparse/redefine-command"
 . 
 . Redefining command \foo with sig. '>{\SplitArgument {1}{,}}D(){0,0}' on line
-. 179.
+. 243.
 .................................................
 1,2
 0,0
 3,-NoValue-
 ============================================================
 ============================================================
-TEST 10: Optional argument tests expand (expect T/F/F/F/T)
+TEST 11: Optional argument tests expand (expect T/F/F/F/T)
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -403,7 +477,7 @@ l. ...}
 l. ...}
 ============================================================
 ============================================================
-TEST 11: Fully expandable functions
+TEST 12: Fully expandable functions
 ============================================================
 .................................................
 . LaTeX info: "xparse/define-command"
@@ -433,7 +507,7 @@ TEST 11: Fully expandable functions
 (a)(b)(c)(d)
 ============================================================
 ============================================================
-TEST 12: Fully expandable long functions
+TEST 13: Fully expandable long functions
 ============================================================
 (\par )(b)
 (-NoValue-)(\par )
@@ -448,7 +522,7 @@ TEST 12: Fully expandable long functions
 (\par )(\par )(\par )(\par )
 ============================================================
 ============================================================
-TEST 13: More tricky expandable tests
+TEST 14: More tricky expandable tests
 ============================================================
 ()(b)
 ()(b)
diff --git a/l3packages/xparse/xparse.dtx b/l3packages/xparse/xparse.dtx
index ef5a95c..cf5e3d3 100644
--- a/l3packages/xparse/xparse.dtx
+++ b/l3packages/xparse/xparse.dtx
@@ -263,20 +263,31 @@
 % \end{verbatim}
 % the user input |\foo{arg1}[arg2]{arg3}| and
 % \verb*|\foo{arg1}  [arg2]   {arg3}| will both be parsed in the same
-% way. However, spaces are \emph{not} ignored when parsing optional
-% arguments after the last mandatory argument. Thus with
+% way.
+% 
+% The behavior of optional arguments \emph{after} any mandatory arguments is
+% selectable. The standard settings will allow spaces here, and thus
+% with
 % \begin{verbatim}
 %   \NewDocumentCommand \foobar { m o } { ... }
 % \end{verbatim}
-% |\foobar{arg1}[arg2]| will find an optional argument but
-% \verb*|\foobar{arg1} [arg2]| will not. This is so that trailing optional
-% arguments are not picked up \enquote{by accident} in input.
-%
-% There is one major exception to the rules listed above: when
-% \pkg{xparse} is used to define what \TeX\ defines as \enquote{control
-% symbols} in which the function name is made up of a single character,
-% such as \enquote{\cmd{\\}}, spaces are \emph{not} ignored directly
-% after them even for mandatory arguments.
+% both |\foobar{arg1}[arg2]| and \verb*|\foobar{arg1} [arg2]| will find an
+% optional argument. This can be changed by giving the modified |!| in
+% the argument specification:
+% \begin{verbatim}
+%   \NewDocumentCommand \foobar { m !o } { ... }
+% \end{verbatim}
+% where \verb*|\foobar{arg1} [arg2]| will not find an optional argument.
+%
+% There is one subtly here due to the difference in handling by \TeX{}
+% of \enquote{control symbols}, where the command name is made up of a single
+% character, such as \enquote{\cmd{\\}}. Spaces are not ignored by \TeX{}
+% here, and thus it is possible to require an optional argument directly
+% follow such a command. The most common example is the use of \cmd{\\} in
+% \pkg{amsmath} environments. In \pkg{xparse} terms it has signature
+% \begin{verbatim}
+%   \DeclareDocumentCommad \\ { !s !o } { ... }
+% \end{verbatim}
 %
 % \subsection{Required delimited arguments}
 %
@@ -949,6 +960,13 @@
 %    \end{macrocode}
 % \end{variable}
 %
+% \begin{variable}{\l_@@_ignore_spaces_bool}
+%   For trailing optionals.
+%    \begin{macrocode}
+\bool_new:N \l_@@_ignore_spaces_bool
+%    \end{macrocode}
+% \end{variable}
+%
 % \begin{variable}{\l_@@_m_args_int}
 %   The number of \texttt{m} arguments: if this is the same as the total
 %   number of arguments, then a short-cut can be taken in the creation of
@@ -1547,6 +1565,7 @@
     \bool_set_false:N \l_@@_long_bool
     \bool_set_false:N \l_@@_some_long_bool
     \bool_set_false:N \l_@@_some_short_bool
+    \bool_set_false:N \l_@@_ignore_spaces_bool
     \@@_normalize_arg_spec_loop:n #1
       \q_recursion_tail \q_recursion_tail \q_recursion_tail \q_recursion_stop
     \int_compare:nNnT \l_@@_current_arg_int > 9
@@ -1635,6 +1654,7 @@
 %   {
 %     \@@_normalize_type_>:w,
 %     \@@_normalize_type_+:w,
+%     \@@_normalize_type_!:w,
 %   }
 %   Check that these prefixes have arguments, namely that the next token
 %   is not \cs{q_recursion_tail}, and remember to leave it after the
@@ -1665,6 +1685,13 @@
     \int_decr:N \l_@@_current_arg_int
     \@@_normalize_arg_spec_loop:n {#1}
   }
+\cs_new_protected:cpn { @@_normalize_type_!:w } #1
+  {
+    \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn }
+    \tl_put_right:Nn \l_@@_arg_spec_tl { ! }
+    \int_decr:N \l_@@_current_arg_int
+    \@@_normalize_arg_spec_loop:n {#1}
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1943,6 +1970,7 @@
   {
     \int_zero:N \l_@@_current_arg_int
     \bool_set_false:N \l_@@_long_bool
+    \bool_set_false:N \l_@@_ignore_spaces_bool
     \int_zero:N \l_@@_m_args_int
     \bool_set_false:N \l_@@_defaults_bool
     \tl_clear:N \l_@@_defaults_tl
@@ -2011,6 +2039,19 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_add_type_!:w}
+%   Much the same for controlling trailing optional arguments.
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_add_type_!:w }
+  {
+    \@@_flush_m_args:
+    \bool_set_true:N \l_@@_ignore_spaces_bool
+    \bool_set_true:N \l_@@_prefixed_bool
+    \@@_prepare_signature_bypass:N
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\@@_add_type_>:w}
 %   When a processor is found, the processor code is stored.  It will be
 %   used by \cs{@@_args_process:} once arguments are all found. Here,
@@ -2215,12 +2256,15 @@
           {
             @@_grab_ #1
             \bool_if:NT \l_@@_long_bool { _long }
-            \int_compare:nNnF \l_@@_mandatory_args_int > 0
-              { _trailing }
+            \bool_lazy_and:nnT
+              { \l_@@_ignore_spaces_bool }
+              { \int_compare_p:nNn \l_@@_mandatory_args_int = 0 }
+              { _ignore_spaces }
             :w
           }
       }
     \bool_set_false:N \l_@@_long_bool
+    \bool_set_false:N \l_@@_ignore_spaces_bool
     \tl_put_right:Nx \l_@@_process_all_tl
       { { \exp_not:o \l_@@_process_one_tl } }
     \tl_clear:N \l_@@_process_one_tl
@@ -2518,8 +2562,8 @@
 %
 % \begin{macro}{\@@_grab_D:w}
 % \begin{macro}{\@@_grab_D_long:w}
-% \begin{macro}{\@@_grab_D_trailing:w}
-% \begin{macro}{\@@_grab_D_long_trailing:w}
+% \begin{macro}{\@@_grab_D_ignore_spaces:w}
+% \begin{macro}{\@@_grab_D_long_ignore_spaces:w}
 %   The generic delimited argument grabber. The auxiliary function does
 %   a peek test before calling \cs{@@_grab_D_call:Nw}, so that the
 %   optional nature of the argument works as expected.
@@ -2534,9 +2578,9 @@
     \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected:Npn
       { _ignore_spaces }
   }
-\cs_new_protected:Npn \@@_grab_D_trailing:w #1#2#3 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_D_ignore_spaces:w #1#2#3 \@@_run_code:
   { \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected_nopar:Npn { } }
-\cs_new_protected:Npn \@@_grab_D_long_trailing:w #1#2#3 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_D_long_ignore_spaces:w #1#2#3 \@@_run_code:
   { \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected:Npn { } }
 %    \end{macrocode}
 % \begin{macro}{\@@_grab_D_aux:NNnNn}
@@ -2688,7 +2732,7 @@
 % \begin{macro}
 %   {
 %     \@@_grab_E:w, \@@_grab_E_long:w,
-%     \@@_grab_E_trailing:w, \@@_grab_E_long_trailing:w
+%     \@@_grab_E_ignore_spaces:w, \@@_grab_E_long_ignore_spaces:w
 %   }
 % \begin{macro}{\@@_grab_E:nnNn}
 % \begin{macro}{\@@_grab_E_loop:nnN}
@@ -2707,13 +2751,13 @@
       \cs_set_protected:Npn
       { _ignore_spaces }
   }
-\cs_new_protected:Npn \@@_grab_E_trailing:w #1#2 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_E_ignore_spaces:w #1#2 \@@_run_code:
   {
     \@@_grab_E:nnNn {#1} {#2}
       \cs_set_protected_nopar:Npn
       { }
   }
-\cs_new_protected:Npn \@@_grab_E_long_trailing:w #1#2 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_E_long_ignore_spaces:w #1#2 \@@_run_code:
   {
     \@@_grab_E:nnNn {#1} {#2}
       \cs_set_protected:Npn
@@ -2766,8 +2810,8 @@
 %
 % \begin{macro}{\@@_grab_G:w}
 % \begin{macro}{\@@_grab_G_long:w}
-% \begin{macro}{\@@_grab_G_trailing:w}
-% \begin{macro}{\@@_grab_G_long_trailing:w}
+% \begin{macro}{\@@_grab_G_ignore_spaces:w}
+% \begin{macro}{\@@_grab_G_long_ignore_spaces:w}
 % \begin{macro}{\@@_grab_G_aux:nNn}
 %   Optional groups are checked by meaning, so that the same code will
 %   work with, for example, \ConTeXt{}-like input.
@@ -2781,9 +2825,9 @@
   {
     \@@_grab_G_aux:nNn {#1} \cs_set_protected:Npn { _ignore_spaces }
   }
-\cs_new_protected:Npn \@@_grab_G_trailing:w #1 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_G_ignore_spaces:w #1 \@@_run_code:
   { \@@_grab_G_aux:nNn {#1} \cs_set_protected_nopar:Npn { } }
-\cs_new_protected:Npn \@@_grab_G_long_trailing:w #1 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_G_long_ignore_spaces:w #1 \@@_run_code:
   { \@@_grab_G_aux:nNn {#1} \cs_set_protected:Npn { } }
 \cs_new_protected:Npn \@@_grab_G_aux:nNn #1#2#3
   {
@@ -2958,8 +3002,8 @@
 %
 % \begin{macro}{\@@_grab_t:w}
 % \begin{macro}{\@@_grab_t_long:w}
-% \begin{macro}{\@@_grab_t_trailing:w}
-% \begin{macro}{\@@_grab_t_long_trailing:w}
+% \begin{macro}{\@@_grab_t_ignore_spaces:w}
+% \begin{macro}{\@@_grab_t_long_ignore_spaces:w}
 % \begin{macro}{\@@_grab_t_aux:NNw}
 %   Dealing with a token is quite easy. Check the match, remove the
 %   token if needed and add a flag to the output.
@@ -2967,9 +3011,9 @@
 \cs_new_protected:Npn \@@_grab_t:w
   { \@@_grab_t_aux:NNw \peek_meaning_remove_ignore_spaces:NTF }
 \cs_new_eq:NN \@@_grab_t_long:w \@@_grab_t:w
-\cs_new_protected:Npn \@@_grab_t_trailing:w
+\cs_new_protected:Npn \@@_grab_t_ignore_spaces:w
   { \@@_grab_t_aux:NNw \peek_meaning_remove:NTF }
-\cs_new_eq:NN \@@_grab_t_long_trailing:w \@@_grab_t_trailing:w
+\cs_new_eq:NN \@@_grab_t_long_ignore_spaces:w \@@_grab_t_ignore_spaces:w
 \cs_new_protected:Npn \@@_grab_t_aux:NNw #1#2#3 \@@_run_code:
   {
     \tl_set:Nn \l_@@_signature_tl {#3}





More information about the latex3-commits mailing list