summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2019-03-05 22:35:14 +0000
committerKarl Berry <karl@freefriends.org>2019-03-05 22:35:14 +0000
commit68872ff6a2a91fa0e84763fc9316493d82075c95 (patch)
tree0546ec4c414553802e31a423aec44f74d252f645 /Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
parent541c4ddf7c5b402b9cfe8af5ef4e49ffa15d3e83 (diff)
l3 (5mar19)
git-svn-id: svn://tug.org/texlive/trunk@50246 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx856
1 files changed, 554 insertions, 302 deletions
diff --git a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
index 5ee7072feec..91d6a006658 100644
--- a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
+++ b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
@@ -1,10 +1,10 @@
% \iffalse meta-comment
%
-%% File: xparse.dtx (C) Copyright 1999 Frank Mittelbach, Chris Rowley,
-%% David Carlisle
-%% (C) Copyright 2004-2008 Frank Mittelbach,
-%% The LaTeX3 Project
-%% (C) Copyright 2009-2018 The LaTeX3 Project
+%% File: xparse.dtx
+%
+% Copyright (C) 1999 Frank Mittelbach, Chris Rowley, David Carlisle
+% (C) 2004-2008 Frank Mittelbach, The LaTeX3 Project
+% (C) 2009-2019 The LaTeX3 Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -67,7 +67,7 @@
% }^^A
% }
%
-% \date{Released 2018-10-17}
+% \date{Released 2019-03-05}
%
% \maketitle
%
@@ -85,18 +85,18 @@
% At present, the functions in \pkg{xparse} which are regarded as
% \enquote{stable} are:
% \begin{itemize}
-% \item \cs{NewDocumentCommand}
-% \item \cs{RenewDocumentCommand}
-% \item \cs{ProvideDocumentCommand}
-% \item \cs{DeclareDocumentCommand}
-% \item \cs{NewDocumentEnvironment}
-% \item \cs{RenewDocumentEnvironment}
-% \item \cs{ProvideDocumentEnvironment}
-% \item \cs{DeclareDocumentEnvironment}
-% \item \cs{NewExpandableDocumentCommand}
-% \item \cs{RenewExpandableDocumentCommand}
-% \item \cs{ProvideExpandableDocumentCommand}
-% \item \cs{DeclareExpandableDocumentCommand}
+% \item \cs{NewDocumentCommand}\\
+% \cs{RenewDocumentCommand}\\
+% \cs{ProvideDocumentCommand}\\
+% \cs{DeclareDocumentCommand}
+% \item \cs{NewDocumentEnvironment}\\
+% \cs{RenewDocumentEnvironment}\\
+% \cs{ProvideDocumentEnvironment}\\
+% \cs{DeclareDocumentEnvironment}
+% \item \cs{NewExpandableDocumentCommand}\\
+% \cs{RenewExpandableDocumentCommand}\\
+% \cs{ProvideExpandableDocumentCommand}\\
+% \cs{DeclareExpandableDocumentCommand}
% \item \cs{IfNoValue(TF)}
% \item \cs{IfValue(TF)}
% \item \cs{IfBoolean(TF)}
@@ -105,7 +105,7 @@
% try all of the commands provided here, but be aware that the
% experimental ones may change or disappear.
%
-% \subsection{Specifying arguments}
+% \section{Specifying arguments}
%
% Before introducing the functions used to create document commands,
% the method for specifying arguments with \pkg{xparse} will be
@@ -126,41 +126,46 @@
% are:
% \begin{itemize}[font=\ttfamily]
% \item[m] A standard mandatory argument, which can either be a single
-% token alone or multiple tokens surrounded by curly braces.
+% token alone or multiple tokens surrounded by curly braces |{}|.
% Regardless of the input, the argument will be passed to the
-% internal code surrounded by a brace pair. This is the \pkg{xparse}
+% internal code without the outer braces. This is the \pkg{xparse}
% type specifier for a normal \TeX{} argument.
-% \item[r] Reads a \enquote{required} delimited argument, where the
-% delimiters are given as \meta{char1} and \meta{char2}:
-% \texttt{r}\meta{char1}\meta{char2}. If the opening \meta{character}
-% is missing, the default marker |-NoValue-| will be inserted after
-% a suitable error.
-% \item[R] As for \texttt{r}, this is a \enquote{required} delimited
-% argument but has a user-definable recovery \meta{default}, given
-% as \texttt{R}\meta{char1}\meta{char2}\marg{default}.
+% \item[r] Given as \texttt{r}\meta{char1}\meta{char2}, this denotes a
+% \enquote{required} delimited argument, where the delimiters are
+% \meta{char1} and \meta{char2}. If the opening delimiter
+% \meta{char1} is missing, the default marker |-NoValue-| will be
+% inserted after a suitable error.
+% \item[R] Given as \texttt{R}\meta{char1}\meta{char2}\marg{default},
+% this is a \enquote{required} delimited argument as for~\texttt{r},
+% but it has a user-definable recovery \meta{default} instead of
+% |-NoValue-|.
% \item[v] Reads an argument \enquote{verbatim}, between the following
% character and its next occurrence, in a way similar to the argument
% of the \LaTeXe{} command \cs{verb}. Thus a \texttt{v}-type argument
-% is read between two matching tokens, which cannot be any of |%|, |\|,
+% is read between two identical characters, which cannot be any of |%|, |\|,
% |#|, |{|, |}| or \verb*| |.
% The verbatim argument can also be enclosed between braces, |{| and |}|.
% A command with a verbatim
-% argument will not work when it appears within an argument of
+% argument will produce an error when it appears within an argument of
% another function.
+% \item[b] Only suitable in the argument specification of an
+% environment, it denotes the body of the environment, between
+% |\begin|\marg{environment} and |\end|\marg{environment}. See
+% Section~\ref{sec:body} for details.
% \end{itemize}
% The types which define optional arguments are:
% \begin{itemize}[font=\ttfamily]
% \item[o] A standard \LaTeX{} optional argument, surrounded with square
% brackets, which will supply
% the special |-NoValue-| marker if not given (as described later).
-% \item[d] An optional argument which is delimited by \meta{char1}
-% and \meta{char2}, given as follows:
-% \texttt{d}\meta{char1}\meta{char2}. As with \texttt{o}, if no
+% \item[d] Given as \texttt{d}\meta{char1}\meta{char2}, an optional
+% argument which is delimited by \meta{char1} and \meta{char2}.
+% As with \texttt{o}, if no
% value is given the special marker |-NoValue-| is returned.
-% \item[O] As for \texttt{o}, but returns \meta{default} if no
-% value is given. Should be given as \texttt{O}\marg{default}.
-% \item[D] As for \texttt{d}, but returns \meta{default} if no
-% value is given: \texttt{D}\meta{char1}\meta{char2}\marg{default}.
+% \item[O] Given as \texttt{O}\marg{default}, is like \texttt{o}, but
+% returns \meta{default} if no value is given.
+% \item[D] Given as \texttt{D}\meta{char1}\meta{char2}\marg{default},
+% it is as for \texttt{d}, but returns \meta{default} if no value is given.
% Internally, the \texttt{o}, \texttt{d} and \texttt{O} types are
% short-cuts to an appropriated-constructed \texttt{D} type argument.
% \item[s] An optional star, which will result in a value
@@ -169,9 +174,9 @@
% \item[t] An optional \meta{char}, which will result in a value
% \cs{BooleanTrue} if \meta{char} is present and \cs{BooleanFalse}
% otherwise. Given as \texttt{t}\meta{char}.
-% \item[e] A set of optional \emph{embellishments}, each of which
-% requires a \emph{value}: \texttt{e}\marg{chars}. If an
-% embellishment is not present, |-NoValue-| is returned. Each
+% \item[e] Given as \texttt{e}\marg{chars}, a set of optional
+% \emph{embellishments}, each of which requires a \emph{value}.
+% If an embellishment is not present, |-NoValue-| is returned. Each
% embellishment gives one argument, ordered as for the list of
% \meta{chars} in the argument specification. All \meta{chars}
% must be distinct. \emph{This is an experimental type}.
@@ -217,7 +222,7 @@
% \NewDocumentCommand{\foobar}{o}{#1}
% \foobar[{[}] % Allowed as the "[" is 'hidden'
% \end{verbatim}
-% These braces will be stripped if they surround the \emph{entire} content
+% These braces will be stripped only if they surround the \emph{entire} content
% of the optional argument
% \begin{verbatim}
% \NewDocumentCommand{\foobaz}{o}{#1}
@@ -241,7 +246,7 @@
% When an optional argument is followed by a mandatory argument with the
% same delimiter, \pkg{xparse} issues a warning because the optional
% argument could not be omitted by the user, thus becoming in effect
-% mandatory. This applies to \texttt{o}, \texttt{d}, \texttt{O},
+% mandatory. This can apply to \texttt{o}, \texttt{d}, \texttt{O},
% \texttt{D}, \texttt{s}, \texttt{t}, \texttt{e}, and \texttt{E} type
% arguments followed by \texttt{r} or \texttt{R}-type required
% arguments, but also to \texttt{g} or \texttt{G} type arguments
@@ -313,10 +318,6 @@
% (\texttt{r}-type) or user-specified default (for \texttt{R}-type) will be
% inserted to allow error recovery.
%
-% Users should note that support for required delimited arguments is somewhat
-% experimental. Feedback is therefore very welcome on the \texttt{LaTeX-L}
-% mailing list.
-%
% \subsection{Verbatim arguments}
%
% Arguments of type~\texttt{v} are read in verbatim mode, which will
@@ -385,7 +386,107 @@
% |-NoValue-| marker as a default for |_|. This allows mixing of explicit
% defaults with testing for missing values.
%
-% \subsection{Declaring commands and environments}
+% \subsection{Body of an environment}
+% \label{sec:body}
+%
+% While environments |\begin|\marg{environment} \dots{}
+% |\end|\marg{environment} are typically used in cases where the code
+% implementing the \meta{environment} does not need to access the
+% contents of the environment (its \enquote{body}), it is sometimes
+% useful to have the body as a standard argument.
+%
+% This is achieved in \pkg{xparse} by ending the argument specification
+% with~\texttt{b}. The approach taken in \pkg{xparse} is
+% different from the earlier packages \pkg{environ} or \pkg{newenviron}:
+% the body of the environment is provided to the code part as a usual
+% argument |#1|, |#2| etc.\@, rather than stored in a macro such as
+% \cs[no-index]{BODY}.
+%
+% For instance
+% \begin{verbatim}
+% \NewDocumentEnvironment { twice }
+% { O{\ttfamily} +b }
+% {#2#1#2} {}
+% \begin{twice}[\itshape]
+% Hello world!
+% \end{twice}
+% \end{verbatim}
+% typesets \enquote{Hello world!{\itshape Hello world!}}.
+%
+% The prefix |+| is used to allow multiple paragraphs in the
+% environment's body. Argument processors can also be applied to
+% \texttt{b}~arguments.
+%
+% By default, spaces are trimmed at both ends of the body: in the
+% example there would otherwise be spaces coming from the ends the lines
+% after |[\itshape]| and |world!|. Putting the prefix |!| before
+% \texttt{b} suppresses space-trimming.
+%
+% When \texttt{b} is used in the argument specification,
+% the last argument of \cs{NewDocumentEnvironment}, which consists of
+% an \meta{end code} to insert at |\end|\marg{environment}, is
+% redundant since one can simply put that code at the end of the
+% \meta{start code}. Nevertheless this (empty) \meta{end code} must be
+% provided.
+%
+% Environments that use this feature can be nested.
+%
+% Users should note that this feature is somewhat experimental. Feedback
+% is therefore very welcome on the \texttt{LaTeX-L} mailing list.
+%
+% \subsection{Starred environments}
+%
+% Many packages define environments with and without \texttt{*} in their
+% name, for instance \texttt{tabular} and \texttt{tabular*}. At
+% present, \pkg{xparse} does not provide specific tools to define these:
+% one should simply define the two environment separately, for instance
+% \begin{verbatim}
+% \NewDocumentEnvironment { tabular } { o +m } {...} {...}
+% \NewDocumentEnvironment { tabular* } { m o +m } {...} {...}
+% \end{verbatim}
+% Of course the implementation of these two environments, denoted
+% \enquote{\texttt{...}} in this example, can rely on the same internal
+% commands.
+%
+% Note that this situation is different from the \texttt{s} argument
+% type: if the signature of an environment starts with~\texttt{s} then
+% the star is searched for after the argument of \cs{begin}. For
+% instance, the following typesets \texttt{star}.
+% \begin{verbatim}
+% \NewDocumentEnvironment { envstar } { s }
+% {\IfBooleanTF {#1} {star} {no star}} {}
+% \begin{envstar}*
+% \end{envstar}
+% \end{verbatim}
+%
+% \subsection{Backwards Compatibility}
+% \label{sec:backwards}
+%
+% One role of \pkg{xparse} is to describe existing \LaTeX{} interfaces,
+% including some that are rather unusual in \LaTeX{} (as opposed to
+% formats such as plain \TeX{}) such as delimited arguments. As such,
+% the package defines some argument specifiers that should largely be
+% avoided nowadays as using them in packages leads to inconsistent user
+% interfaces. The simplest syntax is often best, with argument
+% specifications such as |mmmm| or |ommmm|, namely an optional argument
+% followed by some standard mandatory ones. The optional argument can
+% be made to support key--value syntax using tools from \pkg{l3keys}.
+%
+% The argument types that are not recommended any longer are:
+% \begin{itemize}[font=\ttfamily]
+% \item[l] A mandatory argument which reads everything up to the first
+% begin-group token: in standard \LaTeX{} this is a left brace.
+% \item[u] Reads a mandatory argument \enquote{until} \meta{tokens} are encountered,
+% where the desired \meta{tokens} are given as an argument to the
+% specifier: \texttt{u}\marg{tokens}.
+% \item[g] An optional argument given inside a pair of \TeX{} group
+% tokens (in standard \LaTeX{}, |{| \ldots |}|), which returns
+% |-NoValue-| if not present.
+% \item[G] As for \texttt{g} but returns \meta{default} if no value
+% is given: \texttt{G}\marg{default}.
+% \end{itemize}
+%
+% \section{Declaring commands and environments}
%
% With the concept of an argument specifier defined, it is now
% possible to describe the methods available for creating both
@@ -404,12 +505,13 @@
% \DeclareDocumentCommand
% }
% \begin{syntax}
-% \cs{NewDocumentCommand} \meta{Function} \Arg{arg spec} \Arg{code}
+% \cs{NewDocumentCommand} \meta{function} \Arg{arg spec} \Arg{code}
% \end{syntax}
% This family of commands are used to create a document-level
% \meta{function}. The argument specification for the function is
-% given by \meta{arg spec}, and expanding
-% to be replaced by the \meta{code}.
+% given by \meta{arg spec}, and the function expands to the
+% \meta{code} with |#1|, |#2|, etc.\ replaced by the arguments found
+% by \pkg{xparse}.
% \end{function}
%
% As an example:
@@ -467,6 +569,8 @@
% The arguments will be given following \cs{begin}\Arg{environment}.
% \end{function}
%
+% \section{Other \pkg{xparse} commands}
+%
% \subsection{Testing special values}
%
% Optional arguments created using \pkg{xparse} make use of dedicated
@@ -599,10 +703,10 @@
%
% \begin{function}[updated = 2012-02-12]{\SplitArgument}
% \begin{syntax}
-% \cs{SplitArgument} \Arg{number} \Arg{token}
+% \cs{SplitArgument} \Arg{number} \Arg{token(s)}
% \end{syntax}
% This processor splits the argument given at each occurrence of the
-% \meta{token} up to a maximum of \meta{number} tokens (thus
+% \meta{tokens} up to a maximum of \meta{number} tokens (thus
% dividing the input into $\text{\meta{number}} + 1$ parts).
% An error is given if too many \meta{tokens} are present in the
% input. The processed input is placed inside
@@ -615,9 +719,10 @@
% { > { \SplitArgument { 2 } { ; } } m }
% { \InternalFunctionOfThreeArguments #1 }
% \end{verbatim}
-% Any category code $13$ (active) \meta{tokens} will be replaced
-% before the split takes place. Spaces are trimmed at each end of each
-% item parsed.
+% If only a single character \meta{token} is used for the split, any
+% category code $13$ (active) character matching the \meta{token} will
+% be replaced before the split takes place.
+% Spaces are trimmed at each end of each item parsed.
% \end{function}
%
% \begin{function}{\SplitList}
@@ -633,9 +738,10 @@
% { > { \SplitList { ; } } m }
% { \MappingFunction #1 }
% \end{verbatim}
-% If only a single \meta{token} is used for the split, any
-% category code $13$ (active) \meta{token} will be replaced
-% before the split takes place.
+% If only a single character \meta{token} is used for the split, any
+% category code $13$ (active) character matching the \meta{token} will
+% be replaced before the split takes place.
+% Spaces are trimmed at each end of each item parsed.
% \end{function}
%
% \begin{function}[EXP]{\ProcessList}
@@ -713,7 +819,8 @@
% available:
% \begin{itemize}
% \item The last argument (if any are present) must be one of the
-% mandatory types \texttt{m} or \texttt{r}.
+% mandatory types \texttt{m}, \texttt{r}, \texttt{R}, \texttt{l}
+% or~\texttt{u}.
% \item All short arguments appear before long arguments.
% \item The mandatory argument types \texttt{l} and \texttt{u} may
% not be used after optional arguments.
@@ -768,40 +875,13 @@
% \DescribeOption{log-declarations}
% The package recognises the load-time option \texttt{log-declarations},
% which is a key--value option taking the value \texttt{true} and
-% \texttt{false}. By default, the option is set to \texttt{true}, meaning
-% that each command or environment declared is logged. By loading
+% \texttt{false}. By default, the option is set to \texttt{false}, meaning
+% that no command or environment declared is logged. By loading
% \pkg{xparse} using
% \begin{verbatim}
-% \usepackage[log-declarations=false]{xparse}
+% \usepackage[log-declarations=true]{xparse}
% \end{verbatim}
-% this may be suppressed and no information messages are produced.
-%
-% \section{Backwards Compatibility}
-% \label{sec:backwards}
-%
-% One role of \pkg{xparse} is to describe existing \LaTeX{} interfaces,
-% including some that are rather unusual in \LaTeX{} (as opposed to
-% formats such as plain \TeX{}) such as delimited arguments. As such,
-% the package defines some argument specifiers that should largely be
-% avoided nowadays as using them in packages leads to inconsistent user
-% interfaces. The simplest syntax is often best, with argument
-% specifications such as |mmmm| or |ommmm|, namely an optional argument
-% followed by some standard mandatory ones. The optional argument can
-% be made to support key--value syntax using tools from \pkg{l3keys}.
-%
-% The argument types that are not recommended any longer are:
-% \begin{itemize}[font=\ttfamily]
-% \item[l] A mandatory argument which reads everything up to the first
-% begin-group token: in standard \LaTeX{} this is a left brace.
-% \item[u] Reads a mandatory argument \enquote{until} \meta{tokens} are encountered,
-% where the desired \meta{tokens} are given as an argument to the
-% specifier: \texttt{u}\marg{tokens}.
-% \item[g] An optional argument given inside a pair of \TeX{} group
-% tokens (in standard \LaTeX{}, |{| \ldots |}|), which returns
-% |-NoValue-| if not present.
-% \item[G] As for \texttt{g} but returns \meta{default} if no value
-% is given: \texttt{G}\marg{default}.
-% \end{itemize}
+% each new, declared or renewed command or environment is logged.
%
% \end{documentation}
%
@@ -818,7 +898,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xparse}{2018-10-17}{}
+\ProvidesExplPackage{xparse}{2019-03-05}{}
{L3 Experimental document command parser}
% \end{macrocode}
%
@@ -883,11 +963,19 @@
% Generating environments uses the same mechanism as generating functions.
% However, full processing of arguments is always needed for environments,
% and so the function-generating code needs to know this.
+% This variable is also used at run time to give correct error messages.
% \begin{macrocode}
\bool_new:N \l_@@_environment_bool
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}{\l_@@_environment_str}
+% Name of the environment, used at definition time and at run time.
+% \begin{macrocode}
+\str_new:N \l_@@_environment_str
+% \end{macrocode}
+% \end{variable}
+%
% \begin{variable}{\l_@@_expandable_bool}
% Used to indicate if an expandable command is begin generated, as this
% affects both the acceptable argument types and how they are implemented.
@@ -987,15 +1075,6 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_@@_mandatory_args_int}
-% Holds the total number of mandatory arguments for a function, which is
-% needed to tell whether further mandatory arguments follow an optional
-% one.
-% \begin{macrocode}
-\int_new:N \l_@@_mandatory_args_int
-% \end{macrocode}
-% \end{variable}
-%
% \begin{variable}{\l_@@_prefixed_bool}
% When preparing the signature of non-expandable commands, indicates
% that the current argument is affected by a processor or by |+|
@@ -1018,6 +1097,14 @@
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}{\l_@@_saved_args_tl}
+% Stores \cs{l_@@_args_tl} to deal with space-trimming of
+% \texttt{b}-type arguments.
+% \begin{macrocode}
+\tl_new:N \l_@@_saved_args_tl
+% \end{macrocode}
+% \end{variable}
+%
% \begin{variable}{\l_@@_signature_tl}
% Used when constructing the signature (code for argument grabbing) to
% hold what will become the implementation of the main function.
@@ -1064,7 +1151,7 @@
% \begin{macro}{\@@_declare_cmd:Nnn, \@@_declare_expandable_cmd:Nnn}
% \begin{macro}{\@@_declare_cmd_aux:Nnn}
% \begin{macro}
-% {\@@_declare_cmd_internal:Nnn, \@@_declare_cmd_internal:cnx}
+% {\@@_declare_cmd_internal:Nnnn, \@@_declare_cmd_internal:cnxn}
% The main functions for creating commands set the appropriate flag then
% use the same internal code to do the definition.
% \begin{macrocode}
@@ -1082,7 +1169,7 @@
% The first stage is to log information, both for the user in the log and
% for programmatic use in a property list of all declared commands.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_declare_cmd_aux:Nnn #1#2
+\cs_new_protected:Npn \@@_declare_cmd_aux:Nnn #1#2#3
{
\cs_if_exist:NTF #1
{
@@ -1101,22 +1188,26 @@
{ \token_to_str:N #1 } { \tl_to_str:n {#2} }
}
\bool_set_false:N \l_@@_environment_bool
- \@@_declare_cmd_internal:Nnn #1 {#2}
+ \@@_declare_cmd_internal:Nnnn #1 {#2} {#3} { }
}
% \end{macrocode}
+% At definition time, the variable \cs{l_@@_fn_tl} is only used for error messages.
% The real business of defining a document command starts with setting up
% the appropriate name, then normalizing the argument specification to get rid of
-% shorthands (this step also counts the number of mandatory arguments).
+% shorthands.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_declare_cmd_internal:Nnn #1#2#3
+\cs_new_protected:Npn \@@_declare_cmd_internal:Nnnn #1#2#3#4
{
\tl_set:Nx \l_@@_function_tl { \cs_to_str:N #1 }
+ \tl_set:Nx \l_@@_fn_tl
+ { \exp_not:c { \l_@@_function_tl \c_space_tl } }
\@@_normalize_arg_spec:n {#2}
\exp_args:No \@@_prepare_signature:n \l_@@_arg_spec_tl
\@@_declare_cmd_code:Nnn #1 {#2} {#3}
+ #4
\@@_break_point:n {#2}
}
-\cs_generate_variant:Nn \@@_declare_cmd_internal:Nnn { cnx }
+\cs_generate_variant:Nn \@@_declare_cmd_internal:Nnnn { cnx }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1153,10 +1244,16 @@
\cs_set_protected:Npn \l_@@_current_arg_int {#3}
\cs_set_protected_nopar:Npx #1
{
- \@@_start:nNNnnn
- { \exp_not:n {#2} }
- \exp_not:c { \l_@@_function_tl \c_space_tl }
- \exp_not:c { \l_@@_function_tl \c_space_tl code }
+ \bool_if:NTF \l_@@_environment_bool
+ {
+ \@@_start_env:nnnnn { \exp_not:n {#2} }
+ { \l_@@_environment_str }
+ }
+ {
+ \@@_start:nNNnnn { \exp_not:n {#2} }
+ \exp_not:c { \l_@@_function_tl \c_space_tl }
+ \exp_not:c { \l_@@_function_tl \c_space_tl code }
+ }
{ \exp_not:o \l_@@_signature_tl }
{
\bool_if:NT \l_@@_defaults_bool
@@ -1241,23 +1338,27 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_declare_env:nnnn #1#2
{
+ \str_set:Nx \l_@@_environment_str {#1}
+ \str_set:Nx \l_@@_environment_str
+ { \tl_trim_spaces:o { \l_@@_environment_str } }
%<*initex>
- \cs_if_exist:cTF { environment~ #1 }
+ \cs_if_exist:cTF { environment~ \l_@@_environment_str }
%</initex>
%<*package>
- \cs_if_exist:cTF {#1}
+ \cs_if_exist:cTF { \l_@@_environment_str }
%</package>
{
\__kernel_msg_info:nnxx { xparse } { redefine-environment }
- {#1} { \tl_to_str:n {#2} }
+ { \l_@@_environment_str } { \tl_to_str:n {#2} }
}
{
\__kernel_msg_info:nnxx { xparse } { define-environment }
- {#1} { \tl_to_str:n {#2} }
+ { \l_@@_environment_str } { \tl_to_str:n {#2} }
}
\bool_set_false:N \l_@@_expandable_bool
\bool_set_true:N \l_@@_environment_bool
- \@@_declare_env_internal:nnnn {#1} {#2}
+ \exp_args:NV \@@_declare_env_internal:nnnn
+ \l_@@_environment_str {#2}
}
% \end{macrocode}
% Creating a document environment requires a few more steps than creating
@@ -1267,10 +1368,16 @@
% redefined to contain the appropriate information. To minimize the amount
% of expansion at point of use, the code here is expanded now as well as
% when used.
+% The last argument of \cs{@@_declare_cmd_internal:Nnnn} is only run
+% if the definition succeeded. In package mode this ensures that the
+% original definition of the environment is not changed if the
+% definition fails for any reason. This also avoids an error when
+% defining the \verb*|end aux | function when the user asks for more
+% than $9$ arguments.
% \begin{macrocode}
\cs_new_protected:Npn \@@_declare_env_internal:nnnn #1#2#3#4
{
- \@@_declare_cmd_internal:cnx { environment~ #1 } {#2}
+ \@@_declare_cmd_internal:cnxn { environment~ #1 } {#2}
{
\cs_set_nopar:Npx \exp_not:c { environment~ #1 ~end~aux }
{
@@ -1279,15 +1386,17 @@
}
\exp_not:n {#3}
}
- \cs_set_nopar:cpx { environment~ #1 ~end }
- { \exp_not:c { environment~ #1 ~end~aux } }
- \cs_generate_from_arg_count:cNnn
- { environment~ #1 ~end~aux~ } \cs_set:Npn
- \l_@@_current_arg_int {#4}
+ {
+ \cs_set_nopar:cpx { environment~ #1 ~end }
+ { \exp_not:c { environment~ #1 ~end~aux } }
+ \cs_generate_from_arg_count:cNnn
+ { environment~ #1 ~end~aux~ } \cs_set:Npn
+ \l_@@_current_arg_int {#4}
%<*package>
- \cs_set_eq:cc {#1} { environment~ #1 }
- \cs_set_eq:cc { end #1 } { environment~ #1 ~end }
+ \cs_set_eq:cc {#1} { environment~ #1 }
+ \cs_set_eq:cc { end #1 } { environment~ #1 ~end }
%</package>
+ }
}
% \end{macrocode}
% \end{macro}
@@ -1295,32 +1404,52 @@
%
% \subsection{Structure of \pkg{xparse} commands}
%
-% \begin{macro}{\@@_start:nNNnnn}
-% \begin{macro}{\@@_start_aux:nNNnnn}
-% This sets up a few variables to minimize the boilerplate code
-% included in all \pkg{xparse}-defined commands. It then runs the
-% grabbers~|#4|. Again, the argument specification |#1| is only for
-% diagnostics. The control sequence equal to \cs{scan_stop:} protects
-% against \texttt{f}-expansion and ensures errors are more reasonable
-% when an \pkg{xparse} command is placed in a csname.
+% \begin{macro}{\@@_start_env:nnnnn, \@@_start:nNNnnn}
+% For error messages that occur during run-time when getting arguments
+% of environments it is necessary to keep track of the environment
+% name. We begin non-expandable commands with a token equal to
+% \cs{scan_stop:}, whose name gives a reasonable error message if the
+% command is used inside a csname and protects against
+% \texttt{f}-expansion. This is useless for environments since
+% \cs{begin} is already not expandable.
% \begin{macrocode}
-\cs_new_protected:Npx \@@_start:nNNnnn
+\cs_new_protected:Npn \@@_start_env:nnnnn #1#2
+ {
+ \str_set:Nn \l_@@_environment_str {#2}
+ \bool_set_true:N \l_@@_environment_bool
+ \@@_start_aux:ccnnnn
+ { environment~ \l_@@_environment_str \c_space_tl }
+ { environment~ \l_@@_environment_str \c_space_tl code }
+ {#1}
+ }
+\cs_new_protected:Npx \@@_start:nNNnnn #1#2#3
{
\exp_not:c { xparse~function~is~not~expandable }
- \exp_not:N \@@_start_aux:nNNnnn
+ \exp_not:n { \bool_set_false:N \l_@@_environment_bool }
+ \exp_not:N \@@_start_aux:NNnnnn
+ #2 #3 {#1}
}
-\cs_new_protected:Npn \@@_start_aux:nNNnnn #1#2#3#4#5#6
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_start_aux:NNnnnn, \@@_start_aux:ccnnnn}
+% This sets up a few variables to minimize the boilerplate code
+% included in all \pkg{xparse}-defined commands. It then runs the
+% grabbers~|#4|. Again, the argument specification |#1| is only for
+% diagnostics.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_start_aux:NNnnnn #1#2#3#4#5#6
{
\tl_clear:N \l_@@_args_tl
- \tl_set:Nn \l_@@_fn_tl {#2}
- \tl_set:Nn \l_@@_fn_code_tl {#3}
+ \tl_set:Nn \l_@@_fn_tl {#1}
+ \tl_set:Nn \l_@@_fn_code_tl {#2}
\tl_set:Nn \l_@@_defaults_tl {#5}
\tl_set:Nn \l_@@_process_all_tl {#6}
#4 \@@_run_code:
}
+\cs_generate_variant:Nn \@@_start_aux:NNnnnn { cc }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\@@_run_code:}
% After arguments are grabbed, this function is responsible for
@@ -1369,7 +1498,7 @@
\cs_new_protected:Npn \@@_defaults_error:w \q_recursion_stop
{
\__kernel_msg_error:nnx { xparse } { loop-in-defaults }
- { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
+ { \@@_environment_or_command: }
}
% \end{macrocode}
% To construct \cs{@@_tmp:w}, first go through the arguments
@@ -1485,8 +1614,9 @@
\@@_end_expandable_defaults:nnnNNn {#1} { } {#1} #2#3
{ } { } { } { } { } { } { } { } { } { }
{
- \__kernel_msg_expandable_error:nnn
- { xparse } { loop-in-defaults } {#4}
+ \__kernel_msg_expandable_error:nnf
+ { xparse } { loop-in-defaults }
+ { \exp_args:Nf \tl_trim_spaces:n { \token_to_str:N #4 } }
\use_iv:nnnn
}
\q_stop
@@ -1552,8 +1682,6 @@
% commands will be grabbed expandably and arguments of environments
% will not (because the list of arguments built by non-expandable
% grabbing is used to pass them to the end-environment code).
-% \item Count mandatory arguments, used later to detect which optional
-% arguments are trailing.
% \end{itemize}
% Further checks happen at the end of the loop:
% \begin{itemize}
@@ -1572,7 +1700,6 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_normalize_arg_spec:n #1
{
- \int_zero:N \l_@@_mandatory_args_int
\int_zero:N \l_@@_current_arg_int
\tl_clear:N \l_@@_last_delimiters_tl
\tl_clear:N \l_@@_arg_spec_tl
@@ -1587,7 +1714,7 @@
\int_compare:nNnT \l_@@_current_arg_int > 9
{
\__kernel_msg_error:nnxx { xparse } { too-many-arguments }
- { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
\@@_bad_def:wn
}
\bool_if:NT \l_@@_expandable_bool
@@ -1611,7 +1738,7 @@
\cs_if_exist_use:cF { @@_normalize_type_ \tl_to_str:n {#1} :w }
{
\__kernel_msg_error:nnxx { xparse } { unknown-argument-type }
- { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
\@@_bad_def:wn
}
}
@@ -1699,7 +1826,7 @@
\bool_if:NT \l_@@_long_bool
{
\__kernel_msg_error:nnxx { xparse } { two-markers }
- { \iow_char:N \\ \l_@@_function_tl } { + }
+ { \@@_environment_or_command: } { + }
\@@_bad_def:wn
}
\bool_set_true:N \l_@@_long_bool
@@ -1712,7 +1839,7 @@
\bool_if:NT \l_@@_obey_spaces_bool
{
\__kernel_msg_error:nnxx { xparse } { two-markers }
- { \iow_char:N \\ \l_@@_function_tl } { ! }
+ { \@@_environment_or_command: } { ! }
\@@_bad_def:wn
}
\bool_set_true:N \l_@@_obey_spaces_bool
@@ -1857,6 +1984,31 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_normalize_type_b:w}
+% This argument type is not allowed for commands. This 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
+ {
+ \bool_if:NF \l_@@_environment_bool
+ {
+ \__kernel_msg_error:nnxx
+ { xparse } { invalid-command-arg }
+ { \@@_environment_or_command: } { b }
+ \@@_bad_def:wn
+ }
+ \tl_clear:N \l_@@_last_delimiters_tl
+ \@@_add_arg_spec:n { b }
+ \quark_if_recursion_tail_stop:n {#1}
+ \__kernel_msg_error:nnxx { xparse } { arg-after-body }
+ { \@@_environment_or_command: }
+ { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_single_char_check:n}
% Checks that what should be single characters really are single
% characters (possibly surrounded by spaces).
@@ -1871,13 +2023,13 @@
{ \exp_args:No \tl_to_str:n { \use:nn #1 { } } }
{
\__kernel_msg_warning:nnxx { xparse } { not-single-char }
- { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
}
\group_end:
}
{
\__kernel_msg_error:nnxx { xparse } { not-single-char }
- { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
\@@_bad_def:wn
}
}
@@ -1942,7 +2094,7 @@
\cs_new_protected:Npn \@@_bad_arg_spec:wn #1 \@@_break_point:n #2
{
\__kernel_msg_error:nnxx { xparse } { bad-arg-spec }
- { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#2} }
+ { \@@_environment_or_command: } { \tl_to_str:n {#2} }
}
\cs_new_protected:Npn \@@_bad_def:wn #1 \@@_break_point:n #2 { }
% \end{macrocode}
@@ -1990,10 +2142,9 @@
\bool_if:NT \l_@@_some_obey_spaces_bool
{
\__kernel_msg_error:nnxx { xparse } { non-trailing-obey-spaces }
- { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
\@@_bad_def:wn
}
- \int_incr:N \l_@@_mandatory_args_int
\tl_clear:N \l_@@_last_delimiters_tl
\@@_add_arg_spec:n {#1}
}
@@ -2033,8 +2184,7 @@
%
% For each known argument type there is an appropriate function to actually
% do the addition to the signature. These are separate for expandable and
-% standard functions, as the approaches are different. Of course, if the type
-% is not known at all then a fall-back is needed.
+% standard functions, as the approaches are different.
% \begin{macrocode}
\cs_new_protected:Npn \@@_prepare_signature:N
{
@@ -2098,7 +2248,7 @@
%
% \begin{macro}{\@@_add_type_>:w}
% When a processor is found, the processor code is stored. It will be
-% used by \cs{@@_args_process:} once arguments are all found. Here,
+% used by \cs{@@_args_process:} once arguments are all found. Here too
% the loop calls \cs{@@_prepare_signature_bypass:N} rather than
% \cs{@@_prepare_signature:N} so that the flag is not reset.
% \begin{macrocode}
@@ -2113,13 +2263,25 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_add_type_b:w}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_b:w
+ {
+ \@@_flush_m_args:
+ \@@_add_default:
+ \@@_add_grabber:N b
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_add_type_D:w}
% \begin{macrocode}
\cs_new_protected:Npn \@@_add_type_D:w #1#2#3
{
\@@_flush_m_args:
\@@_add_default:n {#3}
- \@@_add_grabber_optional:N D
+ \@@_add_grabber:N D
\tl_put_right:Nn \l_@@_signature_tl { #1 #2 }
\@@_prepare_signature:N
}
@@ -2134,7 +2296,7 @@
{
\@@_flush_m_args:
\@@_add_default_E:nn {#1} {#2}
- \@@_add_grabber_optional:N E
+ \@@_add_grabber:N E
\tl_put_right:Nn \l_@@_signature_tl { {#1} }
\@@_prepare_signature:N
}
@@ -2149,7 +2311,7 @@
{
\@@_flush_m_args:
\@@_add_default:n {#1}
- \@@_add_grabber_optional:N G
+ \@@_add_grabber:N G
\@@_prepare_signature:N
}
% \end{macrocode}
@@ -2163,7 +2325,7 @@
{
\@@_flush_m_args:
\@@_add_default:
- \@@_add_grabber_mandatory:N l
+ \@@_add_grabber:N l
\@@_prepare_signature:N
}
% \end{macrocode}
@@ -2181,7 +2343,7 @@
{
\@@_add_default:
\bool_if:NTF \l_@@_prefixed_bool
- { \@@_add_grabber_mandatory:N m }
+ { \@@_add_grabber:N m }
{ \int_incr:N \l_@@_m_args_int }
\@@_prepare_signature:N
}
@@ -2195,7 +2357,7 @@
{
\@@_flush_m_args:
\@@_add_default:n {#3}
- \@@_add_grabber_mandatory:N R
+ \@@_add_grabber:N R
\tl_put_right:Nn \l_@@_signature_tl { #1 #2 }
\@@_prepare_signature:N
}
@@ -2210,7 +2372,7 @@
{
\@@_flush_m_args:
\@@_add_default:
- \@@_add_grabber_optional:N t
+ \@@_add_grabber:N t
\tl_put_right:Nn \l_@@_signature_tl {#1}
\@@_prepare_signature:N
}
@@ -2225,7 +2387,7 @@
{
\@@_flush_m_args:
\@@_add_default:
- \@@_add_grabber_mandatory:N u
+ \@@_add_grabber:N u
\tl_put_right:Nn \l_@@_signature_tl { {#1} }
\@@_prepare_signature:N
}
@@ -2241,7 +2403,7 @@
{
\@@_flush_m_args:
\exp_args:No \@@_add_default:n \c_novalue_tl
- \@@_add_grabber_mandatory:N v
+ \@@_add_grabber:N v
\@@_prepare_signature:N
}
% \end{macrocode}
@@ -2251,9 +2413,7 @@
% As \texttt{m} arguments are simply counted, there is a need to add
% them to the token register in a block. As this function can only
% be called if something other than \texttt{m} turns up, the flag can
-% be switched here. The total number of mandatory arguments which
-% remain to be added to
-% the signature is also decreased by the appropriate amount.
+% be switched here.
% \begin{macrocode}
\cs_new_protected:Npn \@@_flush_m_args:
{
@@ -2261,7 +2421,6 @@
{
\tl_put_right:Nx \l_@@_signature_tl
{ \exp_not:c { @@_grab_m_ \int_use:N \l_@@_m_args_int :w } }
- \int_sub:Nn \l_@@_mandatory_args_int { \l_@@_m_args_int }
\tl_put_right:Nx \l_@@_process_all_tl
{ \prg_replicate:nn { \l_@@_m_args_int } { { } } }
}
@@ -2270,8 +2429,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@@_add_grabber_mandatory:N}
-% \begin{macro}{\@@_add_grabber_optional:N}
+% \begin{macro}{\@@_add_grabber:N}
% 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
@@ -2279,12 +2437,7 @@
% 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
- {
- \@@_add_grabber_optional:N #1
- \int_decr:N \l_@@_mandatory_args_int
- }
-\cs_new_protected:Npn \@@_add_grabber_optional:N #1
+\cs_new_protected:Npn \@@_add_grabber:N #1
{
\tl_put_right:Nx \l_@@_signature_tl
{
@@ -2304,7 +2457,6 @@
}
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\@@_add_default:n, \@@_add_default:, \@@_add_default_E:nn}
% Store the default value of an argument, or rather code that gives
@@ -2593,6 +2745,60 @@
% calls \cs{@@_add_arg:n}, responsible for calling processors and
% grabbing further arguments.
%
+% \begin{macro}
+% {
+% \@@_grab_b:w,
+% \@@_grab_b_long:w,
+% \@@_grab_b_obey_spaces:w,
+% \@@_grab_b_long_obey_spaces:w,
+% \@@_grab_b_aux:NNw,
+% \@@_grab_b_end:Nw
+% }
+% This uses the well-tested code of \texttt{D}-type arguments,
+% skipping the peeking step because the \texttt{b}-type argument is
+% always present, and adding a cleanup stage at the end by hijacking
+% the signature. The clean-up consists of properly
+% dealing with \cs{l_@@_args_tl} and also putting back the \cs{end}
+% that served as an end-delimiter: this \cs{end} receives the
+% environment name as its argument and is run normally. The
+% \texttt{D}-type code stores the argument found (body of the
+% environment) as a brace group in \cs{l_@@_args_tl} and depending on
+% the presence of a prefix~|!| we trim spaces or not before adding
+% this braced argument into the saved \cs{l_@@_args_tl}.
+% The strange \verb*|\begin | control sequence is there for display
+% purposes only: it has to look like |\begin| in the terminal but
+% not to delimited arguments.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_b:w
+ { \@@_grab_b_aux:NNw \cs_set_protected_nopar:Npn \tl_trim_spaces:n }
+\cs_new_protected:Npn \@@_grab_b_long:w
+ { \@@_grab_b_aux:NNw \cs_set_protected:Npn \tl_trim_spaces:n }
+\cs_new_protected:Npn \@@_grab_b_obey_spaces:w
+ { \@@_grab_b_aux:NNw \cs_set_protected_nopar:Npn \exp_not:n }
+\cs_new_protected:Npn \@@_grab_b_long_obey_spaces:w
+ { \@@_grab_b_aux:NNw \cs_set_protected:Npn \exp_not:n }
+\cs_new_protected:Npn \@@_grab_b_aux:NNw #1#2#3 \@@_run_code:
+ {
+ \@@_grab_D_aux:NNnN \begin \end {#3} #1
+ \tl_put_left:Nn \l_@@_signature_tl { \@@_grab_b_end:Nw #2 }
+ \tl_set_eq:NN \l_@@_saved_args_tl \l_@@_args_tl
+ \tl_clear:N \l_@@_args_tl
+ \exp_args:Nc \l_@@_fn_tl { begin ~ }
+ }
+\cs_new_protected:Npn \@@_grab_b_end:Nw #1#2 \@@_run_code:
+ {
+ \tl_set:Nx \l_@@_args_tl
+ {
+ \exp_not:V \l_@@_saved_args_tl
+ { \exp_after:wN #1 \l_@@_args_tl }
+ }
+ #2
+ \@@_run_code:
+ \end
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_grab_D:w}
% \begin{macro}{\@@_grab_D_long:w}
% \begin{macro}{\@@_grab_D_obey_spaces:w}
@@ -3037,7 +3243,7 @@
{ \@@_grab_D_call:Nw #1 }
{
\__kernel_msg_error:nnxx { xparse } { missing-required }
- { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
+ { \@@_environment_or_command: }
{ \token_to_str:N #1 }
\@@_add_arg:o \c_novalue_tl
}
@@ -3316,14 +3522,14 @@
\peek_meaning_remove:NTF \char_generate:nn { \tex_endlinechar:D } { 6 }
{
\__kernel_msg_error:nnxxx { xparse } { verbatim-newline }
- { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
+ { \@@_environment_or_command: }
{ \tl_to_str:N \l_@@_v_arg_tl }
{ \tl_to_str:n {#1} }
\@@_add_arg:o \c_novalue_tl
}
{
\__kernel_msg_error:nnxxx { xparse } { verbatim-tokenized }
- { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
+ { \@@_environment_or_command: }
{ \tl_to_str:N \l_@@_v_arg_tl }
{ \tl_to_str:n {#1} }
\@@_add_arg:o \c_novalue_tl
@@ -3673,8 +3879,10 @@
\q_nil { } ##2 \ERROR \q_@@ \ERROR
}
{
- \__kernel_msg_expandable_error:nnnn
- { xparse } { missing-required } {##5} {##2}
+ \__kernel_msg_expandable_error:nnff
+ { xparse } { missing-required }
+ { \exp_args:Nf \tl_trim_spaces:n { \token_to_str:N ##5 } }
+ { \tl_to_str:n {##2} }
##4 {#1} \q_@@ ##5 ##6 {##7}
}
}
@@ -3709,8 +3917,10 @@
##6 \ERROR
}
{
- \__kernel_msg_expandable_error:nnnn
- { xparse } { missing-required } {##4} {##2}
+ \__kernel_msg_expandable_error:nnff
+ { xparse } { missing-required }
+ { \exp_args:Nf \tl_trim_spaces:n { \token_to_str:N ##4 } }
+ { \tl_to_str:n {##2} }
##3 {#1} \q_@@ ##4 ##5 {##6}
}
}
@@ -3891,35 +4101,38 @@
% \subsection{Access to the argument specification}
%
% \begin{macro}{\@@_get_arg_spec_error:N, \@@_get_arg_spec_error:n}
+% \begin{macro}{\@@_get_arg_spec_error_aux:n}
% Provide an informative error when trying to get the argument
% specification of a non-\pkg{xparse} command or environment.
% \begin{macrocode}
\cs_new_protected:Npn \@@_get_arg_spec_error:N #1
{
- \cs_if_exist:NTF #1
- {
- \__kernel_msg_error:nnx { xparse } { non-xparse-command }
- { \token_to_str:N #1 }
- }
- {
- \__kernel_msg_error:nnx { xparse } { unknown-command }
- { \token_to_str:N #1 }
- }
+ \bool_set_false:N \l_@@_environment_bool
+ \tl_set:Nn \l_@@_fn_tl {#1}
+ \@@_get_arg_spec_error_aux:n { \cs_if_exist:NTF #1 }
}
\cs_new_protected:Npn \@@_get_arg_spec_error:n #1
{
- \cs_if_exist:cTF {#1}
+ \bool_set_true:N \l_@@_environment_bool
+ \str_set:Nx \l_@@_environment_str {#1}
+ \@@_get_arg_spec_error_aux:n
+ { \cs_if_exist:cTF { \l_@@_environment_str } }
+ }
+\cs_new_protected:Npn \@@_get_arg_spec_error_aux:n #1
+ {
+ #1
{
- \__kernel_msg_error:nnx { xparse } { non-xparse-environment }
- { \tl_to_str:n {#1} }
+ \__kernel_msg_error:nnx { xparse } { non-xparse }
+ { \@@_environment_or_command: }
}
{
- \__kernel_msg_error:nnx { xparse } { unknown-environment }
- { \tl_to_str:n {#1} }
+ \__kernel_msg_error:nnx { xparse } { unknown }
+ { \@@_environment_or_command: }
}
}
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\@@_get_arg_spec:NTF}
% If the command is not an \pkg{xparse} command, complain. If it is,
@@ -4076,21 +4289,22 @@
% that its |arg_spec| is empty (this also excludes non-macros) and
% that its |replacement_spec| starts with either \cs{@@_start:nNNnnn}
% (non-expandable command) or \cs{@@_start_expandable:nNNNNn}
-% (expandable command).
+% (expandable command) or \cs{@@_start_env:nnnnn} (environment).
% \begin{macrocode}
\cs_new_protected:Npn \@@_cmd_if_xparse:NTF #1
{
\exp_args:Nf \str_case_e:nnTF
{
- \exp_args:Nf \tl_if_empty:nT { \token_get_arg_spec:N #1 }
+ \exp_args:Nf \tl_if_empty:nT { \cs_argument_spec:N #1 }
{
\exp_last_unbraced:Nf \@@_cmd_if_xparse_aux:w
- { \token_get_replacement_spec:N #1 } ~ \q_stop
+ { \cs_replacement_spec:N #1 } ~ \q_stop
}
}
{
{ \token_to_str:N \@@_start:nNNnnn } { }
{ \token_to_str:N \@@_start_expandable:nNNNNn } { }
+ { \token_to_str:N \@@_start_env:nnnnn } { }
}
}
\cs_new:Npn \@@_cmd_if_xparse_aux:w #1 ~ #2 \q_stop {#1}
@@ -4117,42 +4331,70 @@
%
% \subsection{Messages}
%
-% Some messages intended as errors.
+% \begin{macro}{\@@_environment_or_command:}
+% \begin{variable}{\c_@@_ignore_def_tl}
+% Two texts used in several messages.
+% \begin{macrocode}
+\cs_new:Npn \@@_environment_or_command:
+ {
+ \bool_if:NTF \l_@@_environment_bool
+ { environment ~ ' \l_@@_environment_str ' }
+ {
+ command ~ '
+ \exp_args:Nf \tl_trim_spaces:n
+ { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
+ '
+ }
+ }
+\tl_const:Nn \c_@@_ignore_def_tl
+ { \\ \\ LaTeX~will~ignore~this~entire~definition. }
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+%
+% Some messages intended as errors when defining commands/environments.
% \begin{macrocode}
+\__kernel_msg_new:nnnn { xparse } { arg-after-body }
+ { In~the~definition~of~#1,~b~(body)~argument~must~be~last. }
+ {
+ The~'body'~argument~type~is~followed~by~'#2'~in~the~argument~
+ specification~of~the~#1.~This~is~not~allowed.
+ \c_@@_ignore_def_tl
+ }
\__kernel_msg_new:nnnn { xparse } { bad-arg-spec }
- { Bad~argument~specification~'#2'~for~command~'#1'. }
+ { Bad~argument~specification~'#2'~for~#1. }
{
The~argument~specification~provided~was~not~valid:~
- one~or~more~mandatory~pieces~of~information~were~missing. \\ \\
- LaTeX~will~ignore~this~entire~definition.
+ one~or~more~mandatory~pieces~of~information~were~missing.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { command-already-defined }
{ Command~'#1'~already~defined! }
{
You~have~used~#2~
- with~a~command~that~already~has~a~definition. \\
+ with~a~command~that~already~has~a~definition. \\ \\
The~existing~definition~of~'#1'~will~not~be~altered.
}
\__kernel_msg_new:nnnn { xparse } { command-not-yet-defined }
{ Command ~'#1'~not~yet~defined! }
{
You~have~used~#2~
- with~a~command~that~was~never~defined. \\
- LaTeX~will~ignore~this~entire~definition.
+ with~a~command~that~was~never~defined.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { environment-already-defined }
{ Environment~'#1'~already~defined! }
{
You~have~used~\NewDocumentEnvironment
- with~an~environment~that~already~has~a~definition. \\
- The~existing~definition~of~'#1'~will~be~overwritten.
+ with~an~environment~that~already~has~a~definition. \\ \\
+ The~existing~definition~of~'#1'~will~not~be~altered.
}
\__kernel_msg_new:nnnn { xparse } { environment-not-yet-defined }
{ Environment~'#1'~not~yet~defined! }
{
You~have~used~\RenewDocumentEnvironment
- with~an~environment~that~was~never~defined. \\
- LaTeX~will~ignore~this~entire~definition.
+ with~an~environment~that~was~never~defined.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { expandable-ending-optional }
{
@@ -4164,25 +4406,26 @@
(or~no~arguments~at~all).~You~cannot~have~a~terminal~optional~
argument~with~expandable~commands.
}
-\__kernel_msg_new:nnnn { xparse } { if-boolean }
- { Invalid~use~\iow_char:N\\IfBooleanTF~{#1} }
- {
- The~first~argument~of~\iow_char:N\\IfBoolean(TF/T/F)~must~be~
- a~boolean~argument~obtained~from~parsing~'s'~or~'t'~arguments.
- }
\__kernel_msg_new:nnnn { xparse } { inconsistent-long }
{ Inconsistent~long~arguments~for~expandable~command~'#1'. }
{
The~arguments~for~an~expandable~command~must~not~involve~short~
arguments~after~long~arguments.~You~have~tried~to~mix~the~two~types.
}
+\__kernel_msg_new:nnnn { xparse } { invalid-command-arg }
+ { Argument~type~'#2'~not~available~for~#1. }
+ {
+ The~letter~'#2'~can~only~be~used~in~environment~argument~
+ specifications,~not~for~commands.
+ \\ \\
+ LaTeX~will~ignore~this~entire~definition.
+ }
\__kernel_msg_new:nnnn { xparse } { invalid-expandable-argument-type }
{ Argument~type~'#2'~not~available~for~expandable~command~'#1'. }
{
- The~letter~'#2'~does~not~specify~an~argument~type~which~can~be~used~
+ The~letter~'#2'~specifies~an~argument~type~which~cannot~be~used~
in~an~expandable~command.
- \\ \\
- LaTeX~will~ignore~this~entire~definition.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { invalid-after-optional-expandably }
{
@@ -4190,41 +4433,15 @@
for~expandable~command~'#1'.
}
{
- The~letter~'#2'~does~not~specify~an~argument~type~which~can~be~used~
+ The~letter~'#2'~specifies~an~argument~type~which~cannot~be~used~
in~an~expandable~command~after~an~optional~argument.
- \\ \\
- LaTeX~will~ignore~this~entire~definition.
- }
-\__kernel_msg_new:nnnn { xparse } { loop-in-defaults }
- { Circular~dependency~in~defaults~of~'#1'. }
- {
- 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 } { 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.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { non-trailing-obey-spaces }
- { Prefix~'!'~used~before~mandatory~argument~'#2'~of~command~'#1'. }
+ { Prefix~'!'~used~before~mandatory~argument~'#2'~of~#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. }
- {
- You~have~asked~for~the~argument~specification~for~a~command~'#1',~
- but~this~is~not~a~command~defined~using~xparse.
- }
-\__kernel_msg_new:nnnn { xparse } { non-xparse-environment }
- { Environment~'#1'~not~defined~using~xparse. }
- {
- You~have~asked~for~the~argument~specification~for~an~environment~'#1',~
- but~this~is~not~an~environment~defined~using~xparse.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { not-definable }
{ First~argument~of~'#2'~must~be~a~command. }
@@ -4232,89 +4449,106 @@
The~first~argument~of~'#2'~should~be~the~document~command~that~will~
be~defined.~The~provided~argument~'#1'~is~a~character.~Perhaps~a~
backslash~is~missing?
- \\ \\
- LaTeX~will~ignore~this~entire~definition.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { not-one-token }
{ First~argument~of~'#2'~must~be~a~command. }
{
The~first~argument~of~'#2'~should~be~the~document~command~that~will~
be~defined.~The~provided~argument~'#1'~contains~more~than~one~
- token.
- \\ \\
- LaTeX~will~ignore~this~entire~definition.
+ token.~Perhaps~a~backslash~is~missing?
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { not-single-char }
{
- Argument~delimiter~'#2'~for~the~command~'#1'~should~be~
+ Argument~delimiter~'#2'~for~the~#1~should~be~
a~single~character.
}
{
The~argument~specification~provided~was~not~valid:~in~a~place~
- where~a~single~character~is~required,~LaTeX~found~'#2'. \\ \\
- LaTeX~will~ignore~this~entire~definition.
+ where~a~single~character~is~required,~LaTeX~found~'#2'.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { processor-in-expandable }
{ Argument~processor~'>{#2}'~cannot~be~used~for~the~expandable~command~'#1'. }
{
The~argument~specification~for~#1~contains~a~processor~function:~
- this~is~only~supported~for~standard~robust~commands. \\ \\
- LaTeX~will~ignore~this~entire~definition.
- }
-\__kernel_msg_new:nnnn { xparse } { split-excess-tokens }
- { Too~many~'#1'~tokens~when~trying~to~split~argument. }
- {
- LaTeX~was~asked~to~split~the~input~'#3'~
- at~each~occurrence~of~the~token~'#1',~up~to~a~maximum~of~#2~parts.~
- There~were~too~many~'#1'~tokens.
+ this~is~only~supported~for~standard~robust~commands.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { too-many-arguments }
- { Too~many~arguments~in~argument~specification~'#2'~of~command~'#1'. }
+ { Too~many~arguments~in~argument~specification~'#2'~of~#1. }
{
The~argument~specification~provided~has~more~than~9~arguments.~
- This~cannot~be~implemented. \\ \\
- LaTeX~will~ignore~this~entire~definition.
+ This~cannot~be~implemented.
+ \c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { two-markers }
- { Two~'#2'~apply~to~the~same~argument~in~argument~specification~of~command~'#1'. }
+ { Two~'#2'~apply~to~the~same~argument~in~argument~specification~of~#1. }
{
The~argument~specification~provided~has~two~markers~'#2'~applying~
to~the~same~argument;~these~are~redundant.
}
\__kernel_msg_new:nnnn { xparse } { unknown-argument-type }
- { Unknown~argument~type~'#2'~for~the~command~'#1'. }
+ { Unknown~argument~type~'#2'~for~the~#1. }
{
- The~letter~'#2'~does~not~specify~a~known~argument~type.~
- LaTeX~will~ignore~this~entire~definition.
+ The~letter~'#2'~does~not~specify~a~known~argument~type.
+ \c_@@_ignore_def_tl
+ }
+% \end{macrocode}
+%
+% Errors when using commands/environments. The \texttt{if-boolean}
+% message is always used in expandable errors. The
+% \texttt{loop-in-defaults} and \texttt{missing-required} messages can
+% be expandable or not expandable.
+% \begin{macrocode}
+\__kernel_msg_new:nnn { xparse } { if-boolean }
+ { Invalid~use~\iow_char:N\\IfBooleanTF~{#1} }
+\__kernel_msg_new:nnnn { xparse } { loop-in-defaults }
+ { Defaults~of~#1~have~circular~dependency. }
+ {
+ The~default~values~of~two~or~more~arguments~of~the~#1~
+ depend~on~each~other~in~a~way~that~cannot~be~resolved.
}
-\__kernel_msg_new:nnnn { xparse } { unknown-command }
- { Unknown~document~command~'#1'. }
+\__kernel_msg_new:nnnn { xparse } { missing-required }
+ { Missing~required~argument~for~#1. }
{
- You~have~asked~for~the~argument~specification~for~a~command~'#1',~
- but~it~is~not~defined.
+ The~current~#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 } { unknown-environment }
- { Unknown~document~environment~'#1'. }
+\__kernel_msg_new:nnnn { xparse } { non-xparse }
+ { \str_upper_case:n #1~not~defined~using~xparse. }
{
- You~have~asked~for~the~argument~specification~for~an~environment~'#1',~
+ You~have~asked~for~the~argument~specification~for~the~#1,~
+ but~this~was~not~defined~using~xparse.
+ }
+\__kernel_msg_new:nnnn { xparse } { split-excess-tokens }
+ { Too~many~'#1'~tokens~when~trying~to~split~argument. }
+ {
+ LaTeX~was~asked~to~split~the~input~'#3'~
+ at~each~occurrence~of~the~token~'#1',~up~to~a~maximum~of~#2~parts.~
+ There~were~too~many~'#1'~tokens.
+ }
+\__kernel_msg_new:nnnn { xparse } { unknown }
+ { Unknown~document~#1. }
+ {
+ You~have~asked~for~the~argument~specification~for~the~#1,~
but~it~is~not~defined.
}
\__kernel_msg_new:nnnn { xparse } { verbatim-newline }
- { Verbatim~argument~of~'#1'~ended~by~end~of~line. }
+ { Verbatim~argument~of~#1~ended~by~end~of~line. }
{
- The~verbatim~argument~of~'#1'~cannot~contain~more~than~one~line,~
+ The~verbatim~argument~of~the~#1~cannot~contain~more~than~one~line,~
but~the~end~
- of~the~current~line~has~been~reached.~You~have~probably~forgotten~the~
+ of~the~current~line~has~been~reached.~You~may~have~forgotten~the~
closing~delimiter.
\\ \\
LaTeX~will~ignore~'#2'.
}
\__kernel_msg_new:nnnn { xparse } { verbatim-tokenized }
+ { The~verbatim~#1~cannot~be~used~inside~an~argument. }
{
- The~verbatim~command~'#1'~cannot~be~used~inside~an~argument.~
- }
- {
- The~command~'#1'~takes~a~verbatim~argument.~
+ The~#1~takes~a~verbatim~argument.~
It~may~not~appear~within~the~argument~of~another~function.~
It~received~an~illegal~token \tl_if_empty:nF {#3} { ~'#3' } .
\\ \\
@@ -4435,7 +4669,7 @@
\cs_if_exist:cTF {#1}
{ \__kernel_msg_error:nnx { xparse } { environment-already-defined } {#1} }
{ \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
-}
+ }
\cs_new_protected:Npn \RenewDocumentEnvironment #1#2#3#4
{
\cs_if_exist:cTF {#1}
@@ -4456,7 +4690,10 @@
% \begin{macro}{\RenewExpandableDocumentCommand}
% \begin{macro}{\ProvideExpandableDocumentCommand}
% \begin{macro}{\DeclareExpandableDocumentCommand}
-% The expandable versions are essentially the same as the basic functions.
+% The expandable versions are essentially the same as the basic
+% functions. The strange \cs{use:nnn} is there in case |#1| is
+% surrounded with spaces, as can happen with usual document catcodes
+% in \cs{RenewExpandableDocumentCommand} |{| |\!| |}| \ldots{}
% \begin{macrocode}
\cs_new_protected:Npn \NewExpandableDocumentCommand #1#2#3
{
@@ -4505,19 +4742,34 @@
%
% \begin{macro}{\IfBooleanT, \IfBooleanF, \IfBooleanTF}
% The logical \meta{true} and \meta{false} statements are just the
-% normal \cs{c_true_bool} and \cs{c_false_bool}, so testing for them is
-% done with the \cs{bool_if:NTF} functions from \textsf{l3prg}.
+% normal \cs{c_true_bool} and \cs{c_false_bool} so \cs{bool_if:NTF} is
+% almost enough. However, this code-level function blows up badly
+% when passed invalid input. We want \cs{IfBooleanTF} to accept a
+% single (non-space) token equal to \cs{c_true_bool} or
+% \cs{c_false_bool}, possibly surrounded by spaces. If the input is
+% blank or multiple items, jump to the error and pick the false
+% branch. If the input, ignoring spaces (we do this by omitting
+% braces in the \cs{tl_if_single_token:nF} test), is not a single
+% token then jump to the error as well. It is then safe to compare
+% the token to the two booleans, picking the appropriate branch. If
+% neither matches, we jump to the error as well.
% \begin{macrocode}
\cs_new:Npn \IfBooleanTF #1
{
- \bool_lazy_and:nnTF
- { \tl_if_single_p:n {#1} }
- { \tl_if_single_token_p:n #1 }
- { \bool_if:NTF #1 }
- {
- \__kernel_msg_error:nnn { xparse } { if-boolean } {#1}
- \use_ii:nn
- }
+ \tl_if_single:nF {#1}
+ { \prg_break:n { \use:n } }
+ \tl_if_single_token:nF #1
+ { \prg_break:n { \use:n } }
+ \token_if_eq_meaning:NNT #1 \c_true_bool
+ { \prg_break:n { \use_ii:nnn } }
+ \token_if_eq_meaning:NNT #1 \c_false_bool
+ { \prg_break:n { \use_iii:nnn } }
+ \prg_break:n { \use:n }
+ \prg_break_point:
+ {
+ \__kernel_msg_expandable_error:nnn { xparse } { if-boolean } {#1}
+ \use_ii:nn
+ }
}
\cs_new:Npn \IfBooleanT #1#2 { \IfBooleanTF {#1} {#2} { } }
\cs_new:Npn \IfBooleanF #1 { \IfBooleanTF {#1} { } }