[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