From 88e37f91ff634c7e1eec9437624ba4082440cf86 Mon Sep 17 00:00:00 2001 From: Joseph Wright Date: Mon, 28 Oct 2024 13:12:50 +0000 Subject: [PATCH] Introduce an f-specification argument in ltcmd See latex3/latex3#591. --- base/changes.txt | 4 + base/doc/ltnews41.tex | 33 +++ base/doc/usrguide.tex | 36 +++ base/ltcmd.dtx | 221 +++++++++++++- base/testfiles-ltcmd/ltcmd005.luatex.tlg | 358 ----------------------- base/testfiles-ltcmd/ltcmd005.lvt | 48 --- base/testfiles-ltcmd/ltcmd005.tlg | 52 +--- base/testfiles-ltcmd/ltcmd009.lvt | 91 ++++++ base/testfiles-ltcmd/ltcmd009.tlg | 53 ++++ 9 files changed, 433 insertions(+), 463 deletions(-) delete mode 100644 base/testfiles-ltcmd/ltcmd005.luatex.tlg create mode 100644 base/testfiles-ltcmd/ltcmd009.lvt create mode 100644 base/testfiles-ltcmd/ltcmd009.tlg diff --git a/base/changes.txt b/base/changes.txt index 6321cf6fd..a9f6e65cc 100644 --- a/base/changes.txt +++ b/base/changes.txt @@ -6,6 +6,10 @@ to completeness or accuracy and it contains some references to files that are not part of the distribution. ================================================================================ +2024-11-01 Joseph Wright + * ltcmd.dtx, usrguide.tex + New "f"-type argument + ================================================================================ All changes above are only part of the development branch for the next release. ================================================================================ diff --git a/base/doc/ltnews41.tex b/base/doc/ltnews41.tex index 0c9751704..c91ee0949 100644 --- a/base/doc/ltnews41.tex +++ b/base/doc/ltnews41.tex @@ -147,6 +147,39 @@ \section{Introduction} \section{New or improved commands} +\subsection{Collecting environment bodies verbatim} + +The mechanisms in \pkg{ltcmd} (\enquote{\pkg{xparse}}) offer a powerful way to +specify a range of types of document command and environment syntax. This +includes the ability to collect the entire body of an environment, for cases +where treating it as a standard argument is useful. It is also possible in +\pkg{ltcmd} to define argument which grab their content verbatim, another +specialist argument form. To date, however, it was not possible to combine +these two ideas. + +In this release, a new specifier~\texttt{f} is introduced, which collects the +body of an environment in a verbatim-like way. Like the existing +\texttt{v}~specification, each separate line is marked by the special +\cs{obeyedline} marker, which as standard issues a normal paragraph. Thus, this +new specifier is usable both for typesetting and collecting file contents (the +\texttt{f} indicates \enquote{\texttt{filecontents}-like}). Thus, we may use +\begin{verbatim} +\NewDocumentEnvironment + {MyVerbatim}{!O{\ttfamily} +f} + {\begin{center} #1 #2\end{center}} {} +\begin{MyVerbatim}[\ttfamily\itshape] + % Some code is show here + $y = mx + c$ +\end{MyVerbatim} +\end{verbatim} +to obtain +\NewDocumentEnvironment{MyVerbatim}{!O{\ttfamily} +f} + {\begin{center} #1 #2\end{center}} {} +\begin{MyVerbatim}[\ttfamily\itshape] + % Some code is show here + $y = mx + c$ +\end{MyVerbatim} + \section{Code improvements} \section{Bug fixes} diff --git a/base/doc/usrguide.tex b/base/doc/usrguide.tex index e4ea6e4e0..dddcf977c 100644 --- a/base/doc/usrguide.tex +++ b/base/doc/usrguide.tex @@ -858,6 +858,42 @@ \subsection{Typesetting verbatim-like material} Similarly, the \texttt{verbatim} environment sets up the meaning of \cs{par} suitable for breaking lines. +\subsection{Verbatim environments} +\label{sec:cmd:verbenv} + +In some cases, as well as grabbing an environment body you will want the +contents to be treated verbatim. This is available using the argument +specification~\texttt{f}. Like the \texttt{b} specification, this has to be the +last one. Thus for example +\begin{verbatim} +\NewDocumentEnvironment{MyVerbatim}{!O{\ttfamily} +f} + {\begin{center} #1 #2\end{center}} {} +\begin{MyVerbatim}[\ttfamily\itshape] + % Some code is show here + $y = mx + c$ +\end{MyVerbatim} +\end{verbatim} +will typeset +\NewDocumentEnvironment{MyVerbatim}{!O{\ttfamily} +f} + {\begin{center} #1 #2\end{center}} {} +\begin{MyVerbatim}[\ttfamily\itshape] + % Some code is show here + $y = mx + c$ +\end{MyVerbatim} + +As grabbing the entire contents verbatim, newlines are always permitted: if you +use \texttt{f} rather than \texttt{+f}, a warning will be issued and \LaTeX{} +will assume you meant to include the \texttt{+}. As for the \texttt{v} +specification, new lines are stored as \cs{ObeyedLine}. In a similar fashion to +the \texttt{b}~specification, by default \emph{newlines} are trimmed at both +ends of the body. Putting the prefix |!| before \texttt{b} suppresses +space-trimming. + +Notice that for technical reasons, we recommend that an optional argument +coming immediately before an \texttt{f} specification should not allow any +spaces, achieved by adding the \texttt{!} as showing in the example. However, +this is left as a choice for the user. + \subsection{Performance} For document commands where the argument specification is entirely diff --git a/base/ltcmd.dtx b/base/ltcmd.dtx index eccb104bb..3879b100d 100644 --- a/base/ltcmd.dtx +++ b/base/ltcmd.dtx @@ -34,8 +34,8 @@ %%% From File: ltcmd.dtx % % \begin{macrocode} -\def\ltcmdversion{v1.2f} -\def\ltcmddate{2024-07-06} +\def\ltcmdversion{v1.3a} +\def\ltcmddate{2024-11-01} % \end{macrocode} % %<*driver> @@ -1331,28 +1331,47 @@ % \end{macro} % % \begin{macro}{\@@_normalize_type_b:w} -% This argument type is not allowed for commands. This is only +% \changes{v1.3a}{2024-11-01}{Extend to cover \texttt{f}-type grabbing} +% \begin{macro}{\@@_normalize_type_f:w} +% \changes{v1.3a}{2024-11-01}{New function} +% \begin{macro}{\@@_normalize_type_b_or_f:nn} +% \changes{v1.3a}{2024-11-01}{New function} +% These argument type is not allowed for commands. They is only % allowed at the end of the argument specification, hence we check % that |#1| is the end. % \begin{macrocode} \cs_new_protected:Npn \@@_normalize_type_b:w #1 + { \@@_normalize_type_b_or_f:nn {#1} { b } } +\cs_new_protected:Npn \@@_normalize_type_f:w #1 + { + \bool_if:NF \l_@@_long_bool + { + \msg_warning:nn { cmd } { verb-collection-always-long } + \bool_set_true:N \l_@@_long_bool + } + \@@_normalize_type_b_or_f:nn {#1} { f } + } +\cs_new_protected:Npn \@@_normalize_type_b_or_f:nn #1#2 { \bool_if:NF \l_@@_environment_bool { \msg_error:nnxx { cmd } { invalid-command-arg } - { \@@_environment_or_command: } { b } + { \@@_environment_or_command: } {#2} \@@_bad_def:wn } \tl_clear:N \l_@@_last_delimiters_tl - \@@_add_arg_spec:n { b } + \@@_add_arg_spec:n {#2} \quark_if_recursion_tail_stop:n {#1} - \msg_error:nnxx { cmd } { arg-after-body } + \msg_error:nnxxx { cmd } { arg-after-body } + {#2} { \@@_environment_or_command: } { \tl_to_str:n {#1} } \@@_bad_def:wn } % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\@@_single_token_check:n} % Checks that the argument is a single (non-space) token (possibly @@ -1658,16 +1677,27 @@ % \end{macro} % % \begin{macro}{\@@_add_type_b:w} +% \changes{v1.3a}{2024-11-01}{Extend to cover \texttt{f}-type grabbing} +% \begin{macro}{\@@_add_type_f:w} +% \changes{v1.3a}{2024-11-01}{New function} +% \begin{macro}{\@@_add_type_b_or_c:N} +% \changes{v1.3a}{2024-11-01}{New function} % \begin{macrocode} \cs_new_protected:Npn \@@_add_type_b:w + { \@@_add_type_b_or_f:N b } +\cs_new_protected:Npn \@@_add_type_f:w + { \@@_add_type_b_or_f:N f } +\cs_new_protected:Npn \@@_add_type_b_or_f:N #1 { \@@_flush_m_args: \@@_add_default: - \@@_add_grabber:N b + \@@_add_grabber:N #1 \@@_prepare_signature:N } % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\@@_add_type_D:w} % \begin{macrocode} @@ -3002,6 +3032,173 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_grab_f_long:w} +% \changes{v1.3a}{2024-11-01}{New \texttt{f}-type grabbing function} +% \begin{macro}{\@@_grab_f_long_obey_spaces:w} +% \begin{macro}{\@@_grab_f_aux:n} +% \begin{macro}{\@@_grab_f_aux:w} +% \begin{macro}{\@@_grab_f_check:w} +% \begin{macro}{\@@_grab_f_loop:w} +% \begin{macro}{\@@_grab_f_space_check:w} +% \begin{macro}{\@@_grab_f_space_aux:w} +% \begin{macro}{\@@_grab_f_end:nn} +% \begin{macro}{\@@_grab_f_end:n} +% \begin{macro}{\@@_grab_f_end_auxi:w} +% \begin{macro}{\@@_grab_f_end_auxii:w} +% Collecting an environment body verbatim shares some ideas with the +% \texttt{v}-type grabber, and others with the standard \texttt{filecontents} +% environment. The start is to set the end-of-line to a predictable value +% and to deactivate the specials. We then define the end marker: this +% has to have the correct category codes, so is a token list not a string +% (\texttt{end} and the end-of-env name are catcode-11). We use this to set +% up the end-of-env test, then hand over to an auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_grab_f_long:w #1 \@@_run_code: + { + \bool_set_false:N \l_@@_obey_spaces_bool + \@@_grab_f_aux:n {#1} + } +\cs_new_protected:Npn \@@_grab_f_long_obey_spaces:w #1 \@@_run_code: + { + \bool_set_true:N \l_@@_obey_spaces_bool + \@@_grab_f_aux:n {#1} + } +\cs_new_protected:Npn \@@_grab_f_aux:n #1 + { + \tl_set:Nn \l_@@_signature_tl {#1} + \group_begin: + \tl_clear:N \l_@@_v_arg_tl + \tex_escapechar:D = 92 \scan_stop: + \tex_endlinechar:D = `\^^M \scan_stop: + \cs_set_eq:NN \do \char_set_catcode_other:N + \dospecials + \tl_set:Ne \l_@@_tmpa_tl + { + \c_backslash_str end + \c_left_brace_str \@currenvir \c_right_brace_str + } + \use:e + { + \cs_set_protected:Npn \@@_grab_f_check:w + ##1 \l_@@_tmpa_tl ##2 \l_@@_tmpa_tl ##3 + \scan_stop: + } + { + \tl_if_empty:nTF {##3} + { + \tl_put_right:Nn \l_@@_v_arg_tl + { + ##1 + \obeyedline + } + \@@_grab_f_loop:w + } + { \@@_grab_f_end:nn {##1} {##2} } + } + \@@_grab_f_aux:w + } +% \end{macrocode} +% To allow for the need to change the category code of end-of-lines, we +% put this in a small auxiliary. At the end of this, we deal with the +% a special case for the first line before looping. +% \begin{macrocode} +\group_begin: + \char_set_catcode_other:N \^^M % + \cs_new_protected:Npn \@@_grab_f_aux:w % + { % + \cs_set_protected:Npe \@@_grab_f_loop:w ##1 ^^M % + { % + \@@_grab_f_check:w ##1 % + \l_@@_tmpa_tl % + \l_@@_tmpa_tl % + \scan_stop: % + } % + \char_set_catcode_other:N \^^M % + \group_align_safe_begin: % + \peek_after:Nw \@@_grab_f_space_check:w + } % +\group_end: % +\cs_new_protected:Npn \@@_grab_f_check:w { } +\cs_new_protected:Npn \@@_grab_f_loop:w { } +% \end{macrocode} +% If there was a potential optional argument before the \texttt{f}-type +% one, but it was missed out, the next character will already have been +% tokenized. The most common case will be a newline, which will have +% been converted to a space: that is picked up here. (It is impossible +% to filter out all possible cases, as the underlying behavior of +% \tn{futurelet} means that for example a \verb=%= would be a comment +% and be lost.) Alternative approaches require that a category code +% change for \verb=^^M= takes place before searching for any optional +% arguments (see for example \pkg{fancyvrb}). +% \begin{macrocode} +\cs_new_protected:Npn \@@_grab_f_space_check:w + { + \if_meaning:w \l_peek_token \c_space_token + \exp_after:wN \@@_grab_f_space_aux:w + \else: + \group_align_safe_end: + \exp_after:wN \@@_grab_f_loop:w + \fi: + } +\cs_new_protected:Npn \@@_grab_f_space_aux:w + { + \group_align_safe_end: + \tl_set:Nn \l_@@_v_arg_tl { \obeyedline } + \peek_remove_spaces:n + { \@@_grab_f_loop:w } + } +\cs_new_protected:Npn \@@_grab_f_end:nn #1#2 + { + \tl_if_blank:nF {#1#2} + \ERROR + \exp_args:NNNo \group_end: + \tl_set:Nn \l_@@_v_arg_tl { \l_@@_v_arg_tl } + \@@_add_arg:x + { + \bool_if:NTF \l_@@_obey_spaces_bool + { \exp_not:V } + { \exp_args:NV \@@_grab_f_end:n } + \l_@@_v_arg_tl + } + \exp_args:NV \end \@currenvir + } +% \end{macrocode} +% Look for line markers at each end and tidy up if required. +% \begin{macrocode} +\cs_new:Npn \@@_grab_f_end:n #1 + { + \@@_grab_f_end_auxi:w {#1} #1 + \q_nil \obeyedline \q_nil \obeyedline \q_nil \q_stop + } +\cs_new:Npn \@@_grab_f_end_auxi:w + #1#2 \obeyedline \q_nil \obeyedline \q_nil #3 \q_stop + { + \tl_if_empty:nTF {#3} + { \@@_grab_f_end_auxii:w {#1} #1 } + { \@@_grab_f_end_auxii:w {#2} #2 } + \obeyedline \q_stop + } +\cs_new:Npn \@@_grab_f_end_auxii:w + #1#2 \obeyedline #3 \q_stop + { + \tl_if_blank:nTF {#2} + { \tl_tail:n {#1} } + { \exp_not:n {#1} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro} % { % \@@_grab_D:w , @@ -4716,12 +4913,13 @@ % \changes{v1.0f}{2021/06/04}{Normalize various error messages} % \changes{v1.2c}{2023/12/22} % {Generalize message \texttt{invalid-bang} (gh/1198)} +% \changes{v1.3a}{2024-11-01}{Generalize message \texttt{arg-after-body}} % \begin{macrocode} \msg_new:nnnn { cmd } { arg-after-body } - { Argument~type~'b'~must~be~last~in~#1. } + { Argument~type~'#1'~must~be~last~in~#2. } { - The~'b'~argument~type~must~come~last~but~it~is~followed~ - by~'#2'~in~the~argument~specification.~This~is~not~allowed. + The~'#1'~argument~type~must~come~last~but~it~is~followed~ + by~'#3'~in~the~argument~specification.~This~is~not~allowed. \c_@@_ignore_def_tl } \msg_new:nnnn { cmd } { bad-arg-spec } @@ -4934,6 +5132,7 @@ % \end{macrocode} % % Intended more for information. +% \changes{v1.3a}{2024-11-01}{New message \texttt{verb-collection-always-long}} % \begin{macrocode} \msg_new:nnn { cmd } { define-command } % should be just ``define'' but dep in xparse { @@ -4973,6 +5172,8 @@ '#1~code'~and/or~'#1~defaults'.~Maybe~you~tried~using~ \iow_char:N\\let.~This~may~lead~to~an~infinite~loop. } +\msg_new:nnn { cmd } { verb-collection-always-long } + { Verbatim~body~collection~always~permits~newlines. } % \end{macrocode} % % \subsection{User functions} diff --git a/base/testfiles-ltcmd/ltcmd005.luatex.tlg b/base/testfiles-ltcmd/ltcmd005.luatex.tlg deleted file mode 100644 index ad67a80c8..000000000 --- a/base/testfiles-ltcmd/ltcmd005.luatex.tlg +++ /dev/null @@ -1,358 +0,0 @@ -This is a generated file for the LaTeX2e validation system. -Don't change this file in any respect. -Author: Bruno Le Floch -============================================================ -TEST 1: Invalid '!' -============================================================ -! LaTeX cmd Error: Invalid argument prefix '!' in command '\testA'. -For immediate help type H . - ... -l. ... } -The prefix '!' is only allowed for trailing optional arguments. You tried to apply it to an optional argument before mandatory 'R(){-NoValue-}'. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument prefix '!' in command '\testA'. -For immediate help type H . - ... -l. ... } -The prefix '!' is only allowed for trailing optional arguments. You tried to apply it to an optional argument before mandatory 'm'. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument prefix '!' in command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided for command '\testA' has two '!' markers applied to the same argument; one is redundant. -! LaTeX cmd Error: Bad argument specification '!+!' for command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided is not valid: one or more mandatory parts are missing. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Bad argument specification '+!' for command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided is not valid: one or more mandatory parts are missing. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Bad argument specification '!' for command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided is not valid: one or more mandatory parts are missing. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument prefix '+' in command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided for command '\testA' has two '+' markers applied to the same argument; one is redundant. -! LaTeX cmd Error: Bad argument specification '!o' for \testA. -For immediate help type H . - ... -l. ... } -Expandable commands must have a final mandatory argument (or no arguments at all). You cannot have a terminal optional argument with expandable commands. -! LaTeX cmd Error: Invalid argument prefix '!' in command '\testA'. -For immediate help type H . - ... -l. ... } -The prefix '!' is only allowed for trailing optional arguments. You tried to apply it to 'm'. -LaTeX will ignore this entire definition. -============================================================ -============================================================ -TEST 2: Valid '!' and avoid dropping spaces -============================================================ -Runaway argument? -! Paragraph ended before \testA was complete. - -\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 | -Runaway argument? -! Paragraph ended before \testB was complete. - -\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 | -============================================================ -============================================================ -TEST 3: Environment body valid -============================================================ -============================================================ -|...|{\begin {any} \begin {unbalanced} \end {environments} \begin {provided}}{\end {nesting} \end {works} \begin {out} \end {!}}| -|...| -|-NoValue-| [...] \begin {any} \begin {unbalanced} \end {environments} \begin {provided} \end {nesting} \end {works} \begin {out} \end {!} | -|-NoValue-| -============================================================ -TEST 4: Body invalid -============================================================ -|-NoValue-|{}| -! LaTeX Error: \begin{env1} on input line ... ended by \end{env2}. -See the LaTeX manual or LaTeX Companion for explanation. -Type H for immediate help. - ... -l. ... } -Your command was ignored. -Type I to replace it with another command, -or to continue without it. -Runaway argument? -\begin -! Paragraph ended before \environment env2 was complete. - -\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. -! LaTeX cmd Error: Invalid argument type 'b' in command '\testE'. -For immediate help type H . - ... -l. ... } -The letter 'b' can only be used in environment argument specifications, but not for commands. -LaTeX will ignore the entire definition. -! LaTeX cmd Error: Argument type 'b' must be last in environment 'env3'. -For immediate help type H . - ... -l. ... } -The 'b' argument type must come last but it is followed by 'm' in the argument specification. This is not allowed. -LaTeX will ignore this entire definition. -============================================================ -============================================================ -TEST 5: Invalid signatures -============================================================ -! LaTeX cmd Error: Bad argument specification 'O' for command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided is not valid: one or more mandatory parts are missing. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Bad argument specification 'D[]' for environment 'testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided is not valid: one or more mandatory parts are missing. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Bad argument specification '!+>{\TrimSpaces }' for environment 'testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided is not valid: one or more mandatory parts are missing. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument prefix '!' in command '\testA'. -For immediate help type H . - ... -l. ... } -The prefix '!' is only allowed for trailing optional arguments. You tried to apply it to an optional argument before mandatory 'm'. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument prefix '!' in environment 'testA'. -For immediate help type H . - ... -l. ... } -The prefix '!' is only allowed for trailing optional arguments. You tried to apply it to an optional argument before mandatory 'm'. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Too many arguments for command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification 'mmmmmmmmmmmm' asks for more than 9 arguments. This cannot be implemented. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Too many arguments for environment 'testA'. -For immediate help type H . - ... -l. ... } -The argument specification 'mmmmmmmmmmmm' asks for more than 9 arguments. This cannot be implemented. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument prefix '!' in command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided for command '\testA' has two '!' markers applied to the same argument; one is redundant. -! LaTeX cmd Error: Invalid argument prefix '!' in environment 'testA'. -For immediate help type H . - ... -l. ... } -The argument specification provided for environment 'testA' has two '!' markers applied to the same argument; one is redundant. -! LaTeX cmd Error: Invalid argument type 'X' in command '\testA'. -For immediate help type H . - ... -l. ... } -The letter 'X' does not specify a known argument type. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument type 'X' in environment 'testA'. -For immediate help type H . - ... -l. ... } -The letter 'X' does not specify a known argument type. -LaTeX will ignore this entire definition. -============================================================ -============================================================ -TEST 6: Already or not yet defined -============================================================ -! LaTeX cmd Error: Command '\space' already defined. -For immediate help type H . - ... -l. ... } -You have used \NewDocumentCommand with a command that already has a definition. -The existing definition of '\space' will not be altered. -|macro:-> | -! LaTeX cmd Error: Environment 'foo' already defined. -For immediate help type H . - ... -l. ... } -You have used \NewDocumentEnvironment with an environment that already has a definition. -The existing definition of 'foo' will not be altered. -foo -! LaTeX cmd Error: Command '\testA' undefined. -For immediate help type H . - ... -l. ... } -You have used \RenewDocumentCommand with a command that was never defined. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Environment 'testA' undefined. -For immediate help type H . - ... -l. ... } -You have used \RenewDocumentEnvironment with an environment that was never defined. -LaTeX will ignore this entire definition. -============================================================ -============================================================ -TEST 7: Not definable/multi-char -============================================================ -! LaTeX cmd Error: First argument of '\NewDocumentCommand' must be a command. -For immediate help type H . - ... -l. ... } -The first argument of '\NewDocumentCommand' should be the document command that will be defined. The provided argument '+' is a character. Perhaps a backslash is missing? -LaTeX will ignore this entire definition. -! LaTeX cmd Error: First argument of '\NewDocumentCommand' must be a command. -For immediate help type H . - ... -l. ... } -The first argument of '\NewDocumentCommand' should be the document command that will be defined. The provided argument 'space' contains more than one token. Perhaps a backslash is missing? -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Argument delimiter 'ab' invalid in command '\testB'. -For immediate help type H . - ... -l. ... } -The argument specification contains 'ab' in a place where a single token is required. -LaTeX will ignore this entire definition. -! Use of \??? doesn't match its definition. - \??? - ! LaTeX cmd Error: Invalid argument {foo} to \IfBoolean... -l. ... } -If you say, e.g., `\def\a1{...}', then you must always -put `1' after `\a', since control sequence names are -made up of letters only. The macro here has not been -followed by the required stuff, so I'm ignoring it. -FALSE -! Use of \??? doesn't match its definition. - \??? - ! LaTeX cmd Error: Invalid argument {\foo } to \IfBoolean... -l. ... } -If you say, e.g., `\def\a1{...}', then you must always -put `1' after `\a', since control sequence names are -made up of letters only. The macro here has not been -followed by the required stuff, so I'm ignoring it. -! Use of \??? doesn't match its definition. - \??? - ! LaTeX cmd Error: Invalid argument {?} to \IfBoolean... -l. ... } -If you say, e.g., `\def\a1{...}', then you must always -put `1' after `\a', since control sequence names are -made up of letters only. The macro here has not been -followed by the required stuff, so I'm ignoring it. -FALSE -============================================================ -============================================================ -TEST 8: Invalid signatures for expandable commands -============================================================ -! LaTeX cmd Error: Bad argument specification 'mo' for \testA. -For immediate help type H . - ... -l. ... } -Expandable commands must have a final mandatory argument (or no arguments at all). You cannot have a terminal optional argument with expandable commands. -! LaTeX cmd Error: Invalid argument prefix '+' in command '\testA'. -For immediate help type H . - ... -l. ... } -The arguments for an expandable command must not involve short arguments after long arguments. You have tried to mix the two types when defining '\testA'. -! LaTeX cmd Error: Invalid argument type 'v' in \testA. -For immediate help type H . - ... -l. ... } -The letter 'v' specifies an argument type which cannot be used in an expandable command. -LaTeX will ignore this entire definition. -! LaTeX cmd Error: Invalid argument prefix '>' in command '\testA'. -For immediate help type H . - ... -l. ... } -The argument specification for '\testA' contains the processor function '>{\TrimSpaces }'. This is only supported for robust commands, but not for expandable ones. -LaTeX will ignore this entire definition. -============================================================ -============================================================ -TEST 9: Run-time errors -============================================================ -! LaTeX cmd Error: Circular dependency in defaults of command '\testA'. -For immediate help type H . - ... -l. ... } -The default values of two or more arguments of the command '\testA' depend on each other in a way that cannot be resolved. -\C \E \C \E \C \E \C \E -NoValue-|\C \E \C \E \C \E \C \E -NoValue--NoValue-|\C |\C \E |\E -! LaTeX cmd Error: Circular dependency in defaults of environment 'testB'. -For immediate help type H . - ... -l. ... } -The default values of two or more arguments of the environment 'testB' depend on each other in a way that cannot be resolved. -\C \E \C \E \C \E \C \E -NoValue-|\C \E \C \E \C \E \C \E -NoValue--NoValue-|\C |\C \E |\E -! LaTeX cmd Error: Too many ',' separators in argument. -For immediate help type H . - ... -l. ... } -LaTeX was asked to split the input 'a,b,c,d' at each occurrence of the separator ',' into 3 parts. Too many separators were found. -! LaTeX cmd Error: Too many ',' separators in argument. -For immediate help type H . - ... -l. ... } -LaTeX was asked to split the input 'a,b,c,d' at each occurrence of the separator ',' into 3 parts. Too many separators were found. -! LaTeX cmd Error: Verbatim-like command '\testE' illegal in argument. -For immediate help type H . - ... -l. ... } -The command '\testE' takes a verbatim argument and should therefore normally not be used in arguments of other commands or environments. LaTeX found an illegal token (\TYPE ) after '+' and will drop everything up to this point. -Expect further (low-level) errors. --NoValue- -+ -! LaTeX cmd Error: Verbatim-like environment 'testF' illegal in argument. -For immediate help type H . - ... -l. ... } -The environment 'testF' takes a verbatim argument and should therefore normally not be used in arguments of other commands or environments. LaTeX found an illegal token (\TYPE ) after '+' and will drop everything up to this point. -Expect further (low-level) errors. --NoValue- -+ -============================================================ -! LaTeX cmd Error: Verbatim-like command '\testG' ended by end of line. -For immediate help type H . - ... -l. ...\testG+ -The verbatim argument of the command '\testG' cannot contain more than one line, but the end of the current line has been reached. You may have forgotten the closing delimiter. -LaTeX will ignore '+' and you may get some additional (low-level) errors. --NoValue- -+ -! LaTeX cmd Error: Verbatim-like environment 'testH' ended by end of line. -For immediate help type H . - ... -l. ...\begin{testH}+ -The verbatim argument of the environment 'testH' cannot contain more than one line, but the end of the current line has been reached. You may have forgotten the closing delimiter. -LaTeX will ignore '+' and you may get some additional (low-level) errors. --NoValue- -+ diff --git a/base/testfiles-ltcmd/ltcmd005.lvt b/base/testfiles-ltcmd/ltcmd005.lvt index 08d4570f0..94c79952b 100644 --- a/base/testfiles-ltcmd/ltcmd005.lvt +++ b/base/testfiles-ltcmd/ltcmd005.lvt @@ -56,54 +56,6 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% The following tests are outside to allow \ExplSyntaxOff and \obeylines -\TEST { Environment~body~valid } { } - -\NewDocumentEnvironment { env1 } { o >{\SplitList{\par}} + b } - { \TYPE { \tl_to_str:n {|#1|#2|} } } - { \TYPE { \tl_to_str:n {|#1|} } } -\NewDocumentEnvironment { env2 } { ! o ! b } - { \TYPE { \tl_to_str:n {|#1|#2|} } } - { \TYPE { \tl_to_str:n {|#1|} } } -\ExplSyntaxOff -\begin{env1} [...] - \begin{any} - \begin{unbalanced} - \end{environments} - \begin{provided} - - \end{nesting} - \end{works} - \begin{out} - \end{!} -\end{env1} -\begin{env2} [...] - \begin{any} - \begin{unbalanced} - \end{environments} - \begin{provided} - \end{nesting} - \end{works} - \begin{out} - \end{!} -\end{env2} -\ExplSyntaxOn - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\TEST { Body~invalid } - { - \begin{env1}\end{env2} - \begin{env2} - \par - \end{env2} - \NewDocumentCommand{\testE} { b } { } - \NewDocumentEnvironment{env3} { b m } { } { } - } - -% The rest of this test tests all of xparse's messages. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - \TEST { Invalid~signatures } { % Disabled: test requires deprecated xparse.sty diff --git a/base/testfiles-ltcmd/ltcmd005.tlg b/base/testfiles-ltcmd/ltcmd005.tlg index 1a20f4d3b..c085f0b5e 100644 --- a/base/testfiles-ltcmd/ltcmd005.tlg +++ b/base/testfiles-ltcmd/ltcmd005.tlg @@ -85,49 +85,7 @@ My plan is to forget the whole thing and hope for the best. |a|\BooleanTrue |\BooleanTrue | \c_space_token | ============================================================ ============================================================ -TEST 3: Environment body valid -============================================================ -============================================================ -|...|{\begin {any} \begin {unbalanced} \end {environments} \begin {provided}}{\end {nesting} \end {works} \begin {out} \end {!}}| -|...| -|-NoValue-| [...] \begin {any} \begin {unbalanced} \end {environments} \begin {provided} \end {nesting} \end {works} \begin {out} \end {!} | -|-NoValue-| -============================================================ -TEST 4: Body invalid -============================================================ -|-NoValue-|{}| -! LaTeX Error: \begin{env1} on input line ... ended by \end{env2}. -See the LaTeX manual or LaTeX Companion for explanation. -Type H for immediate help. - ... -l. ... } -Your command was ignored. -Type I to replace it with another command, -or to continue without it. -Runaway argument? -\begin -! Paragraph ended before \environment env2 was complete. - - \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. -! LaTeX cmd Error: Invalid argument type 'b' in command '\testE'. -For immediate help type H . - ... -l. ... } -The letter 'b' can only be used in environment argument specifications, but not for commands. -LaTeX will ignore the entire definition. -! LaTeX cmd Error: Argument type 'b' must be last in environment 'env3'. -For immediate help type H . - ... -l. ... } -The 'b' argument type must come last but it is followed by 'm' in the argument specification. This is not allowed. -LaTeX will ignore this entire definition. -============================================================ -============================================================ -TEST 5: Invalid signatures +TEST 3: Invalid signatures ============================================================ ! LaTeX cmd Error: Bad argument specification 'O' for command '\testA'. For immediate help type H . @@ -195,7 +153,7 @@ The letter 'X' does not specify a known argument type. LaTeX will ignore this entire definition. ============================================================ ============================================================ -TEST 6: Already or not yet defined +TEST 4: Already or not yet defined ============================================================ ! LaTeX cmd Error: Command '\space' already defined. For immediate help type H . @@ -225,7 +183,7 @@ You have used \RenewDocumentEnvironment with an environment that was never defin LaTeX will ignore this entire definition. ============================================================ ============================================================ -TEST 7: Not definable/multi-char +TEST 5: Not definable/multi-char ============================================================ ! LaTeX cmd Error: First argument of '\NewDocumentCommand' must be a command. For immediate help type H . @@ -273,7 +231,7 @@ followed by the required stuff, so I'm ignoring it. FALSE ============================================================ ============================================================ -TEST 8: Invalid signatures for expandable commands +TEST 6: Invalid signatures for expandable commands ============================================================ ! LaTeX cmd Error: Bad argument specification 'mo' for \testA. For immediate help type H . @@ -299,7 +257,7 @@ The argument specification for '\testA' contains the processor function '>{\Trim LaTeX will ignore this entire definition. ============================================================ ============================================================ -TEST 9: Run-time errors +TEST 7: Run-time errors ============================================================ ! LaTeX cmd Error: Circular dependency in defaults of command '\testA'. For immediate help type H . diff --git a/base/testfiles-ltcmd/ltcmd009.lvt b/base/testfiles-ltcmd/ltcmd009.lvt new file mode 100644 index 000000000..458bbc67d --- /dev/null +++ b/base/testfiles-ltcmd/ltcmd009.lvt @@ -0,0 +1,91 @@ + +\documentclass{minimal} +\input{regression-test} + +\ExplSyntaxOn +\debug_on:n { check-declarations , deprecation , log-functions } +\ExplSyntaxOff +% \RequirePackage{xparse} + +\begin{document} + +\START +\AUTHOR{Bruno Le Floch, Joseph Wright} + +\ExplSyntaxOn + +% The following tests are outside to allow \ExplSyntaxOff and \obeylines +\TEST { Environment~body~valid } { } + +\NewDocumentEnvironment { env1 } { o >{\SplitList{\par}} + b } + { \TYPE { \tl_to_str:n {|#1|#2|} } } + { \TYPE { \tl_to_str:n {|#1|} } } +\NewDocumentEnvironment { env2 } { ! o ! b } + { \TYPE { \tl_to_str:n {|#1|#2|} } } + { \TYPE { \tl_to_str:n {|#1|} } } +\ExplSyntaxOff +\begin{env1} [...] + \begin{any} + \begin{unbalanced} + \end{environments} + \begin{provided} + + \end{nesting} + \end{works} + \begin{out} + \end{!} +\end{env1} +\begin{env2} [...] + \begin{any} + \begin{unbalanced} + \end{environments} + \begin{provided} + \end{nesting} + \end{works} + \begin{out} + \end{!} +\end{env2} +\ExplSyntaxOn + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\TEST { Body~invalid } + { + \begin{env1}\end{env2} + \begin{env2} + \par + \end{env2} + \NewDocumentCommand{\testE} { b } { } + \NewDocumentEnvironment{env3} { b m } { } { } + } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\TEST { Verbatim~body~collection } { } + +\NewDocumentEnvironment { env3 } { o +f } + { \TYPE { \tl_to_str:n {|#1|#2|} } } + { } +\NewDocumentEnvironment { env4 } { !o !+f } + { \TYPE { \tl_to_str:n {|#1|#2|} } } + { } + +\ExplSyntaxOff +\begin{env3} + Content + &\^ +\end{env3} +\begin{env3}[...] + Content + &\^ +\end{env3} +\begin{env4} + Content + &\^ +\end{env4} +\begin{env4}[...] + Content + &\^ +\end{env4} +\ExplSyntaxOn + +\END diff --git a/base/testfiles-ltcmd/ltcmd009.tlg b/base/testfiles-ltcmd/ltcmd009.tlg new file mode 100644 index 000000000..e31d4c286 --- /dev/null +++ b/base/testfiles-ltcmd/ltcmd009.tlg @@ -0,0 +1,53 @@ +This is a generated file for the LaTeX2e validation system. +Don't change this file in any respect. +Author: Bruno Le Floch, Joseph Wright +============================================================ +TEST 1: Environment body valid +============================================================ +============================================================ +|...|{\begin {any} \begin {unbalanced} \end {environments} \begin {provided}}{\end {nesting} \end {works} \begin {out} \end {!}}| +|...| +|-NoValue-| [...] \begin {any} \begin {unbalanced} \end {environments} \begin {provided} \end {nesting} \end {works} \begin {out} \end {!} | +|-NoValue-| +============================================================ +TEST 2: Body invalid +============================================================ +|-NoValue-|{}| +! LaTeX Error: \begin{env1} on input line ... ended by \end{env2}. +See the LaTeX manual or LaTeX Companion for explanation. +Type H for immediate help. + ... +l. ... } +Your command was ignored. +Type I to replace it with another command, +or to continue without it. +Runaway argument? +\begin +! Paragraph ended before \environment env2 was complete. + + \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. +! LaTeX cmd Error: Invalid argument type 'b' in command '\testE'. +For immediate help type H . + ... +l. ... } +The letter 'b' can only be used in environment argument specifications, but not for commands. +LaTeX will ignore the entire definition. +! LaTeX cmd Error: Argument type 'b' must be last in environment 'env3'. +For immediate help type H . + ... +l. ... } +The 'b' argument type must come last but it is followed by 'm' in the argument specification. This is not allowed. +LaTeX will ignore this entire definition. +============================================================ +============================================================ +TEST 3: Verbatim body collection +============================================================ +============================================================ +|-NoValue-|Content\obeyedline &\^| +|...| Content\obeyedline &\^| +|-NoValue-|\obeyedline Content\obeyedline &\^\obeyedline | +|...|\obeyedline Content\obeyedline &\^\obeyedline |