[latex3-commits] [git/LaTeX3-latex3-latex3] master: Put spaces back when trailing optional arg is absent (fixes #466) (36d2b87)

Bruno Le Floch bruno at le-floch.fr
Sun Sep 23 23:24:05 CEST 2018


Repository : https://github.com/latex3/latex3
On branch  : master
Link       : https://github.com/latex3/latex3/commit/36d2b8749a893be3415f2a731c153149c21b8ca1

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

commit 36d2b8749a893be3415f2a731c153149c21b8ca1
Author: Bruno Le Floch <bruno at le-floch.fr>
Date:   Sun Sep 23 21:50:35 2018 +0200

    Put spaces back when trailing optional arg is absent (fixes #466)
    
    Simply code a variant of the ignore_spaces peek functions as an
    auxiliary in xparse.


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

36d2b8749a893be3415f2a731c153149c21b8ca1
 l3packages/CHANGELOG.md                   |    3 +
 l3packages/xparse/testfiles/xparse005.lvt |   56 ++++++++
 l3packages/xparse/testfiles/xparse005.tlg |  196 +++++++++++++++++++++++++++
 l3packages/xparse/xparse.dtx              |  207 ++++++++++++++++-------------
 4 files changed, 369 insertions(+), 93 deletions(-)

diff --git a/l3packages/CHANGELOG.md b/l3packages/CHANGELOG.md
index bb08e57..4173ec7 100644
--- a/l3packages/CHANGELOG.md
+++ b/l3packages/CHANGELOG.md
@@ -7,6 +7,9 @@ this project uses date-based 'snapshot' version identifiers.
 
 ## [Unreleased]
 
+### Changed
+- `xparse`: put spaces back when a trailing optional arg is absent (fixes #466)
+
 ## [2018-08-23]
 
 ### Added
diff --git a/l3packages/xparse/testfiles/xparse005.lvt b/l3packages/xparse/testfiles/xparse005.lvt
new file mode 100644
index 0000000..91f2959
--- /dev/null
+++ b/l3packages/xparse/testfiles/xparse005.lvt
@@ -0,0 +1,56 @@
+%
+% Copyright (C) 2018 LaTeX3 Project
+%
+
+\documentclass{minimal}
+\input{regression-test}
+
+\RequirePackage[enable-debug]{expl3}
+\ExplSyntaxOn
+\debug_on:n { check-declarations , deprecation , log-functions }
+\ExplSyntaxOff
+\RequirePackage{xparse}
+
+\begin{document}
+
+\START
+\AUTHOR{Bruno Le Floch}
+
+\ExplSyntaxOn
+
+\TEST { Invalid~'!' }
+  {
+    \NewDocumentCommand { \testA } { ! u{.} } { }
+    \NewDocumentCommand { \testA } { ! o r() } { }
+    \NewDocumentCommand { \testA } { ! + o m } { }
+    \NewDocumentCommand { \testA } { ! ! o } { }
+    \NewDocumentCommand { \testA } { ! + ! } { }
+    \NewDocumentCommand { \testA } { + ! } { }
+    \NewDocumentCommand { \testA } { ! } { }
+  }
+
+\OMIT
+\cs_new_protected:Npn \test:nw #1 #2 \q_stop
+  { \TYPE { \tl_to_str:n { | #1 | #2 | } } }
+\TIMO
+
+\TEST { Valid~'!'~and~avoid~dropping~spaces }
+  {
+    \NewDocumentCommand { \testA } { m ! + o o }
+      { \test:nw { #1 | #2 | #3 } }
+    \testA \par \use_none:nn \ERROR \q_stop
+    \testA {a} ~ [b] \q_stop
+    \testA {a} [b] ~ \c_space_token \q_stop
+    \testA {a} [b] \c_space_token [d] \q_stop
+    \use:x { \testA {a} [b] ~ \c_space_tl [c[d]] ~ \c_space_token } \q_stop
+    \NewDocumentCommand { \testB } { m ! + s s }
+      { \test:nw { #1 | #2 | #3 } }
+    \testB \par \use_none:nn \ERROR \q_stop
+    \testB {a} ~ * \q_stop
+    \testB {a} * ~ \c_space_token \q_stop
+    \testB {a} * \c_space_token * \q_stop
+    \use:x { \testB {a} * ~ \c_space_tl * ~ \c_space_token } \q_stop
+  }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\END
diff --git a/l3packages/xparse/testfiles/xparse005.tlg b/l3packages/xparse/testfiles/xparse005.tlg
new file mode 100644
index 0000000..f2ff29f
--- /dev/null
+++ b/l3packages/xparse/testfiles/xparse005.tlg
@@ -0,0 +1,196 @@
+This is a generated file for the LaTeX (2e + expl3) validation system.
+Don't change this file in any respect.
+Author: Bruno Le Floch
+============================================================
+TEST 1: Invalid '!'
+============================================================
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. '!u{.}' on line ....
+.................................................
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "xparse/non-trailing-obey-spaces"
+! 
+! Prefix '!' used before mandatory argument 'u{.}' of command '\testA'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| The prefix '!' can only apply to trailing optional arguments.
+| 
+| LaTeX will ignore this entire definition.
+|...............................................
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. '!or()' on line ....
+.................................................
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "xparse/non-trailing-obey-spaces"
+! 
+! Prefix '!' used before mandatory argument 'R(){-NoValue-}' of command
+! '\testA'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| The prefix '!' can only apply to trailing optional arguments.
+| 
+| LaTeX will ignore this entire definition.
+|...............................................
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. '!+om' on line ....
+.................................................
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "xparse/non-trailing-obey-spaces"
+! 
+! Prefix '!' used before mandatory argument 'm' of command '\testA'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| The prefix '!' can only apply to trailing optional arguments.
+| 
+| LaTeX will ignore this entire definition.
+|...............................................
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. '!!o' on line ....
+.................................................
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "xparse/two-markers"
+! 
+! Two '!' apply to the same argument in argument specification of command
+! '\testA'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| The argument specification provided has two markers '!' applying to the same
+| argument; these are redundant.
+|...............................................
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. '!+!' on line ....
+.................................................
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "xparse/bad-arg-spec"
+! 
+! Bad argument specification '!+!' for command '\testA'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| The argument specification provided was not valid: one or more mandatory
+| pieces of information were missing.
+| 
+| LaTeX will ignore this entire definition.
+|...............................................
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. '+!' on line ....
+.................................................
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "xparse/bad-arg-spec"
+! 
+! Bad argument specification '+!' for command '\testA'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| The argument specification provided was not valid: one or more mandatory
+| pieces of information were missing.
+| 
+| LaTeX will ignore this entire definition.
+|...............................................
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. '!' on line ....
+.................................................
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "xparse/bad-arg-spec"
+! 
+! Bad argument specification '!' for command '\testA'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| The argument specification provided was not valid: one or more mandatory
+| pieces of information were missing.
+| 
+| LaTeX will ignore this entire definition.
+|...............................................
+============================================================
+============================================================
+TEST 2: Valid '!' and avoid dropping spaces
+============================================================
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testA with sig. 'm!+oo' on line ....
+.................................................
+Runaway argument?
+! Paragraph ended before \testA  was complete.
+<to be read again> 
+                   \par 
+l. ...  }
+I suspect you've forgotten a `}', causing me to apply this
+control sequence to too much text. How can we recover?
+My plan is to forget the whole thing and hope for the best.
+|a|-NoValue-|b||
+|a|b|-NoValue-|  |
+|a|b|d||
+|a|b|c[d]| \c_space_token |
+.................................................
+. LaTeX info: "xparse/define-command"
+. 
+. Defining command \testB with sig. 'm!+ss' on line ....
+.................................................
+Runaway argument?
+! Paragraph ended before \testB  was complete.
+<to be read again> 
+                   \par 
+l. ...  }
+I suspect you've forgotten a `}', causing me to apply this
+control sequence to too much text. How can we recover?
+My plan is to forget the whole thing and hope for the best.
+|a|\BooleanFalse |\BooleanTrue ||
+|a|\BooleanTrue |\BooleanFalse |  |
+|a|\BooleanTrue |\BooleanTrue ||
+|a|\BooleanTrue |\BooleanTrue | \c_space_token |
+============================================================
diff --git a/l3packages/xparse/xparse.dtx b/l3packages/xparse/xparse.dtx
index d3001e1..94b7dc6 100644
--- a/l3packages/xparse/xparse.dtx
+++ b/l3packages/xparse/xparse.dtx
@@ -953,10 +953,10 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{variable}{\l_@@_ignore_spaces_bool}
+% \begin{variable}{\l_@@_obey_spaces_bool}
 %   For trailing optionals.
 %    \begin{macrocode}
-\bool_new:N \l_@@_ignore_spaces_bool
+\bool_new:N \l_@@_obey_spaces_bool
 %    \end{macrocode}
 % \end{variable}
 %
@@ -1029,9 +1029,9 @@
 % \end{variable}
 %
 % \begin{variable}
-%   {\l_@@_some_ignore_spaces_bool, \l_@@_some_long_bool, \l_@@_some_short_bool}
+%   {\l_@@_some_obey_spaces_bool, \l_@@_some_long_bool, \l_@@_some_short_bool}
 %   These flags are set while normalizing the argument specification.
-%   The \texttt{ignore_spaces} one is used to detect when |!| is used on
+%   The \texttt{obey_spaces} one is used to detect when |!| is used on
 %   an argument that is not a trailing optional argument.
 %   The other two are used to check whether all short arguments appear
 %   before long arguments: this is needed to grab arguments expandably.
@@ -1041,7 +1041,7 @@
 %   used for expandable commands, to know whether to define a short
 %   auxiliary too.
 %    \begin{macrocode}
-\bool_new:N \l_@@_some_ignore_spaces_bool
+\bool_new:N \l_@@_some_obey_spaces_bool
 \bool_new:N \l_@@_some_long_bool
 \bool_new:N \l_@@_some_short_bool
 %    \end{macrocode}
@@ -1577,9 +1577,9 @@
     \tl_clear:N \l_@@_last_delimiters_tl
     \tl_clear:N \l_@@_arg_spec_tl
     \bool_set_true:N \l_@@_grab_expandably_bool
-    \bool_set_false:N \l_@@_ignore_spaces_bool
+    \bool_set_false:N \l_@@_obey_spaces_bool
     \bool_set_false:N \l_@@_long_bool
-    \bool_set_false:N \l_@@_some_ignore_spaces_bool
+    \bool_set_false:N \l_@@_some_obey_spaces_bool
     \bool_set_false:N \l_@@_some_long_bool
     \bool_set_false:N \l_@@_some_short_bool
     \@@_normalize_arg_spec_loop:n #1
@@ -1700,6 +1700,7 @@
       {
         \__kernel_msg_error:nnxx { xparse } { two-markers }
           { \iow_char:N \\ \l_@@_function_tl } { + }
+        \@@_bad_def:wn
       }
     \bool_set_true:N \l_@@_long_bool
     \int_decr:N \l_@@_current_arg_int
@@ -1708,13 +1709,14 @@
 \cs_new_protected:cpn { @@_normalize_type_!:w } #1
   {
     \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn }
-    \bool_if:NT \l_@@_ignore_spaces_bool
+    \bool_if:NT \l_@@_obey_spaces_bool
       {
         \__kernel_msg_error:nnxx { xparse } { two-markers }
           { \iow_char:N \\ \l_@@_function_tl } { ! }
+        \@@_bad_def:wn
       }
-    \bool_set_true:N \l_@@_ignore_spaces_bool
-    \bool_set_true:N \l_@@_some_ignore_spaces_bool
+    \bool_set_true:N \l_@@_obey_spaces_bool
+    \bool_set_true:N \l_@@_some_obey_spaces_bool
     \int_decr:N \l_@@_current_arg_int
     \@@_normalize_arg_spec_loop:n {#1}
   }
@@ -1787,12 +1789,12 @@
     \@@_single_char_check:n {#1}
     \tl_put_right:Nx \l_@@_arg_spec_tl
       {
-        \bool_if:NT \l_@@_ignore_spaces_bool { ! }
+        \bool_if:NT \l_@@_obey_spaces_bool { ! }
         t \exp_not:n {#1}
       }
     \tl_put_right:Nn \l_@@_last_delimiters_tl {#1}
     \bool_set_false:N \l_@@_grab_expandably_bool
-    \bool_set_false:N \l_@@_ignore_spaces_bool
+    \bool_set_false:N \l_@@_obey_spaces_bool
     \bool_set_false:N \l_@@_long_bool
     \@@_normalize_arg_spec_loop:n
   }
@@ -1977,17 +1979,17 @@
     \tl_put_right:Nx \l_@@_arg_spec_tl
       {
         \bool_if:NT \l_@@_long_bool { + }
-        \bool_if:NT \l_@@_ignore_spaces_bool { ! }
+        \bool_if:NT \l_@@_obey_spaces_bool { ! }
         \exp_not:n {#1}
       }
     \bool_set_false:N \l_@@_long_bool
-    \bool_set_false:N \l_@@_ignore_spaces_bool
+    \bool_set_false:N \l_@@_obey_spaces_bool
   }
 \cs_new_protected:Npn \@@_add_arg_spec_mandatory:n #1
   {
-    \bool_if:NT \l_@@_some_ignore_spaces_bool
+    \bool_if:NT \l_@@_some_obey_spaces_bool
       {
-        \__kernel_msg_error:nnxx { xparse } { ignore-space-non-trailing }
+        \__kernel_msg_error:nnxx { xparse } { non-trailing-obey-spaces }
           { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
         \@@_bad_def:wn
       }
@@ -2012,7 +2014,7 @@
   {
     \int_zero:N \l_@@_current_arg_int
     \bool_set_false:N \l_@@_long_bool
-    \bool_set_false:N \l_@@_ignore_spaces_bool
+    \bool_set_false:N \l_@@_obey_spaces_bool
     \int_zero:N \l_@@_m_args_int
     \bool_set_false:N \l_@@_defaults_bool
     \tl_clear:N \l_@@_defaults_tl
@@ -2087,7 +2089,7 @@
 \cs_new_protected:cpn { @@_add_type_!:w }
   {
     \@@_flush_m_args:
-    \bool_set_true:N \l_@@_ignore_spaces_bool
+    \bool_set_true:N \l_@@_obey_spaces_bool
     \bool_set_true:N \l_@@_prefixed_bool
     \@@_prepare_signature_bypass:N
   }
@@ -2270,24 +2272,16 @@
 %
 % \begin{macro}{\@@_add_grabber_mandatory:N}
 % \begin{macro}{\@@_add_grabber_optional:N}
-%   To keep the various checks needed in one place, adding the grabber to
-%   the signature is done here. For mandatory arguments, the only question
-%   is whether to add a long grabber. For optional arguments, there is
-%   also a check to see if any mandatory arguments are still to be added.
-%   This is used to determine whether to skip spaces or not when
-%   searching for the argument.
+%   To keep the various checks needed in one place, adding the grabber
+%   to the signature is done here.  The only questions are whether the
+%   grabber should be long or not, and whether to obey spaces.  The
+%   \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.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_add_grabber_mandatory:N #1
   {
-    \tl_put_right:Nx \l_@@_signature_tl
-      {
-        \exp_not:c
-          { @@_grab_ #1 \bool_if:NT \l_@@_long_bool { _long } :w }
-      }
-    \bool_set_false:N \l_@@_long_bool
-    \tl_put_right:Nx \l_@@_process_all_tl
-      { { \exp_not:o \l_@@_process_one_tl } }
-    \tl_clear:N \l_@@_process_one_tl
+    \@@_add_grabber_optional:N #1
     \int_decr:N \l_@@_mandatory_args_int
   }
 \cs_new_protected:Npn \@@_add_grabber_optional:N #1
@@ -2298,15 +2292,12 @@
           {
             @@_grab_ #1
             \bool_if:NT \l_@@_long_bool { _long }
-            \bool_lazy_and:nnT
-              { \l_@@_ignore_spaces_bool }
-              { \int_compare_p:nNn \l_@@_mandatory_args_int = 0 }
-              { _ignore_spaces }
+            \bool_if:NT \l_@@_obey_spaces_bool { _obey_spaces }
             :w
           }
       }
     \bool_set_false:N \l_@@_long_bool
-    \bool_set_false:N \l_@@_ignore_spaces_bool
+    \bool_set_false:N \l_@@_obey_spaces_bool
     \tl_put_right:Nx \l_@@_process_all_tl
       { { \exp_not:o \l_@@_process_one_tl } }
     \tl_clear:N \l_@@_process_one_tl
@@ -2604,28 +2595,34 @@
 %
 % \begin{macro}{\@@_grab_D:w}
 % \begin{macro}{\@@_grab_D_long:w}
-% \begin{macro}{\@@_grab_D_ignore_spaces:w}
-% \begin{macro}{\@@_grab_D_long_ignore_spaces:w}
+% \begin{macro}{\@@_grab_D_obey_spaces:w}
+% \begin{macro}{\@@_grab_D_long_obey_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.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_grab_D:w #1#2#3 \@@_run_code:
   {
-    \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected_nopar:Npn
-      { _ignore_spaces }
+    \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected_nopar:Npn
+      \@@_peek_nonspace_remove:NTF
   }
 \cs_new_protected:Npn \@@_grab_D_long:w #1#2#3 \@@_run_code:
   {
-    \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected:Npn
-      { _ignore_spaces }
+    \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected:Npn
+      \@@_peek_nonspace_remove:NTF
+  }
+\cs_new_protected:Npn \@@_grab_D_obey_spaces:w #1#2#3 \@@_run_code:
+  {
+    \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected_nopar:Npn
+      \peek_meaning_remove:NTF
+  }
+\cs_new_protected:Npn \@@_grab_D_long_obey_spaces:w #1#2#3 \@@_run_code:
+  {
+    \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected:Npn
+      \peek_meaning_remove:NTF
   }
-\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_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}
+% \begin{macro}{\@@_grab_D_aux:NNnNN}
 % \begin{macro}{\@@_grab_D_aux:NNnN}
 %   This is a bit complicated. The idea is that, in order to check for
 %   nested optional argument tokens (\texttt{[[...]]} and so on) the
@@ -2635,10 +2632,10 @@
 %   prevents loss of braces, and there is then a test to see if there are
 %   nested delimiters to handle.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_grab_D_aux:NNnNn #1#2#3#4#5
+\cs_new_protected:Npn \@@_grab_D_aux:NNnNN #1#2#3#4#5
   {
     \@@_grab_D_aux:NNnN #1#2 {#3} #4
-    \use:c { peek_meaning_remove #5 :NTF } #1
+    #5 #1
       { \@@_grab_D_call:Nw #1 }
       { \@@_add_arg:o \c_novalue_tl }
   }
@@ -2774,36 +2771,36 @@
 % \begin{macro}
 %   {
 %     \@@_grab_E:w, \@@_grab_E_long:w,
-%     \@@_grab_E_ignore_spaces:w, \@@_grab_E_long_ignore_spaces:w
+%     \@@_grab_E_obey_spaces:w, \@@_grab_E_long_obey_spaces:w
 %   }
-% \begin{macro}{\@@_grab_E:nnNn}
-% \begin{macro}{\@@_grab_E_loop:nnN}
+% \begin{macro}{\@@_grab_E:nnNN}
+% \begin{macro}{\@@_grab_E_loop:NnN}
 % \begin{macro}{\@@_grab_E_finalise:}
 %   Everything here needs to point to a loop.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_grab_E:w #1#2 \@@_run_code:
   {
-    \@@_grab_E:nnNn {#1} {#2}
+    \@@_grab_E:nnNN {#1} {#2}
       \cs_set_protected_nopar:Npn
-      { _ignore_spaces }
+      \@@_peek_nonspace_remove:NTF
   }
 \cs_new_protected:Npn \@@_grab_E_long:w #1#2 \@@_run_code:
   {
-    \@@_grab_E:nnNn {#1} {#2}
+    \@@_grab_E:nnNN {#1} {#2}
       \cs_set_protected:Npn
-      { _ignore_spaces }
+      \@@_peek_nonspace_remove:NTF
   }
-\cs_new_protected:Npn \@@_grab_E_ignore_spaces:w #1#2 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_E_obey_spaces:w #1#2 \@@_run_code:
   {
-    \@@_grab_E:nnNn {#1} {#2}
+    \@@_grab_E:nnNN {#1} {#2}
       \cs_set_protected_nopar:Npn
-      { }
+      \peek_meaning_remove:NTF
   }
-\cs_new_protected:Npn \@@_grab_E_long_ignore_spaces:w #1#2 \@@_run_code:
+\cs_new_protected:Npn \@@_grab_E_long_obey_spaces:w #1#2 \@@_run_code:
   {
-    \@@_grab_E:nnNn {#1} {#2}
+    \@@_grab_E:nnNN {#1} {#2}
       \cs_set_protected:Npn
-      { }
+      \peek_meaning_remove:NTF
   }
 %    \end{macrocode}
 %   A loop is needed here to allow a random ordering of keys. These are
@@ -2811,12 +2808,12 @@
 %   they can appear later. The grabbed values are held in a property list
 %   which is then turned into an ordered list to be passed back to the user.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_grab_E:nnNn #1#2#3#4
+\cs_new_protected:Npn \@@_grab_E:nnNN #1#2#3#4
   {
     \exp_after:wN #3 \l_@@_fn_tl ##1##2##3
       {
         \prop_put:Nnn \l_@@_tmp_prop {##1} {##3}
-        \@@_grab_E_loop:nnN {#4} { } ##2 \q_recursion_stop
+        \@@_grab_E_loop:NnN #4 { } ##2 \q_recursion_stop
       }
     \prop_clear:N \l_@@_tmp_prop
     \tl_set:Nn \l_@@_signature_tl {#2}
@@ -2831,16 +2828,16 @@
           }
         \l_@@_signature_tl \@@_run_code:
       }
-    \@@_grab_E_loop:nnN {#4} { } #1 \q_recursion_tail \q_recursion_stop
+    \@@_grab_E_loop:NnN #4 { } #1 \q_recursion_tail \q_recursion_stop
   }
-\cs_new_protected:Npn \@@_grab_E_loop:nnN #1#2#3#4 \q_recursion_stop
+\cs_new_protected:Npn \@@_grab_E_loop:NnN #1#2#3#4 \q_recursion_stop
   {
     \cs_if_eq:NNTF #3 \q_recursion_tail
       { \@@_grab_E_finalise: }
       {
-        \use:c { peek_meaning_remove #1 :NTF } #3
+        #1 #3
           { \l_@@_fn_tl #3 {#2#4} }
-          { \@@_grab_E_loop:nnN {#1} {#2#3} #4 \q_recursion_stop }
+          { \@@_grab_E_loop:NnN #1 {#2#3} #4 \q_recursion_stop }
       }
   }
 \cs_new_protected:Npn \@@_grab_E_finalise: { }
@@ -2852,31 +2849,38 @@
 %
 % \begin{macro}{\@@_grab_G:w}
 % \begin{macro}{\@@_grab_G_long:w}
-% \begin{macro}{\@@_grab_G_ignore_spaces:w}
-% \begin{macro}{\@@_grab_G_long_ignore_spaces:w}
-% \begin{macro}{\@@_grab_G_aux:nNn}
+% \begin{macro}{\@@_grab_G_obey_spaces:w}
+% \begin{macro}{\@@_grab_G_long_obey_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.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_grab_G:w #1 \@@_run_code:
   {
-    \@@_grab_G_aux:nNn {#1} \cs_set_protected_nopar:Npn
-      { _ignore_spaces }
+    \@@_grab_G_aux:nNN {#1} \cs_set_protected_nopar:Npn
+      \@@_peek_nonspace:NTF
   }
 \cs_new_protected:Npn \@@_grab_G_long:w #1 \@@_run_code:
   {
-    \@@_grab_G_aux:nNn {#1} \cs_set_protected:Npn { _ignore_spaces }
+    \@@_grab_G_aux:nNN {#1} \cs_set_protected:Npn
+      \@@_peek_nonspace:NTF
+  }
+\cs_new_protected:Npn \@@_grab_G_obey_spaces:w #1 \@@_run_code:
+  {
+    \@@_grab_G_aux:nNN {#1} \cs_set_protected_nopar:Npn
+      \peek_meaning:NTF
   }
-\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_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
+\cs_new_protected:Npn \@@_grab_G_long_obey_spaces:w #1 \@@_run_code:
+  {
+    \@@_grab_G_aux:nNN {#1} \cs_set_protected:Npn
+      \peek_meaning:NTF
+  }
+\cs_new_protected:Npn \@@_grab_G_aux:nNN #1#2#3
   {
     \tl_set:Nn \l_@@_signature_tl {#1}
     \exp_after:wN #2 \l_@@_fn_tl ##1
       { \@@_add_arg:n {##1} }
-    \use:c { peek_meaning #3 :NTF } \c_group_begin_token
+    #3 \c_group_begin_token
       { \l_@@_fn_tl }
       { \@@_add_arg:o \c_novalue_tl }
   }
@@ -3029,7 +3033,7 @@
 \cs_new_protected:Npn \@@_grab_R_aux:NNnN #1#2#3#4
   {
     \@@_grab_D_aux:NNnN #1 #2 {#3} #4
-    \peek_meaning_remove_ignore_spaces:NTF #1
+    \@@_peek_nonspace_remove:NTF #1
       { \@@_grab_D_call:Nw #1 }
       {
         \__kernel_msg_error:nnxx { xparse } { missing-required }
@@ -3043,14 +3047,14 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_grab_t:w}
-% \begin{macro}{\@@_grab_t_ignore_spaces:w}
+% \begin{macro}{\@@_grab_t_obey_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.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_grab_t:w
-  { \@@_grab_t_aux:NNw \peek_meaning_remove_ignore_spaces:NTF }
-\cs_new_protected:Npn \@@_grab_t_ignore_spaces:w
+  { \@@_grab_t_aux:NNw \@@_peek_nonspace_remove:NTF }
+\cs_new_protected:Npn \@@_grab_t_obey_spaces:w
   { \@@_grab_t_aux:NNw \peek_meaning_remove:NTF }
 \cs_new_protected:Npn \@@_grab_t_aux:NNw #1#2#3 \@@_run_code:
   {
@@ -4091,6 +4095,23 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\@@_peek_nonspace:NTF, \@@_peek_nonspace_remove:NTF, \@@_peek_nonspace_aux:nNNTF}
+%   Collect spaces in a loop, and put the collected spaces back in the
+%   false branch of a call to \cs{peek_meaning:NTF} or
+%   \cs{peek_meaning_remove:NTF}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_peek_nonspace:NTF
+  { \@@_peek_nonspace_aux:nNNTF { } \peek_meaning:NTF }
+\cs_new_protected:Npn \@@_peek_nonspace_remove:NTF
+  { \@@_peek_nonspace_aux:nNNTF { } \peek_meaning_remove:NTF }
+\cs_new_protected:Npn \@@_peek_nonspace_aux:nNNTF #1#2#3#4#5
+  {
+    \peek_meaning_remove:NTF \c_space_token
+      { \@@_peek_nonspace_aux:nNNTF { #1 ~ } #2 #3 {#4} {#5} }
+      { #2 #3 { #4 } { #5 #1 } }
+  }
+% \end{macro}
+%
 % \subsection{Messages}
 %
 % Some messages intended as errors.
@@ -4177,19 +4198,19 @@
     The~default~values~of~two~or~more~arguments~of~'#1'~depend~on~each~
     other~in~a~way~that~cannot~be~resolved.
   }
-\__kernel_msg_new:nnnn { xparse } { ignore-space-non-trailing }
-  { Prefix~'!'~used~before~mandatory~argument~'#2'~of~command~'#1'. }
-  {
-    The~prefix~'!'~can~only~apply~to~trailing~optional~arguments.
-    \\ \\
-    LaTeX~will~ignore~this~entire~definition.
-  }
 \__kernel_msg_new:nnnn { xparse } { missing-required }
   { Failed~to~find~required~argument~starting~with~'#2'~for~command~'#1'. }
   {
     The~current~command~'#1'~expects~an~argument~starting~with~'#2'.~
     LaTeX~did~not~find~it,~and~will~insert~a~default~value~to~be~processed.
   }
+\__kernel_msg_new:nnnn { xparse } { non-trailing-obey-spaces }
+  { Prefix~'!'~used~before~mandatory~argument~'#2'~of~command~'#1'. }
+  {
+    The~prefix~'!'~can~only~apply~to~trailing~optional~arguments.
+    \\ \\
+    LaTeX~will~ignore~this~entire~definition.
+  }
 \__kernel_msg_new:nnnn { xparse } { non-xparse-command }
   { Command~'#1'~not~defined~using~xparse. }
   {





More information about the latex3-commits mailing list