[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