From d12b5fe6d47c6b6188b48f5a442dc625b1eea5b1 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 10 Feb 2017 23:29:10 +0000 Subject: l3 (10feb17) git-svn-id: svn://tug.org/texlive/trunk@43183 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/l3packages/l3keys2e/l3keys2e.dtx | 8 +- .../source/latex/l3packages/xfrac/xfrac.dtx | 8 +- .../source/latex/l3packages/xparse/xparse.dtx | 2306 ++++++++++++-------- .../latex/l3packages/xtemplate/xtemplate.dtx | 8 +- 4 files changed, 1445 insertions(+), 885 deletions(-) (limited to 'Master/texmf-dist/source/latex/l3packages') diff --git a/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx b/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx index df48e99599f..9c895dd3b24 100644 --- a/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx +++ b/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx @@ -23,8 +23,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/02/07] -%\@ifpackagelater{expl3}{2017/02/07} +\RequirePackage{expl3}[2017/02/10] +%\@ifpackagelater{expl3}{2017/02/10} % {} % {% % \PackageError{l3keys2e}{Support package l3kernel too old} @@ -38,8 +38,8 @@ % } \def\ExplFileName{l3keys2e} \def\ExplFileDescription{LaTeX2e option processing using LaTeX3 keys} -\def\ExplFileDate{2017/02/07} -\def\ExplFileVersion{6846} +\def\ExplFileDate{2017/02/10} +\def\ExplFileVersion{6878} % %<*driver> \documentclass[full]{l3doc} diff --git a/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx b/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx index a09cbfae677..2d01dd37e08 100644 --- a/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx @@ -24,8 +24,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/02/07] -%\@ifpackagelater{expl3}{2017/02/07} +\RequirePackage{expl3}[2017/02/10] +%\@ifpackagelater{expl3}{2017/02/10} % {} % {% % \PackageError{xfrac}{Support package l3kernel too old} @@ -40,8 +40,8 @@ \RequirePackage{amstext,graphicx,l3keys2e,textcomp,xparse,xtemplate} \def\ExplFileName{xfrac} \def\ExplFileDescription{L3 Experimental split-level fractions} -\def\ExplFileDate{2017/02/07} -\def\ExplFileVersion{6846} +\def\ExplFileDate{2017/02/10} +\def\ExplFileVersion{6878} % %<*driver> \documentclass[full]{l3doc} diff --git a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx index f4138d1b0e0..768a9a317a5 100644 --- a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx @@ -4,7 +4,7 @@ %% David Carlisle %% (C) Copyright 2004-2008 Frank Mittelbach, %% The LaTeX3 Project -%% (C) Copyright 2009-2016 The LaTeX3 Project +%% (C) Copyright 2009-2017 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 @@ -27,8 +27,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/02/07] -%\@ifpackagelater{expl3}{2017/02/07} +\RequirePackage{expl3}[2017/02/10] +%\@ifpackagelater{expl3}{2017/02/10} % {} % {% % \PackageError{xparse}{Support package l3kernel too old} @@ -42,8 +42,8 @@ % } \def\ExplFileName{xparse} \def\ExplFileDescription{L3 Experimental document command parser} -\def\ExplFileDate{2017/02/07} -\def\ExplFileVersion{6846} +\def\ExplFileDate{2017/02/10} +\def\ExplFileVersion{6878} % %<*driver> \documentclass[full]{l3doc} @@ -184,10 +184,11 @@ % \item[e] An optional set of \emph{embellishments}, each of which requires a % \emph{value}. If a key is not present, |-NoValue-| is returned. % The returned data is a token list comprising one braced entry per key, -% ordered as for the key list in the signature. +% ordered as for the key list in the argument specification. Given as +% \texttt{e}\marg{tokens}. % \emph{This is an experimental type}. -% \item[E] As for \texttt{E} but returns one or more \meta{defaults} -% if values are not given: \texttt{E}\marg{defaults}. See +% \item[E] As for \texttt{e} but returns one or more \meta{defaults} +% if values are not given: \texttt{E}\marg{tokens}\marg{defaults}. See % Section~\ref{sec:embellishment} for more details. % \end{itemize} % @@ -249,10 +250,14 @@ % argument processors is a somewhat advanced topic, (or at least a less % commonly used feature) and is covered in Section~\ref{sec:processors}. % -% By default, an argument of type~\texttt{v} must be at most one line. -% Prefixing with \texttt{+} allows line breaks within the argument. The -% argument is given as a string of characters with category codes~$12$ -% or~$13$, except spaces, which have category code~$10$. +% 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}, +% \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 +% followed by \texttt{m} type arguments. % % \subsection{Spacing and optional arguments} % @@ -288,7 +293,7 @@ % delimited} (\texttt{R}-type) argument is that an error will be raised if % the latter is missing. Thus for example % \begin{verbatim} -% \DeclareDocumentCommand\foo{r()m} +% \DeclareDocumentCommand {\foo} {r()m} {} % \foo{oops} % \end{verbatim} % will lead to an error message being issued. The marker |-NoValue-| @@ -305,17 +310,68 @@ % result in the grabbed argument consisting of tokens of category codes % $12$~(\enquote{other}) and $13$~(\enquote{active}), except spaces, % which are given category code $10$~(\enquote{space}). The argument is -% delimited in a similar manner to the \LaTeXe{} \cs{verb} function. +% delimited in a similar manner to the \LaTeXe{} \cs{verb} function, or +% by (correctly nested) pairs of braces. % % Functions containing verbatim arguments cannot appear in the arguments % of other functions. The \texttt{v}~argument specifier includes code to check % this, and will raise an error if the grabbed argument has already been % tokenized by \TeX{} in an irreversible way. % +% By default, an argument of type~\texttt{v} must be at most one line. +% Prefixing with \texttt{+} allows line breaks within the argument. +% % Users should note that support for verbatim arguments is somewhat % experimental. Feedback is therefore very welcome on the \texttt{LaTeX-L} % mailing list. % +% \subsection{Default values of arguments} +% +% Uppercase argument types (\texttt{O}, \texttt{D}, \ldots{}) allow to +% specify a default value to be used when the argument is missing; their +% lower-case counterparts use the special marker |-NoValue-|. The +% default value can be expressed in terms of the value of any other +% arguments by using |#1|, |#2|, and so on. +% \begin{verbatim} +% \DeclareDocumentCommand {\conjugate} { m O{#1ed} O{#2} } {(#1,#2,#3)} +% \conjugate {walk} % => (walk,walked,walked) +% \conjugate {find} [found] % => (find,found,found) +% \conjugate {do} [did] [done] % => (do,did,done) +% \end{verbatim} +% The default values may refer to arguments that appear later in the +% argument specification. For instance a command could accept two +% optional arguments, equal by default: +% \begin{verbatim} +% \DeclareDocumentCommand {\margins} { O{#3} m O{#1} m } {(#1,#2,#3,#4)} +% \margins {a} {b} % => {(-NoValue-,a,-NoValue-,b)} +% \margins [1cm] {a} {b} % => {(1cm,a,1cm,b)} +% \margins {a} [1cm] {b} % => {(1cm,a,1cm,b)} +% \margins [1cm] {a} [2cm] {b} % => {(1cm,a,2cm,b)} +% \end{verbatim} +% +% Users should note that support for default arguments referring to +% other arguments is somewhat experimental. Feedback is therefore very +% welcome on the \texttt{LaTeX-L} mailing list. +% +% \subsection{Default values for \enquote{embellishments}} +% \label{sec:embellishment} +% +% The \texttt{E}-type argument allows one default value per test token. +% This is achieved by giving a list of defaults for each entry in the +% list, for example: +% \begin{verbatim} +% E{^_}{{UP}{DOWN}} +% \end{verbatim} +% If the list of default values is \emph{shorter} than the list of test tokens, +% the special \cs{NoValue} marker will be returned (as for the \texttt{e}-type +% argument). Thus for example +% \begin{verbatim} +% E{^_}{{UP}} +% \end{verbatim} +% has default \texttt{UP} for the |^| test token, but will return the +% \cs{NoValue} marker as a default for |_|. This allows mixing of explicit +% defaults with testing for missing values. +% % \subsection{Declaring commands and environments} % % With the concept of an argument specifier defined, it is now @@ -472,25 +528,6 @@ % take based on this information. % \end{function} % -% \subsection{Default values for \enquote{embellishments}} -% \label{sec:embellishment} -% -% The \texttt{E}-type argument allows one default value per test token. -% This is achieved by giving a list of defaults for each entry in the -% list, for example: -% \begin{verbatim} -% E{^_}{{UP}{DOWN}} -% \end{verbatim} -% If the list of default values is \emph{shorter} than the list of test tokens, -% the special \cs{NoValue} marker will be returned (as for the \texttt{e}-type -% argument). Thus for example -% \begin{verbatim} -% E{^_}{{UP}} -% \end{verbatim} -% has default \texttt{UP} for the |^| test token, but will return the -% \cs{NoValue} marker as a default for |_|. This allows mixing of explicit -% defaults with testing for missing values. -% % \subsection{Argument processors} % \label{sec:processors} % @@ -652,8 +689,8 @@ % to mix short and long argument types. % \item The mandatory argument types \texttt{l} and \texttt{u} are % not available. -% \item The \enquote{optional group} argument types \texttt{g} and -% \texttt{G} are not available. +% \item The optional argument types \texttt{g} +% and \texttt{G} are not available. % \item The \enquote{verbatim} argument type \texttt{v} is not available. % \item Argument processors (using \texttt{>}) are not available. % \item It is not possible to differentiate between, for example @@ -742,17 +779,6 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\c_@@_shorthands_prop} -% Shorthands are stored as a property list: this is set up here as it -% is a constant. -% \begin{macrocode} -\prop_new:N \c_@@_shorthands_prop -\prop_put:Nnn \c_@@_shorthands_prop { o } { d[] } -\prop_put:Nnn \c_@@_shorthands_prop { O } { D[] } -\prop_put:Nnn \c_@@_shorthands_prop { s } { t* } -% \end{macrocode} -% \end{variable} -% % \begin{variable}{\c_@@_special_chars_seq} % In \IniTeX{} mode, we store special characters in a sequence. % Maybe |$| or |&| will have to be added later. @@ -774,6 +800,22 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_all_long_set_bool} +% Whether \cs{l_@@_all_long_bool}'s value is fixed yet or not. This +% is to deal with the case of leading \texttt{t}-type argument, whose +% \enquote{long} status should be ignored. +% \begin{macrocode} +\bool_new:N \l_@@_all_long_set_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_arg_spec_tl} +% Holds the argument specification after normalization of shorthands. +% \begin{macrocode} +\tl_new:N \l_@@_arg_spec_tl +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_args_tl} % Token list variable for grabbed arguments. % \begin{macrocode} @@ -781,11 +823,12 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_command_arg_specs_prop} -% Used to record all document commands created, and the argument -% specifications that go with these. +% \begin{variable}{\l_@@_args_i_tl, \l_@@_args_ii_tl} +% Hold the modified arguments when dealing with default values or +% processors. % \begin{macrocode} -\prop_new:N \l_@@_command_arg_specs_prop +\tl_new:N \l_@@_args_i_tl +\tl_new:N \l_@@_args_ii_tl % \end{macrocode} % \end{variable} % @@ -798,6 +841,17 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_defaults_bool, \l_@@_defaults_tl} +% The boolean indicates whether there are any argument with default +% value; the token list holds the code to determine these default +% values in terms of other arguments, and dummy code for arguments +% that do not need a default. +% \begin{macrocode} +\bool_new:N \l_@@_defaults_bool +\tl_new:N \l_@@_defaults_tl +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_environment_bool} % Generating environments uses the same mechanism as generating functions. % However, full processing of arguments is always needed for environments, @@ -807,14 +861,6 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_environment_arg_specs_prop} -% Used to record all document environment created, and the argument -% specifications that go with these. -% \begin{macrocode} -\prop_new:N \l_@@_environment_arg_specs_prop -% \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. @@ -837,6 +883,14 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\g_@@_grabber_int} +% Used (in exceptional cases) to get unique names for grabbers used by +% expandable commands. +% \begin{macrocode} +\int_new:N \g_@@_grabber_int +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_fn_tl} % For passing the pre-formed name of the auxiliary to be used as the % parsing function. @@ -845,6 +899,14 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_fn_code_tl} +% For passing the pre-formed name of the auxiliary that contains the +% actual code. +% \begin{macrocode} +\tl_new:N \l_@@_fn_code_tl +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_function_tl} % Holds the control sequence name of the function currently being % defined: used to avoid passing this as an argument and to avoid repeated @@ -854,6 +916,17 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_last_delimiters_tl} +% Holds the delimiters (first tokens) of all optional arguments since +% the previous mandatory argument, to warn about cases where it would +% be impossible to omit optional arguments completely because the +% following mandatory argument has the same delimiter as one of the +% optional arguments. +% \begin{macrocode} +\tl_new:N \l_@@_last_delimiters_tl +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_long_bool} % Used to indicate that an argument is long: this is used on a per-argument % basis for non-expandable functions, or for the entire set of arguments @@ -881,38 +954,48 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_processor_bool} -% Indicates that the current argument will be followed by one or more -% processors. +% \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 |+| +% (namely is long). % \begin{macrocode} -\bool_new:N \l_@@_processor_bool +\bool_new:N \l_@@_prefixed_bool % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_processor_int} -% In the grabber routine, each processor is saved with a number -% recording the order it was found in. The total is then used to work -% back through the grabbers so they apply to the argument right to left. +% \begin{variable}{\l_@@_process_all_tl, \l_@@_process_one_tl, \l_@@_process_some_bool} +% When preparing the signature, the processors that will be applied to +% a given argument are collected in \cs{l_@@_process_one_tl}, while +% \cs{l_@@_process_all_tl} contains processors for all arguments. The +% boolean indicates whether there are any processors (to bypass the +% whole endeavour otherwise). % \begin{macrocode} -\int_new:N \l_@@_processor_int +\tl_new:N \l_@@_process_all_tl +\tl_new:N \l_@@_process_one_tl +\bool_new:N \l_@@_process_some_bool % \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. +% When arguments are grabbed (at point of use of the command/environment), +% it also stores the code for grabbing the remaining arguments. % \begin{macrocode} \tl_new:N \l_@@_signature_tl % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_tmp_prop, \l_@@_tmpa_tl, \l_@@_tmpb_tl} +% \begin{macro}{\@@_tmp:w} % Scratch space. % \begin{macrocode} \prop_new:N \l_@@_tmp_prop \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl +\cs_new_eq:NN \@@_tmp:w ? % \end{macrocode} +% \end{macro} % \end{variable} % % \subsection{Declaring commands and environments} @@ -949,26 +1032,20 @@ \__msg_kernel_info:nnxx { xparse } { define-command } { \token_to_str:N #1 } { \tl_to_str:n {#2} } } - \prop_put:Nnn \l_@@_command_arg_specs_prop {#1} {#2} \bool_set_false:N \l_@@_environment_bool \@@_declare_cmd_internal:Nnn #1 {#2} } % \end{macrocode} % The real business of defining a document command starts with setting up -% the appropriate name, then counting up the number of mandatory arguments. +% the appropriate name, then normalizing the argument specification to get rid of +% shorthands (this step also counts the number of mandatory arguments). % \begin{macrocode} \cs_new_protected:Npn \@@_declare_cmd_internal:Nnn #1#2#3 { \tl_set:Nx \l_@@_function_tl { \cs_to_str:N #1 } - \@@_count_mandatory:n {#2} - \@@_prepare_signature:n {#2} - \int_compare:nNnTF \l_@@_current_arg_int = \l_@@_m_args_int - { - \bool_if:NTF \l_@@_environment_bool - { \@@_declare_cmd_mixed:Nn #1 {#3} } - { \@@_declare_cmd_all_m:Nn #1 {#3} } - } - { \@@_declare_cmd_mixed:Nn #1 {#3} } + \@@_normalize_arg_spec:n {#2} + \exp_args:No \@@_prepare_signature:n \l_@@_arg_spec_tl + \@@_declare_cmd_code:Nnn #1 {#2} {#3} \@@_break_point:n {#2} } \cs_generate_variant:Nn \@@_declare_cmd_internal:Nnn { cnx } @@ -984,69 +1061,68 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_declare_cmd_all_m:Nn, \@@_declare_cmd_mixed:Nn} +% \begin{macro}{\@@_declare_cmd_code:Nnn} % \begin{macro}[aux] -% {\@@_declare_cmd_mixed_aux:Nn, \@@_declare_cmd_mixed_expandable:Nn} -% When all of the arguments to grab are simple \texttt{m}-type, a short -% cut can be taken to provide only a single function. In the case of -% expandable commands, this can also happen for \texttt{+m} (as all arguments -% in this case must be long). +% {\@@_declare_cmd_code_aux:Nnn, \@@_declare_cmd_code_expandable:Nnn} +% The appropriate auxiliary is called. % \begin{macrocode} -\cs_new_protected:Npn \@@_declare_cmd_all_m:Nn #1#2 - { - \cs_generate_from_arg_count:Ncnn #1 - { - cs_set - \bool_if:NF \l_@@_expandable_bool { _protected } - \bool_if:NF \l_@@_all_long_bool { _nopar } - :Npn - } - \l_@@_current_arg_int {#2} - } -% \end{macrocode} -% In the case of mixed arguments, any remaining \texttt{m}-type ones are -% first added to the signature, then the appropriate auxiliary is called. -% \begin{macrocode} -\cs_new_protected:Npn \@@_declare_cmd_mixed:Nn +\cs_new_protected:Npn \@@_declare_cmd_code:Nnn { \bool_if:NTF \l_@@_expandable_bool - { \@@_declare_cmd_mixed_expandable:Nn } - { \@@_declare_cmd_mixed_aux:Nn } + { \@@_declare_cmd_code_expandable:Nnn } + { \@@_declare_cmd_code_aux:Nnn } } % \end{macrocode} -% Creating standard functions with mixed arg.~specs sets up the main function -% to zero the number of processors, set the name of the function (for the -% grabber) and clears the list of grabbed arguments. +% Standard functions call +% \cs{@@_start:nNNnnn}, which receives an auxiliary used for +% grabbing arguments, an auxiliary containing the code, and then the +% signature, default arguments, and processors. % \begin{macrocode} -\cs_new_protected:Npn \@@_declare_cmd_mixed_aux:Nn #1#2 +\cs_new_protected:Npn \@@_declare_cmd_code_aux:Nnn #1#2#3 { - \@@_flush_m_args: \cs_generate_from_arg_count:cNnn { \l_@@_function_tl \c_space_tl code } - \cs_set_protected:Npn \l_@@_current_arg_int {#2} + \cs_set_protected:Npn \l_@@_current_arg_int {#3} \cs_set_protected_nopar:Npx #1 { - \int_zero:N \l_@@_processor_int - \tl_set:Nn \exp_not:N \l_@@_args_tl - { \exp_not:c { \l_@@_function_tl \c_space_tl code } } - \tl_set:Nn \exp_not:N \l_@@_fn_tl - { \exp_not:c { \l_@@_function_tl \c_space_tl } } - \exp_not:o \l_@@_signature_tl - \exp_not:N \l_@@_args_tl + \@@_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 + { \exp_not:o \l_@@_defaults_tl } + } + { + \bool_if:NT \l_@@_process_some_bool + { \exp_not:o \l_@@_process_all_tl } + } } } -\cs_new_protected:Npn \@@_declare_cmd_mixed_expandable:Nn #1#2 +\cs_new_protected:Npn \@@_declare_cmd_code_expandable:Nnn #1#2#3 { \cs_generate_from_arg_count:cNnn { \l_@@_function_tl \c_space_tl code } - \cs_set:Npn \l_@@_current_arg_int {#2} + \cs_set:Npn \l_@@_current_arg_int {#3} + \bool_if:NT \l_@@_defaults_bool + { + \use:x + { + \cs_generate_from_arg_count:cNnn + { \l_@@_function_tl \c_space_tl defaults } + \cs_set:Npn \l_@@_current_arg_int + { \exp_not:o \l_@@_defaults_tl } + } + } \cs_set_nopar:Npx #1 { - \exp_not:o \l_@@_signature_tl - \exp_not:N \@@_grab_expandable_end:wN - \exp_not:c { \l_@@_function_tl \c_space_tl code } - \exp_not:N \q_@@ - \exp_not:c { \l_@@_function_tl \c_space_tl } + \exp_not:N \@@_start_expandable:nNNNn + { \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:c { \l_@@_function_tl \c_space_tl defaults } + { \exp_not:o \l_@@_signature_tl } } \bool_if:NTF \l_@@_all_long_bool { \cs_set:cpx } @@ -1079,7 +1155,6 @@ \__msg_kernel_info:nnxx { xparse } { define-environment } {#1} { \tl_to_str:n {#2} } } - \prop_put:Nnn \l_@@_environment_arg_specs_prop {#1} {#2} \bool_set_false:N \l_@@_expandable_bool \bool_set_true:N \l_@@_environment_bool \@@_declare_env_internal:nnnn {#1} {#2} @@ -1100,7 +1175,7 @@ \cs_set_nopar:Npx \exp_not:c { environment~ #1 ~end~aux } { \exp_not:N \exp_not:N \exp_not:c { environment~ #1~end~aux~ } - \exp_not:n { \tl_tail:N \l_@@_args_tl } + \exp_not:n { \exp_not:o \l_@@_args_tl } } \exp_not:n {#3} } @@ -1118,178 +1193,610 @@ % \end{macro} % \end{macro} % -% \subsection{Counting mandatory arguments} +% \subsection{Structure of \pkg{xparse} commands} % -% \begin{macro}{\@@_count_mandatory:n} -% \begin{macro}{\@@_count_mandatory:N} -% \begin{macro}[aux]{\@@_count_mandatory:N} -% Loop through the signature to count up mandatory arguments before the -% main parsing run. First, check if the current token is a short-cut for -% another argument type. If it is, expand it and loop again. If not, then -% look for a \enquote{counting} function to check the argument type. No error -% is raised here if one is not found as one will be raised by later code. +% \begin{macro}{\@@_start: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. % \begin{macrocode} -\cs_new_protected:Npn \@@_count_mandatory:n #1 +\cs_new_protected:Npn \@@_start:nNNnnn #1#2#3#4#5#6 { - \int_zero:N \l_@@_mandatory_args_int - \@@_count_mandatory:N #1 - \q_recursion_tail \q_recursion_tail \q_recursion_tail \q_recursion_stop + \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_@@_defaults_tl {#5} + \tl_set:Nn \l_@@_process_all_tl {#6} + #4 \@@_run_code: } -\cs_new_protected:Npn \@@_count_mandatory:N #1 +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_run_code:} +% After arguments are grabbed, this function is responsible for +% inserting default values, running processors, and finally running +% the code. +% \begin{macrocode} +\cs_new_protected:Npn \@@_run_code: { - \quark_if_recursion_tail_stop:N #1 - \prop_get:NnNTF \c_@@_shorthands_prop {#1} \l_@@_tmpa_tl - { \exp_after:wN \@@_count_mandatory:N \l_@@_tmpa_tl } - { \@@_count_mandatory_aux:N #1 } + \tl_if_empty:NF \l_@@_defaults_tl { \@@_defaults: } + \tl_if_empty:NF \l_@@_process_all_tl { \@@_args_process: } + \exp_after:wN \l_@@_fn_code_tl \l_@@_args_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_defaults:} +% \begin{macro}[aux]{\@@_defaults_def:, \@@_defaults_def:nn, \@@_defaults_def:nnn, \@@_defaults_def_aux:nn} +% \begin{macro}[aux]{\@@_defaults_aux:, \@@_defaults_error:w} +% First construct \cs{@@_tmp:w} (see below) that will receive +% the arguments found so far and determine default values for any +% missing argument. Then call it repeatedly until the set of +% arguments stabilizes. Since that could lead to an infinite loop we +% only call it up to nine times, the maximal number needed for +% stabilization if there is a chain of arguments that depend on each +% other. If that fails to stabilize raise an error. +% \begin{macrocode} +\cs_new_protected:Npn \@@_defaults: + { + \@@_defaults_def: + \tl_set_eq:NN \l_@@_args_i_tl \l_@@_args_tl + \@@_defaults_aux: \@@_defaults_aux: \@@_defaults_aux: + \@@_defaults_aux: \@@_defaults_aux: \@@_defaults_aux: + \@@_defaults_aux: \@@_defaults_aux: \@@_defaults_aux: + \@@_defaults_error:w + \q_recursion_stop + \tl_set_eq:NN \l_@@_args_tl \l_@@_args_i_tl + } +\cs_new_protected:Npn \@@_defaults_aux: + { + \tl_set:Nx \l_@@_args_ii_tl + { \exp_after:wN \@@_tmp:w \l_@@_args_i_tl } + \tl_if_eq:NNT \l_@@_args_ii_tl \l_@@_args_i_tl + { \use_none_delimit_by_q_recursion_stop:w } + \tl_set_eq:NN \l_@@_args_i_tl \l_@@_args_ii_tl + } +\cs_new_protected:Npn \@@_defaults_error:w \q_recursion_stop + { + \__msg_kernel_error:nnx { xparse } { loop-in-defaults } + { \exp_after:wN \token_to_str:N \l_@@_fn_tl } + } +% \end{macrocode} +% To construct \cs{@@_tmp:w}, first go through the arguments +% found and the corresponding defaults, building a token list with +% |{#|\meta{arg number}|}| for arguments found in the input (whose +% default will not be used) and otherwise +% |{|\cs{exp_not:n}\Arg{default}|}| for arguments whose default will +% be used. The case of \texttt{E}-type arguments, detected by +% \cs{tl_if_head_is_group:nTF}, is special because we may need to +% partly use an argument found in the input and partly some default. +% This case is delayed until \cs{@@_tmp:w} is called: then we +% map through the original argument and its corresponding list of +% defaults; for each item (corresponding to one embellishment) if a +% value has already been found use it otherwise use the default. +% \begin{macrocode} +\cs_new_protected:Npn \@@_defaults_def: + { + \tl_clear:N \l_@@_tmpa_tl + \int_zero:N \l_@@_current_arg_int + \@@_tl_mapthread_function:NNN \l_@@_args_tl \l_@@_defaults_tl + \@@_defaults_def:nn + \cs_generate_from_arg_count:NNVo \@@_tmp:w \cs_set:Npn + \l_@@_current_arg_int \l_@@_tmpa_tl + } +\cs_generate_variant:Nn \cs_generate_from_arg_count:NNnn { NNVo } +\cs_new_protected:Npn \@@_defaults_def:nn + { + \int_incr:N \l_@@_current_arg_int + \exp_args:NV \@@_defaults_def:nnn \l_@@_current_arg_int + } +\cs_new_protected:Npn \@@_defaults_def:nnn #1#2#3 + { + \tl_if_head_is_group:nTF {#3} + { + \tl_put_right:Nn \l_@@_tmpa_tl + { + { + \exp_args:Nf \@@_tl_mapthread_function:nnN + { \tl_item:Nn \l_@@_args_tl {#1} } + {#3} + \@@_defaults_def_aux:nn + } + } + } + { + \@@_if_no_value:nTF {#2} + { + \tl_put_right:Nx \l_@@_tmpa_tl + { { \exp_not:N \exp_not:n { \exp_not:o { \use_none:n #3 } } } } + } + { + \tl_put_right:Nn \l_@@_tmpa_tl + { { \exp_not:n { ## #1 } } } + } + } + } +\cs_new:Npn \@@_defaults_def_aux:nn #1#2 + { + \@@_if_no_value:nTF {#1} + { { \exp_not:n {#2} } } + { { \exp_not:n {#1} } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_args_process:} +% \begin{macro}[aux]{\@@_args_process_loop:nn, \@@_args_process_aux:n, \@@_args_process_aux:nn} +% Loop through arguments (stored in \cs{l_@@_args_tl}) and the +% corresponding processors (in \cs{l_@@_process_all_tl}) +% simultaneously, apply all processors for each argument and store the +% result back into \cs{l_@@_args_tl}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_args_process: + { + \tl_clear:N \l_@@_args_ii_tl + \@@_tl_mapthread_function:NNN + \l_@@_args_tl + \l_@@_process_all_tl + \@@_args_process_loop:nn + \tl_set_eq:NN \l_@@_args_tl \l_@@_args_ii_tl + } +\cs_new_protected:Npn \@@_args_process_loop:nn #1#2 + { + \tl_set:Nn \ProcessedArgument {#1} + \@@_if_no_value:nF {#1} + { \tl_map_function:nN {#2} \@@_args_process_aux:n } + \tl_put_right:No \l_@@_args_ii_tl + { \exp_after:wN { \ProcessedArgument } } + } +\cs_new_protected:Npn \@@_args_process_aux:n + { \exp_args:No \@@_args_process_aux:nn { \ProcessedArgument } } +\cs_new_protected:Npn \@@_args_process_aux:nn #1#2 { #2 {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_start_expandable:nNNNn} +% This is called for all expandable commands. |#5| is the signature, +% responsible for grabbing arguments. |#4| is used to determine +% default values. |#3| is the code to run. +% |#2|~is a function (named after the command) that grabs a single +% argument in the input stream. The argument specification |#1| is +% unused but used by diagnostic functions. +% \begin{macrocode} +\cs_new:Npn \@@_start_expandable:nNNNn #1#2#3#4#5 + { #5 \@@_end_expandable:NNw #4 #3 \q_@@ #2 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_end_expandable:NNw} +% \begin{macro}[EXP,aux]{\@@_end_expandable_aux:w} +% \begin{macro}[EXP,aux]{\@@_end_expandable_aux:nNNN} +% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nnnNNn} +% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nnw} +% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nw} +% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults_E:nnw} +% Followed by a function |#1| to determine default values, the code +% |#2|, arguments that have been grabbed, then \cs{q_@@} and a generic +% grabber. The idea to find default values is similar to the +% non-expandable case but we cannot define an auxiliary function, so +% at every step in the loop we need to go through all arguments +% searching for which ones started out as |-NoValue-| and replacing +% these by the newly computed values. In fact we need to keep track +% of three versions of all arguments: the original version, the +% previous version with default values, and the currently built +% version (first argument of \cs{@@_end_expandable_defaults:nnnNNn}). +% \begin{macrocode} +\cs_new:Npn \@@_end_expandable:NNw #1#2 + { \@@_end_expandable_aux:w #1#2 \prg_do_nothing: } +\cs_new:Npn \@@_end_expandable_aux:w #1#2#3 \q_@@ #4 + { \exp_args:No \@@_end_expandable_aux:nNNN {#3} #1 #2 #4 } +\cs_new:Npn \@@_end_expandable_aux:nNNN #1#2#3#4 + { + \cs_if_exist:NF #2 { \exp_after:wN \use_iv:nnnn } + \@@_end_expandable_defaults:nnnNNn {#1} { } {#1} #2#3 + { } { } { } { } { } { } { } { } { } { } + { + \__msg_kernel_expandable_error:nnn + { xparse } { loop-in-defaults } {#4} + \use_iv:nnnn + } + \q_stop + } +\cs_new:Npn \@@_end_expandable_defaults:nnnNNn #1#2#3#4#5#6 + { + #6 + \str_if_eq:nnTF {#1} {#2} + { \use_i_delimit_by_q_stop:nw { #5 #1 } } + { + \exp_args:No \@@_tl_mapthread_function:nnN + { #4 #1 } {#3} + \@@_end_expandable_defaults:nnw + \@@_end_expandable_defaults:nnnNNn { } {#1} {#3} #4 #5 + } + } +\cs_new:Npn \@@_end_expandable_defaults:nnw #1#2 + { + \tl_if_head_is_group:nTF {#1} + { + \@@_end_expandable_defaults_E:nnw { } + #1 \q_nil \q_mark + #2 \q_nil + } + { + \@@_if_no_value:nTF {#2} + { \exp_args:No \@@_end_expandable_defaults:nw { \use_none:n #1 } } + { \@@_end_expandable_defaults:nw {#2} } + } + } +\cs_new:Npn \@@_end_expandable_defaults_E:nnw #1#2#3 \q_mark #4 + { + \quark_if_nil:nTF {#2} + { \@@_end_expandable_defaults:nw {#1} } + { + \@@_if_no_value:nTF {#4} + { \@@_end_expandable_defaults_E:nnw { #1 {#2} } } + { \@@_end_expandable_defaults_E:nnw { #1 {#4} } } + #3 \q_mark + } } -\cs_new_protected:Npn \@@_count_mandatory_aux:N #1 +\cs_new:Npn \@@_end_expandable_defaults:nw + #1#2 \@@_end_expandable_defaults:nnnNNn #3 + { #2 \@@_end_expandable_defaults:nnnNNn { #3 {#1} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Normalizing the argument specifications} +% +% The goal here is to expand aliases and check that the argument +% specification is valid before the main parsing run. If it is not +% valid the entire set up is abandoned to avoid any strange internal +% errors. A function is provided for each argument type that will grab +% any extra arguments and call the loop function. +% +% The first thing that is done in the loop is to check that the various +% argument types have the correct number of data items associated with +% them. The opportunity is also taken to make sure that where a single +% token is required, one has actually been supplied. +% +% The second is that processors and the marker~|+| for long arguments +% must be followed by arguments. +% +% The third is to check for forbidden types for expandable commands, +% namely \texttt{g}, +% \texttt{G}, \texttt{l} (as the next left brace may have been inserted +% by \pkg{xparse} due to a failed search for an optional argument), +% \texttt{u} (any preceding optional argument may wrap part of the +% delimiter up in braces), and \texttt{v}. +% +% The fourth is that an optional argument should not be followed by a +% mandatory argument with the same delimiter, as otherwise the optional +% argument could never be omitted. +% +% The last is to count mandatory arguments. +% +% \begin{macro}{\@@_normalize_arg_spec:n} +% \begin{macro}{\@@_normalize_arg_spec_loop:n} +% Loop through the argument specification, calling an auxiliary +% specific to each argument type. If any argument is unknown stop the +% definition. After the loop, if there are more than +% $9$ arguments, stop. Additionally, expandable commands may not end +% with an optional argument; this case is detected by using the fact +% that \cs{l_@@_last_delimiters_tl} is cleared by every mandatory +% argument and filled by every optional argument. +% \begin{macrocode} +\cs_new_protected:Npn \@@_normalize_arg_spec:n #1 { - \cs_if_exist_use:cF { @@_count_type_ \token_to_str:N #1 :w } - { \@@_count_type_m:w } + \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 + \@@_normalize_arg_spec_loop:n #1 + \q_recursion_tail \q_recursion_tail \q_recursion_tail \q_recursion_stop + \int_compare:nNnT \l_@@_current_arg_int > 9 + { + \__msg_kernel_error:nnxx { xparse } { too-many-arguments } + { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} } + \@@_bad_def:wn + } + \bool_if:NT \l_@@_expandable_bool + { + \tl_if_empty:NF \l_@@_last_delimiters_tl + { + \__msg_kernel_error:nnxx { xparse } { expandable-ending-optional } + { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} } + \@@_bad_def:wn + } + } + } +\cs_new_protected:Npn \@@_normalize_arg_spec_loop:n #1 + { + \quark_if_recursion_tail_stop:n {#1} + \int_incr:N \l_@@_current_arg_int + \cs_if_exist_use:cF { @@_normalize_type_ \tl_to_str:n {#1} :w } + { + \__msg_kernel_error:nnxx { xparse } { unknown-argument-type } + { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} } + \@@_bad_def:wn + } } % \end{macrocode} % \end{macro} % \end{macro} +% +% \begin{macro} +% { +% \@@_normalize_type_d:w, +% \@@_normalize_type_e:w, +% \@@_normalize_type_g:w, +% \@@_normalize_type_o:w, +% \@@_normalize_type_O:w, +% \@@_normalize_type_r:w, +% \@@_normalize_type_s:w, +% } +% These argument types are aliases of more general ones, for example +% with the default argument |-NoValue-|. To easily insert that marker +% expanded in the definitions we call \cs{@@_tmp:w} with the argument +% |-NoValue-|. For argument types that need additional data, check +% that that data is present (not \cs{q_recursion_tail}) before +% proceeding. +% \begin{macrocode} +\cs_set_protected:Npn \@@_tmp:w #1 + { + \cs_new_protected:Npn \@@_normalize_type_d:w ##1##2 + { + \quark_if_recursion_tail_stop_do:nn {##2} { \@@_bad_arg_spec:wn } + \@@_normalize_type_D:w {##1} {##2} {#1} + } + \cs_new_protected:Npn \@@_normalize_type_e:w ##1 + { + \quark_if_recursion_tail_stop_do:nn {##1} { \@@_bad_arg_spec:wn } + \@@_normalize_type_E:w {##1} { } + } + \cs_new_protected:Npn \@@_normalize_type_g:w + { \@@_normalize_type_G:w {#1} } + \cs_new_protected:Npn \@@_normalize_type_o:w + { \@@_normalize_type_D:w [ ] {#1} } + \cs_new_protected:Npn \@@_normalize_type_O:w + { \@@_normalize_type_D:w [ ] } + \cs_new_protected:Npn \@@_normalize_type_r:w ##1##2 + { + \quark_if_recursion_tail_stop_do:nn {##2} { \@@_bad_arg_spec:wn } + \@@_normalize_type_R:w {##1} {##2} {#1} + } + \cs_new_protected:Npn \@@_normalize_type_s:w + { \@@_normalize_type_t:w * } + } +\exp_args:No \@@_tmp:w { \c_@@_no_value_tl } +% \end{macrocode} % \end{macro} % % \begin{macro} % { -% \@@_count_type_>:w, -% \@@_count_type_+:w, -% \@@_count_type_d:w, -% \@@_count_type_D:w, -% \@@_count_type_e:w, -% \@@_count_type_E:w, -% \@@_count_type_g:w, -% \@@_count_type_G:w, -% \@@_count_type_m:w, -% \@@_count_type_r:w, -% \@@_count_type_R:w, -% \@@_count_type_t:w, -% \@@_count_type_u:w +% \@@_normalize_type_>:w, +% \@@_normalize_type_+:w, % } -% For counting the mandatory arguments, a function is provided for each -% argument type that will mop any extra arguments and call the loop function. -% Only the counting functions for mandatory arguments actually do anything: -% the rest are simply there to ensure the loop continues correctly. There are -% no count functions for \texttt{l} or \texttt{v} argument types as they are -% exactly the same as \texttt{m}, and so a little code can be saved. -% -% The second thing that can be done here is to check that the signature is -% actually valid, such that all of the various argument types have the -% correct number of data items associated with them. If this fails to be -% the case, the entire set up is abandoned to avoid any strange internal -% errors. The opportunity is also taken to make sure that where a single -% token is required, one has actually been supplied. -% -% The third is that processors and the marker~|+| for long arguments -% must be followed by arguments. For this, just check that the next -% token is not \cs{q_recursion_tail}, and remember to leave it after -% the looping macro. -% \begin{macrocode} -\cs_new_protected:cpn { @@_count_type_>:w } #1#2 +% Check that these prefixes have arguments, namely that the next token +% is not \cs{q_recursion_tail}, and remember to leave it after the +% looping macro. Processors are forbidden in expandable commands. +% If all is good, store the prefix in the cleaned up +% \cs{l_@@_arg_spec_tl}, and decrement the argument number as prefixes +% do not correspond to arguments. +% \begin{macrocode} +\cs_new_protected:cpn { @@_normalize_type_>:w } #1#2 { \quark_if_recursion_tail_stop_do:nn {#2} { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N #2 + \bool_if:NT \l_@@_expandable_bool + { + \__msg_kernel_error:nnxx { xparse } { processor-in-expandable } + { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} } + \@@_bad_def:wn + } + \tl_put_right:Nn \l_@@_arg_spec_tl { > {#1} } + \int_decr:N \l_@@_current_arg_int + \@@_normalize_arg_spec_loop:n {#2} } -\cs_new_protected:cpn { @@_count_type_+:w } #1 +\cs_new_protected:cpn { @@_normalize_type_+:w } #1 { \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N #1 - } -\cs_new_protected:Npn \@@_count_type_d:w #1#2 - { - \@@_single_token_check:n {#1} - \@@_single_token_check:n {#2} - \quark_if_recursion_tail_stop_do:Nn #2 { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N + \tl_put_right:Nn \l_@@_arg_spec_tl { + } + \int_decr:N \l_@@_current_arg_int + \@@_normalize_arg_spec_loop:n {#1} } -\cs_new_protected:Npn \@@_count_type_D:w #1#2#3 +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_normalize_type_D:w, +% \@@_normalize_type_E:w, +% \@@_normalize_type_G:w, +% \@@_normalize_type_t:w, +% } +% Optional argument types. Check that all required data is present +% (and consists of single tokens if applicable) and check for +% forbidden types for expandable commands. For \texttt{E}-type +% require that there is at least one embellishment, that each one is a +% single token, and that there aren't more optional arguments than +% embellishments. Then store the data in \cs{l_@@_arg_spec_tl}, and +% for later checks store in \cs{l_@@_last_delimiters_tl} the tokens +% whose presence determines whether there is an optional argument (for +% braces store |{}|, seen later as an empty delimiter). +% \begin{macrocode} +\cs_new_protected:Npn \@@_normalize_type_D:w #1#2#3 { \@@_single_token_check:n {#1} \@@_single_token_check:n {#2} \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N - } -\cs_new_protected:Npn \@@_count_type_e:w #1 - { - \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N + \tl_put_right:Nn \l_@@_arg_spec_tl { D #1 #2 {#3} } + \tl_put_right:Nn \l_@@_last_delimiters_tl {#1} + \@@_normalize_arg_spec_loop:n } -\cs_new_protected:Npn \@@_count_type_E:w #1#2 +\cs_new_protected:Npn \@@_normalize_type_E:w #1#2 { \quark_if_recursion_tail_stop_do:nn {#2} { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N + \tl_if_blank:nT {#1} { \@@_bad_arg_spec:wn } + \tl_map_function:nN {#1} \@@_single_token_check:n + \int_compare:nNnT { \tl_count:n {#2} } > { \tl_count:n {#1} } + { \@@_bad_arg_spec:wn } + \tl_put_right:Nn \l_@@_arg_spec_tl { E {#1} {#2} } + \tl_put_right:Nn \l_@@_last_delimiters_tl {#1} + \@@_normalize_arg_spec_loop:n } -\cs_new_protected:Npn \@@_count_type_g:w - { \@@_count_mandatory:N } -\cs_new_protected:Npn \@@_count_type_G:w #1 +\cs_new_protected:Npn \@@_normalize_type_G:w #1 { \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N + \@@_normalize_error_if_expandable:N G + \tl_put_right:Nn \l_@@_arg_spec_tl { G {#1} } + \tl_put_right:Nn \l_@@_last_delimiters_tl { { } } + \@@_normalize_arg_spec_loop:n } -\cs_new_protected:Npn \@@_count_type_m:w +\cs_new_protected:Npn \@@_normalize_type_t:w #1 { + \@@_single_token_check:n {#1} + \quark_if_recursion_tail_stop_do:Nn #1 { \@@_bad_arg_spec:wn } + \tl_put_right:Nn \l_@@_arg_spec_tl { t #1 } + \tl_put_right:Nn \l_@@_last_delimiters_tl {#1} + \@@_normalize_arg_spec_loop:n + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_normalize_type_l:w, +% \@@_normalize_type_m:w, +% \@@_normalize_type_R:w, +% \@@_normalize_type_u:w +% \@@_normalize_type_v:w +% } +% Mandatory arguments. First check the required data is present, +% consists of single tokens where applicable, and that the argument +% type is allowed for expandable commands if applicable. For the +% \texttt{m} and \texttt{R} argument types check that they do not +% follow some optional argument with that delimiter as otherwise the +% optional argument could not be omitted. Then save data in +% \cs{l_@@_arg_spec_tl}, count the mandatory argument, and empty the +% list of last delimiters. +% \begin{macrocode} +\cs_new_protected:Npn \@@_normalize_type_l:w + { + \@@_normalize_error_if_expandable:N l + \tl_put_right:Nn \l_@@_arg_spec_tl { l } \int_incr:N \l_@@_mandatory_args_int - \@@_count_mandatory:N + \tl_clear:N \l_@@_last_delimiters_tl + \@@_normalize_arg_spec_loop:n } -\cs_new_protected:Npn \@@_count_type_r:w #1#2 +\cs_new_protected:Npn \@@_normalize_type_m:w { - \@@_single_token_check:n {#1} - \@@_single_token_check:n {#2} - \quark_if_recursion_tail_stop_do:Nn #2 { \@@_bad_arg_spec:wn } + \@@_delimiter_check:nnn { } { m } { \iow_char:N \{ } + \tl_put_right:Nn \l_@@_arg_spec_tl { m } \int_incr:N \l_@@_mandatory_args_int - \@@_count_mandatory:N + \tl_clear:N \l_@@_last_delimiters_tl + \@@_normalize_arg_spec_loop:n } -\cs_new_protected:Npn \@@_count_type_R:w #1#2#3 +\cs_new_protected:Npn \@@_normalize_type_R:w #1#2#3 { \@@_single_token_check:n {#1} \@@_single_token_check:n {#2} \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn } + \@@_delimiter_check:nnn {#1} { R/r } { \tl_to_str:n {#1} } + \tl_put_right:Nn \l_@@_arg_spec_tl { R #1 #2 {#3} } \int_incr:N \l_@@_mandatory_args_int - \@@_count_mandatory:N + \tl_clear:N \l_@@_last_delimiters_tl + \@@_normalize_arg_spec_loop:n } -\cs_new_protected:Npn \@@_count_type_t:w #1 +\cs_new_protected:Npn \@@_normalize_type_u:w #1 { - \@@_single_token_check:n {#1} - \quark_if_recursion_tail_stop_do:Nn #1 { \@@_bad_arg_spec:wn } - \@@_count_mandatory:N + \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn } + \@@_normalize_error_if_expandable:N u + \tl_put_right:Nn \l_@@_arg_spec_tl { u {#1} } + \int_incr:N \l_@@_mandatory_args_int + \tl_clear:N \l_@@_last_delimiters_tl + \@@_normalize_arg_spec_loop:n } -\cs_new_protected:Npn \@@_count_type_u:w #1 +\cs_new_protected:Npn \@@_normalize_type_v:w { - \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn } + \@@_normalize_error_if_expandable:N v + \tl_put_right:Nn \l_@@_arg_spec_tl { v } \int_incr:N \l_@@_mandatory_args_int - \@@_count_mandatory:N + \tl_clear:N \l_@@_last_delimiters_tl + \@@_normalize_arg_spec_loop:n } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_single_token_check:n} -% \begin{macro}[aux]{\@@_single_token_check_aux:nwn} % A spin-out function to check that what should be single tokens really % are single tokens. % \begin{macrocode} \cs_new_protected:Npn \@@_single_token_check:n #1 { \exp_args:Nx \tl_if_single_token:nF { \tl_trim_spaces:n {#1} } - { \@@_single_token_check_aux:nwn {#1} } + { + \__msg_kernel_error:nnxx { xparse } { not-single-token } + { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} } + \@@_bad_def:wn + } } -\cs_new_protected:Npn \@@_single_token_check_aux:nwn - #1#2 \@@_break_point:n #3 +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_normalize_error_if_expandable:N} +% Called for arguments that are forbidden for expandable commands. +% \begin{macrocode} +\cs_new_protected:Npn \@@_normalize_error_if_expandable:N #1 { - \__msg_kernel_error:nnx { xparse } { not-single-token } - { \tl_to_str:n {#1} } { \tl_to_str:n {#3} } + \bool_if:NT \l_@@_expandable_bool + { + \__msg_kernel_error:nnxx + { xparse } { invalid-expandable-argument-type } + { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} } + \@@_bad_def:wn + } } % \end{macrocode} % \end{macro} +% +% \begin{macro}{\@@_delimiter_check:nnn} +% Called for \texttt{m} and \texttt{R} arguments. Checks that the +% leading token does not coincide with the token denoting the presence +% of a previous optional argument. Instead of dealing with braces for +% the \texttt{m}-type we use an empty delimiter to denote that case. +% \begin{macrocode} +\cs_new_protected:Npn \@@_delimiter_check:nnn #1#2#3 + { + \tl_map_inline:Nn \l_@@_last_delimiters_tl + { + \tl_if_eq:nnT {##1} {#1} + { + \__msg_kernel_warning:nnxx { xparse } { optional-mandatory } + {#2} {#3} + } + } + } +% \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_bad_arg_spec:wn} -% If the signature is wrong, this provides an escape from the entire +% \begin{macro}{\@@_bad_arg_spec:wn, \@@_bad_def:wn} +% If the argument specification is wrong, this provides an escape from the entire % definition process. % \begin{macrocode} \cs_new_protected:Npn \@@_bad_arg_spec:wn #1 \@@_break_point:n #2 - { \__msg_kernel_error:nnx { xparse } { bad-arg-spec } { \tl_to_str:n {#2} } } + { + \__msg_kernel_error:nnxx { xparse } { bad-arg-spec } + { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#2} } + } +\cs_new_protected:Npn \@@_bad_def:wn #1 \@@_break_point:n #2 { } % \end{macrocode} % \end{macro} % @@ -1298,69 +1805,58 @@ % \begin{macro}{\@@_prepare_signature:n} % \begin{macro}{\@@_prepare_signature:N} % \begin{macro}{\@@_prepare_signature_bypass:N} -% \begin{macro}[aux]{\@@_prepare_signature_add:N} % Actually creating the signature uses the same loop approach as counting % up mandatory arguments. There are first a number of variables which need -% to be set to track what is going on. +% to be set to track what is going on. Many of these variables are unused +% when defining expandable commands. % \begin{macrocode} \cs_new_protected:Npn \@@_prepare_signature:n #1 { \bool_set_false:N \l_@@_all_long_bool + \bool_set_false:N \l_@@_all_long_set_bool \int_zero:N \l_@@_current_arg_int \bool_set_false:N \l_@@_long_bool \int_zero:N \l_@@_m_args_int - \bool_set_false:N \l_@@_processor_bool + \bool_set_false:N \l_@@_defaults_bool + \tl_clear:N \l_@@_defaults_tl + \tl_clear:N \l_@@_process_all_tl + \tl_clear:N \l_@@_process_one_tl + \bool_set_false:N \l_@@_process_some_bool \tl_clear:N \l_@@_signature_tl \@@_prepare_signature:N #1 \q_recursion_tail \q_recursion_stop + \bool_if:NF \l_@@_expandable_bool { \@@_flush_m_args: } } % \end{macrocode} % The main looping function does not take an argument, but carries out the % reset on the processor boolean. This is split off from the rest of the % process so that when actually setting up processors the flag-reset can % be bypassed. +% +% 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. % \begin{macrocode} \cs_new_protected:Npn \@@_prepare_signature:N { - \bool_set_false:N \l_@@_processor_bool + \bool_set_false:N \l_@@_prefixed_bool \@@_prepare_signature_bypass:N } \cs_new_protected:Npn \@@_prepare_signature_bypass:N #1 { \quark_if_recursion_tail_stop:N #1 - \prop_get:NnNTF \c_@@_shorthands_prop {#1} \l_@@_tmpa_tl - { \exp_after:wN \@@_prepare_signature:N \l_@@_tmpa_tl } - { - \int_incr:N \l_@@_current_arg_int - \@@_prepare_signature_add:N #1 - } - } -% \end{macrocode} -% 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. -% \begin{macrocode} -\cs_new_protected:Npn \@@_prepare_signature_add:N #1 - { - \cs_if_exist_use:cF + \int_incr:N \l_@@_current_arg_int + \use:c { @@_add \bool_if:NT \l_@@_expandable_bool { _expandable } _type_ \token_to_str:N #1 :w } - { - \__msg_kernel_error:nnx { xparse } { unknown-argument-type } - { \token_to_str:N #1 } - \bool_if:NTF \l_@@_expandable_bool - { \@@_add_expandable_type_m:w } - { \@@_add_type_m:w } - } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % \subsection{Setting up a standard signature} % @@ -1369,7 +1865,9 @@ % \texttt{m} arguments. These are collected and added to the signature % all at once by \cs{@@_flush_m_args:}, called for every other argument % type. All of the functions then call the loop function -% \cs{@@_prepare_signature:N}. +% \cs{@@_prepare_signature:N}. Default values of arguments are +% collected by \cs{@@_add_default:n} rather than being stored with the +% argument. % % \begin{macro}{\@@_add_type_+:w} % Making the next argument long means setting the flag and knocking one back @@ -1380,74 +1878,59 @@ { \@@_flush_m_args: \bool_set_true:N \l_@@_long_bool + \bool_set_true:N \l_@@_prefixed_bool \int_decr:N \l_@@_current_arg_int - \@@_prepare_signature:N + \@@_prepare_signature_bypass:N } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_type_>:w} -% When a processor is found, the function \cs{@@_process_arg:n} is added -% to the signature along with the processor code itself. When the signature -% is used, the code will be added to an execution list by -% \cs{@@_process_arg:n}. Here, the loop calls -% \cs{@@_prepare_signature_bypass:N} rather than +% When a processor is found, the processor code is stored. It will be +% used by \cs{@@_args_process:} once arguments are all found. Here, +% the loop calls \cs{@@_prepare_signature_bypass:N} rather than % \cs{@@_prepare_signature:N} so that the flag is not reset. % \begin{macrocode} \cs_new_protected:cpn { @@_add_type_>:w } #1 { \@@_flush_m_args: - \bool_set_true:N \l_@@_processor_bool + \bool_set_true:N \l_@@_prefixed_bool + \bool_set_true:N \l_@@_process_some_bool \int_decr:N \l_@@_current_arg_int - \tl_put_right:Nn \l_@@_signature_tl { \@@_process_arg:n {#1} } + \tl_put_right:Nn \l_@@_process_one_tl { {#1} } \@@_prepare_signature_bypass:N } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_type_d:w, \@@_add_type_D:w} -% To save on repeated code, \texttt{d} is actually turned into the same -% grabber as is used by \texttt{D}, by putting the |-NoValue-| default in -% the correct place. +% \begin{macro}{\@@_add_type_D:w} % \begin{macrocode} -\cs_new_protected:Npn \@@_add_type_d:w #1#2 - { \exp_args:NNNo \@@_add_type_D:w #1 #2 \c_@@_no_value_tl } \cs_new_protected:Npn \@@_add_type_D:w #1#2#3 { \@@_flush_m_args: + \@@_add_default:n {#3} \@@_add_grabber_optional:N D - \tl_put_right:Nn \l_@@_signature_tl { #1 #2 {#3} } + \tl_put_right:Nn \l_@@_signature_tl { #1 #2 } \@@_prepare_signature:N } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_type_e:w, \@@_add_type_E:w} -% Setting up for the \texttt{e}-type argument is somewhat specialised as -% the |-NoValue-| tokens are inserted by the grabber rather than here. As -% such, all that is needed is to pass data straight through. +% \begin{macro}{\@@_add_type_E:w} +% The \texttt{E}-type argument needs a special handling of default +% values. % \begin{macrocode} -\cs_new_protected:Npn \@@_add_type_e:w #1 - { \@@_add_type_E:w {#1} { } } \cs_new_protected:Npn \@@_add_type_E:w #1#2 { \@@_flush_m_args: + \@@_add_default_E:nn {#1} {#2} \@@_add_grabber_optional:N E - \tl_put_right:Nn \l_@@_signature_tl { {#1} {#2} } + \tl_put_right:Nn \l_@@_signature_tl { {#1} } \@@_prepare_signature:N } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_type_g:w} -% The \texttt{g} type is simply an alias for \texttt{G} with the correct -% default built-in. -% \begin{macrocode} -\cs_new_protected:Npn \@@_add_type_g:w - { \exp_args:No \@@_add_type_G:w \c_@@_no_value_tl } -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\@@_add_type_G:w} % For the \texttt{G} type, the grabber and the default are added to the % signature. @@ -1455,8 +1938,8 @@ \cs_new_protected:Npn \@@_add_type_G:w #1 { \@@_flush_m_args: + \@@_add_default:n {#1} \@@_add_grabber_optional:N G - \tl_put_right:Nn \l_@@_signature_tl { {#1} } \@@_prepare_signature:N } % \end{macrocode} @@ -1469,6 +1952,7 @@ \cs_new_protected:Npn \@@_add_type_l:w { \@@_flush_m_args: + \@@_add_default: \@@_add_grabber_mandatory:N l \@@_prepare_signature:N } @@ -1485,28 +1969,24 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_add_type_m:w { - \bool_if:nTF { \l_@@_long_bool || \l_@@_processor_bool } - { - \@@_flush_m_args: - \@@_add_grabber_mandatory:N m - } + \@@_add_default: + \bool_if:NTF \l_@@_prefixed_bool + { \@@_add_grabber_mandatory:N m } { \int_incr:N \l_@@_m_args_int } \@@_prepare_signature:N } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_type_r:w, \@@_add_type_R:w} -% The \texttt{r}- and \texttt{R}-type arguments are very similar to the -% \texttt{d}- and \texttt{D}-types. +% \begin{macro}{\@@_add_type_R:w} +% The \texttt{R}-type argument is very similar to the \texttt{D}-type. % \begin{macrocode} -\cs_new_protected:Npn \@@_add_type_r:w #1#2 - { \exp_args:NNNo \@@_add_type_R:w #1 #2 \c_@@_no_value_tl } \cs_new_protected:Npn \@@_add_type_R:w #1#2#3 { \@@_flush_m_args: + \@@_add_default:n {#3} \@@_add_grabber_mandatory:N R - \tl_put_right:Nn \l_@@_signature_tl { #1 #2 {#3} } + \tl_put_right:Nn \l_@@_signature_tl { #1 #2 } \@@_prepare_signature:N } % \end{macrocode} @@ -1519,6 +1999,7 @@ \cs_new_protected:Npn \@@_add_type_t:w #1 { \@@_flush_m_args: + \@@_add_default: \@@_add_grabber_optional:N t \tl_put_right:Nn \l_@@_signature_tl {#1} \@@_prepare_signature:N @@ -1533,6 +2014,7 @@ \cs_new_protected:Npn \@@_add_type_u:w #1 { \@@_flush_m_args: + \@@_add_default: \@@_add_grabber_mandatory:N u \tl_put_right:Nn \l_@@_signature_tl { {#1} } \@@_prepare_signature:N @@ -1541,11 +2023,14 @@ % \end{macro} % % \begin{macro}{\@@_add_type_v:w} -% At this stage, the \texttt{v} argument is identical to \texttt{l}. +% At this stage, the \texttt{v} argument is identical to \texttt{l} +% except that since the grabber may fail to read a verbatim argument +% we need a default value. % \begin{macrocode} \cs_new_protected:Npn \@@_add_type_v:w { \@@_flush_m_args: + \exp_args:No \@@_add_default:n \c_@@_no_value_tl \@@_add_grabber_mandatory:N v \@@_prepare_signature:N } @@ -1567,6 +2052,8 @@ \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 } { { } } } } \int_zero:N \l_@@_m_args_int } @@ -1590,6 +2077,9 @@ { @@_grab_ #1 \bool_if:NT \l_@@_long_bool { _long } :w } } \bool_set_false:N \l_@@_long_bool + \tl_put_right:Nx \l_@@_process_all_tl + { { \exp_not:o \l_@@_process_one_tl } } + \tl_clear:N \l_@@_process_one_tl \int_decr:N \l_@@_mandatory_args_int } \cs_new_protected:Npn \@@_add_grabber_optional:N #1 @@ -1606,109 +2096,124 @@ } } \bool_set_false:N \l_@@_long_bool + \tl_put_right:Nx \l_@@_process_all_tl + { { \exp_not:o \l_@@_process_one_tl } } + \tl_clear:N \l_@@_process_one_tl } % \end{macrocode} % \end{macro} % \end{macro} % -% \subsection{Setting up expandable types} -% -% The approach here is not dissimilar to that for standard types, although -% types which are not supported in expandable functions give an error. There is -% also a need to define the per-function auxiliaries: this is done here, while -% the general grabbers are dealt with later. -% -% \begin{macro}{\@@_add_expandable_type_+:w} -% Check that a plus is given only if it occurs for every argument. +% \begin{macro}{\@@_add_default:n, \@@_add_default:, \@@_add_default_E:nn} +% \begin{macro}[aux]{\@@_add_default_E_aux:n} +% Store the default value of an argument, or rather code that gives +% that default value (it may involve other arguments). Defaults are +% always stored with a leading |.| except for \texttt{E}-type +% arguments, to distinguish them. For \texttt{E}-type arguments, pad +% the defaults |#2| with some |{-NoValue-}| until there are the same +% numbers as embellishments~|#1|. Then for technical reasons make +% sure the first default is wrapped in braces. These functions are +% also used when defining expandable commands. % \begin{macrocode} -\cs_new_protected:cpn { @@_add_expandable_type_+:w } +\cs_new_protected:Npn \@@_add_default:n #1 { - \bool_set_true:N \l_@@_long_bool - \int_compare:nNnTF \l_@@_current_arg_int = \c_one - { \bool_set_true:N \l_@@_all_long_bool } + \bool_set_true:N \l_@@_defaults_bool + \tl_put_right:Nn \l_@@_defaults_tl { { . #1} } + } +\cs_new_protected:Npn \@@_add_default: + { \tl_put_right:Nn \l_@@_defaults_tl { . } } +\cs_new_protected:Npn \@@_add_default_E:nn #1#2 + { + \bool_set_true:N \l_@@_defaults_bool + \tl_set:Nx \l_@@_tmpa_tl { - \bool_if:NF \l_@@_all_long_bool - { \__msg_kernel_error:nn { xparse } { inconsistent-long } } + \exp_not:n {#2} + \prg_replicate:nn + { \tl_count:n {#1} - \tl_count:n {#2} } + { { \c_@@_no_value_tl } } + } + \tl_put_right:Nx \l_@@_defaults_tl + { + { + \exp_not:f + { \exp_after:wN \@@_add_default_E_aux:n \l_@@_tmpa_tl } + } } - \int_decr:N \l_@@_current_arg_int - \@@_prepare_signature:N } +\cs_new:Npn \@@_add_default_E_aux:n #1 { {#1} } % \end{macrocode} % \end{macro} +% \end{macro} +% +% \subsection{Setting up expandable types} +% +% The approach here is not dissimilar to that for standard types, but fewer types +% are supported. There is +% also a need to define the per-function auxiliaries: this is done here, while +% the general grabbers are dealt with later. % -% \begin{macro}{\@@_add_expandable_type_>:w} -% No processors in expandable arguments, so this issues an error. +% \begin{macro}{\@@_add_expandable_type_+:w} +% ^^A todo % \begin{macrocode} -\cs_new_protected:cpn { @@_add_expandable_type_>:w } #1 +\cs_new_protected:cpn { @@_add_expandable_type_+:w } { - \__msg_kernel_error:nnx { xparse } { processor-in-expandable } - { \token_to_str:c { \l_@@_function_tl } } + \bool_set_true:N \l_@@_long_bool \int_decr:N \l_@@_current_arg_int \@@_prepare_signature:N } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_expandable_type_d:w} % \begin{macro}{\@@_add_expandable_type_D:w} -% \begin{macro}{\@@_add_expandable_type_D_aux:NNn} -% \begin{macro}{\@@_add_expandable_type_D_aux:Nn} -% The set up for \texttt{d}- and \texttt{D}-type arguments is the same, -% and involves constructing a rather complex auxiliary which is used +% \begin{macro}{\@@_add_expandable_type_D_aux:NNNn} +% \begin{macro}{\@@_add_expandable_type_D_aux:NNN} +% \begin{macro}{\@@_add_expandable_type_D_aux:NN} +% The set up for \texttt{D}-type arguments involves constructing a +% rather complex auxiliary which is used % repeatedly when grabbing. There is an auxiliary here so that the -% \texttt{R}-type can share code readily. +% \texttt{R}-type can share code readily: |#1| is |D| or~|R|. +% The |_aux:NN| auxiliary is needed if the two delimiting tokens are +% identical: in contrast to the non-expandable route, the grabber here +% has to act differently for this case. % \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_type_d:w #1#2 - { - \exp_args:NNNo - \@@_add_expandable_type_D:w #1 #2 \c_@@_no_value_tl - } -\cs_new_protected:Npn \@@_add_expandable_type_D:w #1#2 - { - \tl_if_eq:nnTF {#1} {#2} - { - \@@_add_expandable_grabber_optional:n { D_alt } - \@@_add_expandable_type_D_aux:Nn #1 - } - { - \@@_add_expandable_grabber_optional:n { D } - \@@_add_expandable_type_D_aux:NNn #1#2 - } +\cs_new_protected:Npn \@@_add_expandable_type_D:w + { \@@_add_expandable_type_D_aux:NNNn D } +\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNNn #1#2#3#4 + { + \@@_add_default:n {#4} + \tl_if_eq:nnTF {#2} {#3} + { \@@_add_expandable_type_D_aux:NN #1 #2 } + { \@@_add_expandable_type_D_aux:NNN #1 #2 #3 } + \bool_set_false:N \l_@@_long_bool + \@@_prepare_signature:N } -\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNn #1#2#3 +\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNN #1#2#3 { + \@@_add_expandable_grabber:n {#1} \bool_if:NTF \l_@@_all_long_bool { \cs_set:cpx } { \cs_set_nopar:cpx } - { \l_@@_expandable_aux_name_tl } ##1 ##2 #1 ##3 \q_@@ ##4 #2 + { \l_@@_expandable_aux_name_tl } ##1 ##2 #2 ##3 \q_@@ ##4 #3 { ##1 {##2} {##3} {##4} } \tl_put_right:Nx \l_@@_signature_tl { \exp_not:c { \l_@@_expandable_aux_name_tl } - \exp_not:n { #1 #2 {#3} } + \exp_not:n { #2 #3 } } - \bool_set_false:N \l_@@_long_bool - \@@_prepare_signature:N - } -% \end{macrocode} -% This route is needed if the two delimiting tokens are identical: in -% contrast to the non-expandable route, the grabber here has to act -% differently for this case. -% \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_type_D_aux:Nn #1#2 + } +\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NN #1#2 { + \@@_add_expandable_grabber:n { #1_alt } \bool_if:NTF \l_@@_all_long_bool { \cs_set:cpx } { \cs_set_nopar:cpx } - { \l_@@_expandable_aux_name_tl } ##1 #1 ##2 #1 + { \l_@@_expandable_aux_name_tl } ##1 #2 ##2 #2 { ##1 {##2} } \tl_put_right:Nx \l_@@_signature_tl { \exp_not:c { \l_@@_expandable_aux_name_tl } - \exp_not:n { #1 {#2} } + \exp_not:n {#2} } - \bool_set_false:N \l_@@_long_bool - \@@_prepare_signature:N } % \end{macrocode} % \end{macro} @@ -1716,93 +2221,76 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\@@_add_expandable_type_g:w} -% \begin{macro}{\@@_add_expandable_type_G:w} -% These are not allowed at all, so there is a complaint and a fall-back. +% \begin{macro}{\@@_add_expandable_type_E:w} +% \begin{macro}[aux]{\@@_add_expandable_type_E_aux:n} +% For each embellishment, use \cs{@@_get_grabber:NN} to obtain an +% auxiliary delimited by that token and store a pair constituted of +% the auxiliary and the token in \cs{l_@@_tmpb_tl}, before appending +% the whole set of these pairs to the signature, and an equal number +% of |-NoValue-| markers (regardless of the default values of +% arguments). % \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_type_g:w +\cs_new_protected:Npn \@@_add_expandable_type_E:w #1#2 { - \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type } - { g } - \@@_add_expandable_type_m:w + \@@_add_default_E:nn {#1} {#2} + \@@_add_expandable_grabber:n { E } + \tl_clear:N \l_@@_tmpb_tl + \tl_map_function:nN {#1} \@@_add_expandable_type_E_aux:n + \tl_put_right:Nx \l_@@_signature_tl + { + { \exp_not:o \l_@@_tmpb_tl } + { + \prg_replicate:nn { \tl_count:n {#1} } + { { \c_@@_no_value_tl } } + } + } + \bool_set_false:N \l_@@_long_bool + \@@_prepare_signature:N } -\cs_new_protected:Npn \@@_add_expandable_type_G:w #1 +\cs_new_protected:Npn \@@_add_expandable_type_E_aux:n #1 { - \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type } - { G } - \@@_add_expandable_type_m:w + \@@_get_grabber:NN #1 \l_@@_tmpa_tl + \tl_put_right:Nx \l_@@_tmpb_tl + { \exp_not:o \l_@@_tmpa_tl \exp_not:N #1 } } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\@@_add_expandable_type_l:w} -% Invalid in expandable contexts (as the next left brace may have been -% inserted by \pkg{xparse} due to a failed search for an optional argument). -% \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_type_l:w - { - \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type } - { l } - \@@_add_expandable_type_m:w - } -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\@@_add_expandable_type_m:w} % Unlike the standard case, when working expandably each argument is always -% grabbed separately unless the function takes only \texttt{m}-type -% arguments. To deal with the latter case, the value of -% \cs{l_@@_m_args_int} needs to be increased appropriately. +% grabbed separately. % \begin{macrocode} \cs_new_protected:Npn \@@_add_expandable_type_m:w { - \int_incr:N \l_@@_m_args_int - \@@_add_expandable_grabber_mandatory:n { m } - \bool_set_false:N \l_@@_long_bool + \@@_add_default: + \@@_add_expandable_grabber:n { m } \@@_prepare_signature:N } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_expandable_type_r:w} % \begin{macro}{\@@_add_expandable_type_R:w} -% The \texttt{r}- and \texttt{R}-types are very similar to \texttt{D}-type -% arguments, and so the same internals are used. +% The \texttt{R}-type is very similar to the \texttt{D}-type +% argument, and so the same internals are used. % \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_type_r:w #1#2 - { - \exp_args:NNNo - \@@_add_expandable_type_R:w #1 #2 \c_@@_no_value_tl - } -\cs_new_protected:Npn \@@_add_expandable_type_R:w #1#2 - { - \tl_if_eq:nnTF {#1} {#2} - { - \@@_add_expandable_grabber_mandatory:n { R_alt } - \@@_add_expandable_type_D_aux:Nn #1 - } - { - \@@_add_expandable_grabber_mandatory:n { R } - \@@_add_expandable_type_D_aux:NNn #1#2 - } - } +\cs_new_protected:Npn \@@_add_expandable_type_R:w + { \@@_add_expandable_type_D_aux:NNNn R } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}{\@@_add_expandable_type_t:w} +% An auxiliary delimited by |#1| is built now. It will be used to +% test for the presence of that token. % \begin{macrocode} \cs_new_protected:Npn \@@_add_expandable_type_t:w #1 { - \@@_add_expandable_grabber_optional:n { t } - \bool_if:NTF \l_@@_all_long_bool - { \cs_set:cpn } - { \cs_set_nopar:cpn } - { \l_@@_expandable_aux_name_tl } ##1 #1 {##1} + \@@_add_default: + \@@_add_expandable_grabber_t: + \@@_get_grabber:NN #1 \l_@@_tmpa_tl \tl_put_right:Nx \l_@@_signature_tl { - \exp_not:c { \l_@@_expandable_aux_name_tl } + \exp_not:o \l_@@_tmpa_tl \exp_not:N #1 } \bool_set_false:N \l_@@_long_bool @@ -1811,119 +2299,127 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_expandable_type_u:w} -% Invalid in an expandable context as any preceding optional argument may -% wrap part of the delimiter up in braces. +% \begin{macro}{\@@_add_expandable_grabber:n, \@@_add_expandable_grabber_t:} +% For \texttt{t}-type arguments, simply add a grabber to the signature +% and reset the boolean keeping track of~\texttt{+} markers (they +% should be ignored for the purpose of determining the long status of +% the command because they take no argument). For all other +% arguments, if the command's long status is already known then check +% that this argument has the correct long status, and otherwise set +% the long status to this argument's long status. % \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_type_u:w #1 +\cs_new_protected:Npn \@@_add_expandable_grabber:n #1 { - \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type } - { u } - \@@_add_expandable_type_m:w + \bool_if:NTF \l_@@_all_long_set_bool + { + \bool_if:nT + { \bool_xor_p:nn { \l_@@_all_long_bool } { \l_@@_long_bool } } + { + \__msg_kernel_error:nnx { xparse } { inconsistent-long } + { \iow_char:N \\ \l_@@_function_tl } + \@@_bad_def:wn + } + } + { + \bool_set:Nn \l_@@_all_long_bool { \l_@@_long_bool } + \bool_set_true:N \l_@@_all_long_set_bool + } + \tl_put_right:Nx \l_@@_signature_tl + { \exp_not:c { @@_expandable_grab_ #1 :w } } + \bool_set_false:N \l_@@_long_bool } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_add_expandable_type_v:w} -% Another forbidden type. -% \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_type_v:w +\cs_new_protected:Npn \@@_add_expandable_grabber_t: { - \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type } - { v } - \@@_add_expandable_type_m:w + \tl_put_right:Nn \l_@@_signature_tl + { \@@_expandable_grab_t:w } + \bool_set_false:N \l_@@_long_bool } % \end{macrocode} % \end{macro} % -% \begin{macro} -% { -% \@@_add_expandable_grabber_mandatory:n, -% \@@_add_expandable_grabber_optional:n -% } -% \begin{macro}[aux]{\@@_add_expandable_long_check:} -% Adding a grabber to the signature is very simple here, with only a test to -% ensure that optional arguments still have mandatory ones to follow. This -% is also a good place to check on the consistency of the long status of -% arguments. +% \begin{macro}{\@@_get_grabber:NN} +% \begin{macro}[aux]{\@@_get_grabber_auxi:NN} +% \begin{macro}[aux]{\@@_get_grabber_auxii:NN} +% Given a token |#1|, defines an expandable function delimited by that +% token and stores it in the token list~|#2|. The function is named +% after the token, unless that function name is already taken by some +% other grabber (this can happen in the rare case where delimiters +% with different category codes are used in the same document): in +% that case use a global counter to get a unique name. Since the +% grabbers are not named after \pkg{xparse} commands they should not +% be used to get material from the input stream. % \begin{macrocode} -\cs_new_protected:Npn \@@_add_expandable_grabber_mandatory:n #1 +\cs_new_protected:Npn \@@_get_grabber:NN #1#2 { - \@@_add_expandable_long_check: - \tl_put_right:Nx \l_@@_signature_tl - { \exp_not:c { @@_expandable_grab_ #1 :w } } - \bool_set_false:N \l_@@_long_bool - \int_decr:N \l_@@_mandatory_args_int + \cs_set:Npn \@@_tmp:w ##1 #1 {##1} + \exp_args:Nc \@@_get_grabber_auxi:NN + { @@_grabber_ \token_to_str:N #1 :w } #2 } -\cs_new_protected:Npn \@@_add_expandable_grabber_optional:n #1 +\cs_new_protected:Npn \@@_get_grabber_auxi:NN #1#2 { - \@@_add_expandable_long_check: - \int_compare:nNnF \l_@@_mandatory_args_int > \c_zero - { \__msg_kernel_error:nn { xparse } { expandable-ending-optional } } - \tl_put_right:Nx \l_@@_signature_tl - { \exp_not:c { @@_expandable_grab_ #1 :w } } - \bool_set_false:N \l_@@_long_bool + \cs_if_eq:NNTF \@@_tmp:w #1 + { \tl_set:Nn #2 {#1} } + { + \cs_if_exist:NTF #1 + { + \int_gincr:N \g_@@_grabber_int + \exp_args:Nc \@@_get_grabber_auxi:NN + { + @@_grabber_ + - \int_use:N \g_@@_grabber_int :w + } + #2 + } + { \@@_get_grabber_auxii:NN #1 #2 } + } } -\cs_new_protected:Npn \@@_add_expandable_long_check: +\cs_new_protected:Npn \@@_get_grabber_auxii:NN #1#2 { - \bool_if:nT { \l_@@_all_long_bool && ! \l_@@_long_bool } - { \__msg_kernel_error:nn { xparse } { inconsistent-long } } + \cs_set_eq:NN #1 \@@_tmp:w + \tl_set:Nn #2 {#1} } % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \subsection{Grabbing arguments} % % All of the grabbers follow the same basic pattern. The initial -% function sets up the appropriate information to define -% \cs{@@_grab_arg:w} to grab the argument. This means determining -% whether to use \cs{cs_set:Npn} or \cs{cs_set_nopar:Npn}, and for -% optional arguments whether to skip spaces. In all cases, -% \cs{@@_grab_arg:w} is then called to actually do the grabbing. +% function stores in \cs{l_@@_signature_tl} the code to grab further +% arguments, defines (the function in) \cs{l_@@_fn_tl} that will grab +% the argument, and calls it. % -% \begin{macro}{\@@_grab_arg:w} -% \begin{macro}[aux]{\@@_grab_arg_auxi:w} -% \begin{macro}[aux]{\@@_grab_arg_auxii:w} -% Each time an argument is actually grabbed, \pkg{xparse} defines a -% function to do it. In that way, long arguments from previous functions -% can be included in the definition of the grabber function, so that -% it does not raise an error if not long. The generic function used -% for this is reserved here. A couple of auxiliary functions are also -% needed in various places. -% \begin{macrocode} -\cs_new_protected:Npn \@@_grab_arg:w { } -\cs_new_protected:Npn \@@_grab_arg_auxi:w { } -\cs_new_protected:Npn \@@_grab_arg_auxii:w { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} +% Defining \cs{l_@@_fn_tl} means determining whether to use +% \cs{cs_set:Npn} or \cs{cs_set_nopar:Npn}, and for optional arguments +% whether to skip spaces. Once the argument is found, \cs{l_@@_fn_tl} +% calls \cs{@@_add_arg:n}, responsible for calling processors and +% grabbing further arguments. % % \begin{macro}{\@@_grab_D:w} % \begin{macro}{\@@_grab_D_long:w} % \begin{macro}{\@@_grab_D_trailing:w} % \begin{macro}{\@@_grab_D_long_trailing:w} % The generic delimited argument grabber. The auxiliary function does -% a peek test before calling \cs{@@_grab_arg:w}, so that the +% a peek test before calling \cs{@@_grab_D_call:Nw}, so that the % optional nature of the argument works as expected. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_D:w #1#2#3#4 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_D:w #1#2#3 \@@_run_code: { - \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn + \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected_nopar:Npn { _ignore_spaces } } -\cs_new_protected:Npn \@@_grab_D_long:w #1#2#3#4 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_D_long:w #1#2#3 \@@_run_code: { - \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected:Npn + \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected:Npn { _ignore_spaces } } -\cs_new_protected:Npn \@@_grab_D_trailing:w #1#2#3#4 \l_@@_args_tl - { \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn { } } -\cs_new_protected:Npn \@@_grab_D_long_trailing:w #1#2#3#4 \l_@@_args_tl - { \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected:Npn { } } +\cs_new_protected:Npn \@@_grab_D_trailing:w #1#2#3 \@@_run_code: + { \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected_nopar:Npn { } } +\cs_new_protected:Npn \@@_grab_D_long_trailing:w #1#2#3 \@@_run_code: + { \@@_grab_D_aux:NNnNn #1 #2 {#3} \cs_set_protected:Npn { } } % \end{macrocode} -% \begin{macro}[aux]{\@@_grab_D_aux:NNnnNn} +% \begin{macro}[aux]{\@@_grab_D_aux:NNnNn} % \begin{macro}[aux]{\@@_grab_D_aux:NNnN} % This is a bit complicated. The idea is that, in order to check for % nested optional argument tokens (\texttt{[[...]]} and so on) the @@ -1933,15 +2429,12 @@ % prevents loss of braces, and there is then a test to see if there are % nested delimiters to handle. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_D_aux:NNnnNn #1#2#3#4#5#6 +\cs_new_protected:Npn \@@_grab_D_aux:NNnNn #1#2#3#4#5 { - \@@_grab_D_aux:NNnN #1#2 {#4} #5 - \use:c { peek_meaning_remove #6 :NTF } #1 - { \@@_grab_arg:w } - { - \@@_add_arg:n {#3} - #4 \l_@@_args_tl - } + \@@_grab_D_aux:NNnN #1#2 {#3} #4 + \use:c { peek_meaning_remove #5 :NTF } #1 + { \@@_grab_D_call:Nw #1 } + { \@@_add_arg:o \c_@@_no_value_tl } } % \end{macrocode} % Inside the \enquote{standard} grabber, there is a test to see if the @@ -1953,48 +2446,22 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_grab_D_aux:NNnN #1#2#3#4 { - \cs_set_protected_nopar:Npn \@@_grab_arg:w + \tl_set:Nn \l_@@_signature_tl {#3} + \exp_after:wN #4 \l_@@_fn_tl ##1 #2 { - \exp_after:wN #4 \l_@@_fn_tl ####1 #2 + \tl_if_in:nnTF {##1} {#1} + { \@@_grab_D_nested:NNnN #1 #2 {##1} #4 } { - \tl_if_in:nnTF {####1} {#1} - { \@@_grab_D_nested:NNnnN #1 #2 {####1} {#3} #4 } + \tl_if_blank:oTF { \use_none:n ##1 } + { \@@_add_arg:o { \use_none:n ##1 } } { - \tl_if_blank:oTF { \use_none:n ####1 } - { \@@_add_arg:o { \use_none:n ####1 } } - { - \str_if_eq_x:nnTF - { \exp_not:o { \use_none:n ####1 } } - { { \exp_not:o { \use_ii:nnn ####1 \q_nil } } } - { \@@_add_arg:o { \use_ii:nn ####1 } } - { \@@_add_arg:o { \use_none:n ####1 } } - } - #3 \l_@@_args_tl + \str_if_eq_x:nnTF + { \exp_not:o { \use_none:n ##1 } } + { { \exp_not:o { \use_ii:nnn ##1 \q_nil } } } + { \@@_add_arg:o { \use_ii:nn ##1 } } + { \@@_add_arg:o { \use_none:n ##1 } } } } -% \end{macrocode} -% This section needs a little explanation. In order to avoid losing any -% braces, a token needs to be inserted before the argument to be grabbed. -% If the argument runs away because the closing token is missing then this -% inserted token shows up in the terminal. Ideally, |#1| would therefore be -% used directly, but that is no good as it will mess up the rest of the -% grabber. Instead, a copy of |#1| with an altered category code is used, -% as this will look right in the terminal but will not mess up the grabber. -% The only issue then is that the category code of |#1| is unknown. So there -% is a quick test to ensure that the inserted token can never be matched by -% the grabber. (This assumes that |#1| and |#2| are not the same character -% with different category codes, but that really should not happen in any -% sensible document-level syntax.) -% \begin{macrocode} - \token_if_eq_catcode:NNTF + #1 - { - \exp_after:wN \exp_after:wN \exp_after:wN - \l_@@_fn_tl \char_generate:nn { `#1 } { 11 } - } - { - \exp_after:wN \l_@@_fn_tl - \token_to_str:N #1 - } } } % \end{macrocode} @@ -2004,7 +2471,7 @@ % \end{macro} % \end{macro} % \end{macro} -% \begin{macro}[aux]{\@@_grab_D_nested:NNnnN} +% \begin{macro}[aux]{\@@_grab_D_nested:NNnN} % \begin{macro}[aux]{\@@_grab_D_nested:w} % \begin{macro}{\l_@@_nesting_a_tl} % \begin{macro}{\l_@@_nesting_b_tl} @@ -2029,11 +2496,11 @@ \tl_new:N \l_@@_nesting_a_tl \tl_new:N \l_@@_nesting_b_tl \quark_new:N \q_@@ -\cs_new_protected:Npn \@@_grab_D_nested:NNnnN #1#2#3#4#5 +\cs_new_protected:Npn \@@_grab_D_nested:NNnN #1#2#3#4 { \tl_clear:N \l_@@_nesting_a_tl \tl_clear:N \l_@@_nesting_b_tl - \exp_after:wN #5 \l_@@_fn_tl ##1 #1 ##2 \q_@@ ##3 #2 + \exp_after:wN #4 \l_@@_fn_tl ##1 #1 ##2 \q_@@ ##3 #2 { \tl_put_right:No \l_@@_nesting_a_tl { \use_none:n ##1 #1 } \tl_put_right:No \l_@@_nesting_b_tl { \use_i:nn #2 ##3 } @@ -2056,7 +2523,6 @@ \tl_put_right:No \l_@@_nesting_a_tl \l_@@_nesting_b_tl \@@_add_arg:V \l_@@_nesting_a_tl - #4 \l_@@_args_tl } } } @@ -2070,43 +2536,66 @@ % \end{macro} % \end{macro} % \end{macro} +% \begin{macro}{\@@_grab_D_call:Nw} +% For \texttt{D} and \texttt{R}-type arguments, to avoid losing any +% braces, a token needs to be inserted before the argument to be grabbed. +% If the argument runs away because the closing token is missing then this +% inserted token shows up in the terminal. Ideally, |#1| would therefore be +% used directly, but that is no good as it will mess up the rest of the +% grabber. Instead, a copy of |#1| with an altered category code is used, +% as this will look right in the terminal but will not mess up the grabber. +% The only issue then is that the category code of |#1| is unknown. So there +% is a quick test to ensure that the inserted token can never be matched by +% the grabber. (This assumes that the open and close delimiters are not the +% same character with different category codes, but that really should not +% happen in any sensible document-level syntax.) +% \begin{macrocode} +\cs_set_protected_nopar:Npn \@@_grab_D_call:Nw #1 + { + \token_if_eq_catcode:NNTF + #1 + { + \exp_after:wN \exp_after:wN \exp_after:wN + \l_@@_fn_tl \char_generate:nn { `#1 } { 11 } + } + { + \exp_after:wN \l_@@_fn_tl + \token_to_str:N #1 + } + } +% \end{macrocode} +% \end{macro} % % \begin{macro} % { % \@@_grab_E:w, \@@_grab_E_long:w, % \@@_grab_E_trailing:w, \@@_grab_E_long_trailing:w % } -% \begin{macro}[aux]{\@@_grab_E:nnnNn} -% \begin{macro}[aux]{\@@_grab_E_setup:Nw} +% \begin{macro}[aux]{\@@_grab_E:nnNn} % \begin{macro}[aux]{\@@_grab_E_loop:nnN} % \begin{macro}[aux]{\@@_grab_E_finalise:} % Everything here needs to point to a loop. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_E:w #1#2#3 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_E:w #1#2 \@@_run_code: { - \@@_grab_E:nnnNn - {#1} {#2} {#3} + \@@_grab_E:nnNn {#1} {#2} \cs_set_protected_nopar:Npn { _ignore_spaces } } -\cs_new_protected:Npn \@@_grab_E_long:w #1#2#3 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_E_long:w #1#2 \@@_run_code: { - \@@_grab_E:nnnNn - {#1} {#2} {#3} + \@@_grab_E:nnNn {#1} {#2} \cs_set_protected:Npn { _ignore_spaces } } -\cs_new_protected:Npn \@@_grab_E_trailing:w #1#2#3 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_E_trailing:w #1#2 \@@_run_code: { - \@@_grab_E:nnnNn - {#1} {#2} {#3} + \@@_grab_E:nnNn {#1} {#2} \cs_set_protected_nopar:Npn { } } -\cs_new_protected:Npn \@@_grab_E_long_trailing:w #1#2#3 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_E_long_trailing:w #1#2 \@@_run_code: { - \@@_grab_E:nnnNn - {#1} {#2} {#3} + \@@_grab_E:nnNn {#1} {#2} \cs_set_protected:Npn { } } @@ -2116,16 +2605,15 @@ % they can appear later. The grabbed values are held in a property list % which is then turned into an ordered list to be passed back to the user. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_E:nnnNn #1#2#3#4#5 +\cs_new_protected:Npn \@@_grab_E:nnNn #1#2#3#4 { - \exp_after:wN #4 \l_@@_fn_tl ##1##2##3 + \exp_after:wN #3 \l_@@_fn_tl ##1##2##3 { \prop_put:Nnn \l_@@_tmp_prop {##1} {##3} - \@@_grab_E_loop:nnN {#5} { } ##2 \q_recursion_stop + \@@_grab_E_loop:nnN {#4} { } ##2 \q_recursion_stop } \prop_clear:N \l_@@_tmp_prop - \@@_grab_E_setup:Nw - #1 \q_recursion_tail \q_mark #2 \q_recursion_tail \q_recursion_stop + \tl_set:Nn \l_@@_signature_tl {#2} \cs_set_protected:Npn \@@_grab_E_finalise: { \tl_clear:N \l_@@_tmpa_tl @@ -2140,21 +2628,8 @@ } } \@@_add_arg:V \l_@@_tmpa_tl - #3 \l_@@_args_tl } - \@@_grab_E_loop:nnN {#5} { } #1 \q_recursion_tail \q_recursion_stop - } -% \end{macrocode} -% To allow for flexible default values, the list of those given may be -% shorter than the number of test tokens. This can readily be achieved -% by storing only the given defaults in the property list. -% \begin{macrocode} -\cs_new_protected:Npn \@@_grab_E_setup:Nw #1#2 \q_mark #3 - { - \quark_if_recursion_tail_stop:N #1 - \quark_if_recursion_tail_stop:n {#3} - \prop_put:Nnn \l_@@_tmp_prop {#1} {#3} - \@@_grab_E_setup:Nw #2 \q_mark + \@@_grab_E_loop:nnN {#4} { } #1 \q_recursion_tail \q_recursion_stop } \cs_new_protected:Npn \@@_grab_E_loop:nnN #1#2#3#4 \q_recursion_stop { @@ -2172,42 +2647,36 @@ % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macro}{\@@_grab_G:w} % \begin{macro}{\@@_grab_G_long:w} % \begin{macro}{\@@_grab_G_trailing:w} % \begin{macro}{\@@_grab_G_long_trailing:w} -% \begin{macro}[aux]{\@@_grab_G_aux:nnNn} +% \begin{macro}[aux]{\@@_grab_G_aux:nNn} % Optional groups are checked by meaning, so that the same code will % work with, for example, Con\TeX{}t-like input. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_G:w #1#2 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_G:w #1 \@@_run_code: { - \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected_nopar:Npn + \@@_grab_G_aux:nNn {#1} \cs_set_protected_nopar:Npn { _ignore_spaces } } -\cs_new_protected:Npn \@@_grab_G_long:w #1#2 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_G_long:w #1 \@@_run_code: { - \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected:Npn { _ignore_spaces } + \@@_grab_G_aux:nNn {#1} \cs_set_protected:Npn { _ignore_spaces } } -\cs_new_protected:Npn \@@_grab_G_trailing:w #1#2 \l_@@_args_tl - { \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected_nopar:Npn { } } -\cs_new_protected:Npn \@@_grab_G_long_trailing:w #1#2 \l_@@_args_tl - { \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected:Npn { } } -\cs_new_protected:Npn \@@_grab_G_aux:nnNn #1#2#3#4 +\cs_new_protected:Npn \@@_grab_G_trailing:w #1 \@@_run_code: + { \@@_grab_G_aux:nNn {#1} \cs_set_protected_nopar:Npn { } } +\cs_new_protected:Npn \@@_grab_G_long_trailing:w #1 \@@_run_code: + { \@@_grab_G_aux:nNn {#1} \cs_set_protected:Npn { } } +\cs_new_protected:Npn \@@_grab_G_aux:nNn #1#2#3 { - \exp_after:wN #3 \l_@@_fn_tl ##1 - { - \@@_add_arg:n {##1} - #2 \l_@@_args_tl - } - \use:c { peek_meaning #4 :NTF } \c_group_begin_token + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN #2 \l_@@_fn_tl ##1 + { \@@_add_arg:n {##1} } + \use:c { peek_meaning #3 :NTF } \c_group_begin_token { \l_@@_fn_tl } - { - \@@_add_arg:n {#1} - #2 \l_@@_args_tl - } + { \@@_add_arg:o \c_@@_no_value_tl } } % \end{macrocode} % \end{macro} @@ -2221,17 +2690,15 @@ % \begin{macro}[aux]{\@@_grab_l_aux:nN} % Argument grabbers for mandatory \TeX{} arguments are pretty simple. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_l:w #1 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_l:w #1 \@@_run_code: { \@@_grab_l_aux:nN {#1} \cs_set_protected_nopar:Npn } -\cs_new_protected:Npn \@@_grab_l_long:w #1 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_l_long:w #1 \@@_run_code: { \@@_grab_l_aux:nN {#1} \cs_set_protected:Npn } \cs_new_protected:Npn \@@_grab_l_aux:nN #1#2 { + \tl_set:Nn \l_@@_signature_tl {#1} \exp_after:wN #2 \l_@@_fn_tl ##1## - { - \@@_add_arg:n {##1} - #1 \l_@@_args_tl - } + { \@@_add_arg:n {##1} } \l_@@_fn_tl } % \end{macrocode} @@ -2243,22 +2710,18 @@ % \begin{macro}{\@@_grab_m_long:w} % Collecting a single mandatory argument is quite easy. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_m:w #1 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_m:w #1 \@@_run_code: { + \tl_set:Nn \l_@@_signature_tl {#1} \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl ##1 - { - \@@_add_arg:n {##1} - #1 \l_@@_args_tl - } + { \@@_add_arg:n {##1} } \l_@@_fn_tl } -\cs_new_protected:Npn \@@_grab_m_long:w #1 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_m_long:w #1 \@@_run_code: { + \tl_set:Nn \l_@@_signature_tl {#1} \exp_after:wN \cs_set_protected:Npn \l_@@_fn_tl ##1 - { - \@@_add_arg:n {##1} - #1 \l_@@_args_tl - } + { \@@_add_arg:n {##1} } \l_@@_fn_tl } % \end{macrocode} @@ -2273,92 +2736,71 @@ % \begin{macro}{\@@_grab_m_6:w} % \begin{macro}{\@@_grab_m_7:w} % \begin{macro}{\@@_grab_m_8:w} -% Grabbing 1--8 mandatory arguments. We don't need to worry about -% nine arguments as this is only possible if everything is -% mandatory. Each function has an auxiliary so that \cs{par} tokens -% from other arguments still work. +% \begin{macro}{\@@_grab_m_9:w} +% \begin{macro}[aux]{\@@_grab_m_aux:Nnnnnnnnn} +% Grabbing 1--8 mandatory arguments is done by giving 8--1 known +% arguments to a 9-argument function that stores them in +% \cs{l_@@_args_tl}. For simplicity, grabbing 9 mandatory arguments +% is done by grabbing 5 then 4 arguments. % \begin{macrocode} -\cs_new_protected:cpn { @@_grab_m_1:w } #1 \l_@@_args_tl +\cs_new_protected_nopar:Npn \@@_grab_m_aux:Nnnnnnnnn #1#2#3#4#5#6#7#8#9 { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl ##1 - { - \tl_put_right:Nn \l_@@_args_tl { {##1} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_put_right:No \l_@@_args_tl + { #1 {#2} {#3} {#4} {#5} {#6} {#7} {#8} {#9} } + \l_@@_signature_tl \@@_run_code: } -\cs_new_protected:cpn { @@_grab_m_2:w } #1 \l_@@_args_tl +\cs_new_protected:cpn { @@_grab_m_1:w } #1 \@@_run_code: { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl - ##1##2 - { - \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \use_none:nnnnnnn { } { } { } { } { } { } { } } -\cs_new_protected:cpn { @@_grab_m_3:w } #1 \l_@@_args_tl +\cs_new_protected:cpn { @@_grab_m_2:w } #1 \@@_run_code: { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl - ##1##2##3 - { - \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} {##3} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \use_none:nnnnnn { } { } { } { } { } { } } -\cs_new_protected:cpn { @@_grab_m_4:w } #1 \l_@@_args_tl +\cs_new_protected:cpn { @@_grab_m_3:w } #1 \@@_run_code: { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl - ##1##2##3##4 - { - \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} {##3} {##4} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \use_none:nnnnn { } { } { } { } { } } -\cs_new_protected:cpn { @@_grab_m_5:w } #1 \l_@@_args_tl +\cs_new_protected:cpn { @@_grab_m_4:w } #1 \@@_run_code: { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl - ##1##2##3##4##5 - { - \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} {##3} {##4} {##5} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \use_none:nnnn { } { } { } { } } -\cs_new_protected:cpn { @@_grab_m_6:w } #1 \l_@@_args_tl +\cs_new_protected:cpn { @@_grab_m_5:w } #1 \@@_run_code: { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl - ##1##2##3##4##5##6 - { - \tl_put_right:Nn \l_@@_args_tl - { {##1} {##2} {##3} {##4} {##5} {##6} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \use_none:nnn { } { } { } } -\cs_new_protected:cpn { @@_grab_m_7:w } #1 \l_@@_args_tl +\cs_new_protected:cpn { @@_grab_m_6:w } #1 \@@_run_code: { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl - ##1##2##3##4##5##6##7 - { - \tl_put_right:Nn \l_@@_args_tl - { {##1} {##2} {##3} {##4} {##5} {##6} {##7} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \use_none:nn { } { } } -\cs_new_protected:cpn { @@_grab_m_8:w } #1 \l_@@_args_tl +\cs_new_protected:cpn { @@_grab_m_7:w } #1 \@@_run_code: { - \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl - ##1##2##3##4##5##6##7##8 - { - \tl_put_right:Nn \l_@@_args_tl - { {##1} {##2} {##3} {##4} {##5} {##6} {##7} {##8} } - #1 \l_@@_args_tl - } - \l_@@_fn_tl + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \use_none:n { } + } +\cs_new_protected:cpn { @@_grab_m_8:w } #1 \@@_run_code: + { + \tl_set:Nn \l_@@_signature_tl {#1} + \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn + \l_@@_fn_tl \prg_do_nothing: + } +\cs_new_protected:cpx { @@_grab_m_9:w } + { + \exp_not:c { @@_grab_m_5:w } + \exp_not:c { @@_grab_m_4:w } } % \end{macrocode} % \end{macro} @@ -2369,27 +2811,29 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\@@_grab_R:w, \@@_grab_R_long:w} -% \begin{macro}[aux]{\@@_grab_R_aux:NNnnN} +% \begin{macro}[aux]{\@@_grab_R_aux:NNnN} % The grabber for \texttt{R}-type arguments is basically the same as % that for \texttt{D}-type ones, but always skips spaces (as it is mandatory) % and has a hard-coded error message. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_R:w #1#2#3#4 \l_@@_args_tl - { \@@_grab_R_aux:NNnnN #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn } -\cs_new_protected:Npn \@@_grab_R_long:w #1#2#3#4 \l_@@_args_tl - { \@@_grab_R_aux:NNnnN #1 #2 {#3} {#4} \cs_set_protected:Npn } -\cs_new_protected:Npn \@@_grab_R_aux:NNnnN #1#2#3#4#5 +\cs_new_protected:Npn \@@_grab_R:w #1#2#3 \@@_run_code: + { \@@_grab_R_aux:NNnN #1 #2 {#3} \cs_set_protected_nopar:Npn } +\cs_new_protected:Npn \@@_grab_R_long:w #1#2#3 \@@_run_code: + { \@@_grab_R_aux:NNnN #1 #2 {#3} \cs_set_protected:Npn } +\cs_new_protected:Npn \@@_grab_R_aux:NNnN #1#2#3#4 { - \@@_grab_D_aux:NNnN #1 #2 {#4} #5 + \@@_grab_D_aux:NNnN #1 #2 {#3} #4 \peek_meaning_remove_ignore_spaces:NTF #1 - { \@@_grab_arg:w } + { \@@_grab_D_call:Nw #1 } { \__msg_kernel_error:nnxx { xparse } { missing-required } - { \token_to_str:N #1 } { \tl_to_str:n {#3} } - \@@_add_arg:n {#3} - #4 \l_@@_args_tl + { \exp_after:wN \token_to_str:N \l_@@_fn_tl } + { \token_to_str:N #1 } + \@@_add_arg:o \c_@@_no_value_tl } } % \end{macrocode} @@ -2400,34 +2844,24 @@ % \begin{macro}{\@@_grab_t_long:w} % \begin{macro}{\@@_grab_t_trailing:w} % \begin{macro}{\@@_grab_t_long_trailing:w} -% \begin{macro}[aux]{\@@_grab_t_aux:NnNn} +% \begin{macro}[aux]{\@@_grab_t_aux:NNw} % Dealing with a token is quite easy. Check the match, remove the % token if needed and add a flag to the output. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_t:w #1#2 \l_@@_args_tl - { - \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected_nopar:Npn - { _ignore_spaces } - } -\cs_new_protected:Npn \@@_grab_t_long:w #1#2 \l_@@_args_tl - { \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected:Npn { _ignore_spaces } } -\cs_new_protected:Npn \@@_grab_t_trailing:w #1#2 \l_@@_args_tl - { \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected_nopar:Npn { } } -\cs_new_protected:Npn \@@_grab_t_long_trailing:w #1#2 \l_@@_args_tl - { \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected:Npn { } } -\cs_new_protected:Npn \@@_grab_t_aux:NnNn #1#2#3#4 - { - \exp_after:wN #3 \l_@@_fn_tl +\cs_new_protected:Npn \@@_grab_t:w + { \@@_grab_t_aux:NNw \peek_meaning_remove_ignore_spaces:NTF } +\cs_new_eq:NN \@@_grab_t_long:w \@@_grab_t:w +\cs_new_protected:Npn \@@_grab_t_trailing:w + { \@@_grab_t_aux:NNw \peek_meaning_remove:NTF } +\cs_new_eq:NN \@@_grab_t_long_trailing:w \@@_grab_t_trailing:w +\cs_new_protected:Npn \@@_grab_t_aux:NNw #1#2#3 \@@_run_code: + { + \tl_set:Nn \l_@@_signature_tl {#3} + \exp_after:wN \cs_set_protected:Npn \l_@@_fn_tl { - \use:c { peek_meaning_remove #4 :NTF } #1 - { - \@@_add_arg:n { \BooleanTrue } - #2 \l_@@_args_tl - } - { - \@@_add_arg:n { \BooleanFalse } - #2 \l_@@_args_tl - } + #1 #2 + { \@@_add_arg:n { \BooleanTrue } } + { \@@_add_arg:n { \BooleanFalse } } } \l_@@_fn_tl } @@ -2444,17 +2878,15 @@ % Grabbing up to a list of tokens is quite easy: define the grabber, % and then collect. % \begin{macrocode} -\cs_new_protected:Npn \@@_grab_u:w #1#2 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_u:w #1#2 \@@_run_code: { \@@_grab_u_aux:nnN {#1} {#2} \cs_set_protected_nopar:Npn } -\cs_new_protected:Npn \@@_grab_u_long:w #1#2 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_u_long:w #1#2 \@@_run_code: { \@@_grab_u_aux:nnN {#1} {#2} \cs_set_protected:Npn } \cs_new_protected:Npn \@@_grab_u_aux:nnN #1#2#3 { + \tl_set:Nn \l_@@_signature_tl {#2} \exp_after:wN #3 \l_@@_fn_tl ##1 #1 - { - \@@_add_arg:n {##1} - #2 \l_@@_args_tl - } + { \@@_add_arg:n {##1} } \l_@@_fn_tl } % \end{macrocode} @@ -2466,7 +2898,6 @@ % \begin{macro}{\@@_grab_v_long:w} % \begin{macro}{\@@_grab_v_aux:w} % \begin{macro}{\@@_grab_v_group_end:} -% \begin{variable}{\l_@@_v_rest_of_signature_tl} % \begin{variable}{\l_@@_v_arg_tl} % The opening delimiter is the first non-space token, and is never % read verbatim. This is required by consistency with the case where @@ -2484,7 +2915,6 @@ % It is ended by \cs{@@_grab_v_group_end:}, which smuggles % the collected argument out of the group. % \begin{macrocode} -\tl_new:N \l_@@_v_rest_of_signature_tl \tl_new:N \l_@@_v_arg_tl \cs_new_protected:Npn \@@_grab_v:w { @@ -2496,9 +2926,9 @@ \bool_set_true:N \l_@@_long_bool \@@_grab_v_aux:w } -\cs_new_protected:Npn \@@_grab_v_aux:w #1 \l_@@_args_tl +\cs_new_protected:Npn \@@_grab_v_aux:w #1 \@@_run_code: { - \tl_set:Nn \l_@@_v_rest_of_signature_tl {#1} + \tl_set:Nn \l_@@_signature_tl {#1} \group_begin: \group_align_safe_begin: \tex_escapechar:D = 92 \scan_stop: @@ -2523,7 +2953,6 @@ } % \end{macrocode} % \end{variable} -% \end{variable} % \end{macro} % \end{macro} % \end{macro} @@ -2586,8 +3015,7 @@ \cs_new_protected:Npn \@@_grab_v_aux_loop_end: { \@@_grab_v_group_end: - \exp_args:Nx \@@_add_arg:n { \tl_tail:N \l_@@_v_arg_tl } - \l_@@_v_rest_of_signature_tl \l_@@_args_tl + \@@_add_arg:x { \tl_tail:N \l_@@_v_arg_tl } } % \end{macrocode} % \end{macro} @@ -2681,7 +3109,6 @@ \cs_new_protected:Npn \@@_grab_v_aux_abort:n #1 { \@@_grab_v_group_end: - \@@_add_arg:o \c_@@_no_value_tl \exp_after:wN \exp_after:wN \exp_after:wN \peek_meaning_remove:NTF \char_generate:nn { \tex_endlinechar:D } { 6 } { @@ -2689,14 +3116,14 @@ { \exp_after:wN \token_to_str:N \l_@@_fn_tl } { \tl_to_str:N \l_@@_v_arg_tl } { \tl_to_str:n {#1} } - \l_@@_v_rest_of_signature_tl \l_@@_args_tl + \@@_add_arg:o \c_@@_no_value_tl } { \__msg_kernel_error:nnxxx { xparse } { verbatim-tokenized } { \exp_after:wN \token_to_str:N \l_@@_fn_tl } { \tl_to_str:N \l_@@_v_arg_tl } { \tl_to_str:n {#1} } - \l_@@_v_rest_of_signature_tl \l_@@_args_tl + \@@_add_arg:o \c_@@_no_value_tl } } % \end{macrocode} @@ -2732,51 +3159,23 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_arg:n, \@@_add_arg:V, \@@_add_arg:o} -% \begin{macro}[aux]{\@@_add_arg_aux:n, \@@_add_arg_aux:V} -% The argument-storing system provides a single point for interfacing -% with processors. They are done in a loop, counting downward. In this -% way, the processor which was found last is executed first. The result -% is that processors apply from right to left, as intended. Notice that -% a set of braces are added back around the result of processing so that -% the internal function will correctly pick up one argument for each -% input argument. +% \begin{macro}{\@@_add_arg:n, \@@_add_arg:V, \@@_add_arg:o, \@@_add_arg:x} +% When an argument is found it is stored, then further arguments are +% grabbed by calling \cs{l_@@_signature_tl}. % \begin{macrocode} \cs_new_protected:Npn \@@_add_arg:n #1 { - \int_compare:nNnTF \l_@@_processor_int = \c_zero - { \tl_put_right:Nn \l_@@_args_tl { {#1} } } - { - \tl_clear:N \ProcessedArgument - \@@_if_no_value:nTF {#1} - { - \int_zero:N \l_@@_processor_int - \tl_put_right:Nn \l_@@_args_tl { {#1} } - } - { \@@_add_arg_aux:n {#1} } - } + \tl_put_right:Nn \l_@@_args_tl { {#1} } + \l_@@_signature_tl \@@_run_code: } -\cs_generate_variant:Nn \@@_add_arg:n { V , o } -\cs_new_protected:Npn \@@_add_arg_aux:n #1 - { - \use:c { @@_processor_ \int_use:N \l_@@_processor_int :n } {#1} - \int_decr:N \l_@@_processor_int - \int_compare:nNnTF \l_@@_processor_int = \c_zero - { - \tl_put_right:Nx \l_@@_args_tl - { { \exp_not:V \ProcessedArgument } } - } - { \@@_add_arg_aux:V \ProcessedArgument } -} -\cs_generate_variant:Nn \@@_add_arg_aux:n { V } +\cs_generate_variant:Nn \@@_add_arg:n { V , o , x } % \end{macrocode} % \end{macro} -% \end{macro} % % \subsection{Grabbing arguments expandably} % % \begin{macro}[EXP]{\@@_expandable_grab_D:w} -% \begin{macro}[EXP, aux]{\@@_expandable_grab_D:NNNnwN} +% \begin{macro}[EXP, aux]{\@@_expandable_grab_D:NNNwNn} % \begin{macro}[EXP, aux]{\@@_expandable_grab_D:NNNwNnnn} % \begin{macro}[EXP, aux]{\@@_expandable_grab_D:Nw} % \begin{macro}[EXP, aux]{\@@_expandable_grab_D:nnNNNwN} @@ -2785,25 +3184,24 @@ % it. % \begin{macrocode} \cs_new:Npn \@@_expandable_grab_D:w #1 \q_@@ #2 - { #2 { \@@_expandable_grab_D:NNNnwNn #1 \q_@@ #2 } } + { #2 { \@@_expandable_grab_D:NNNwNn #1 \q_@@ #2 } } % \end{macrocode} -% We then wish to test whether |#7|, which we just grabbed, is exactly |#2|. +% We then wish to test whether |#6|, which we just grabbed, is exactly |#2|. % Expand the only grabber function we have, |#1|, once: the two strings below -% are equal if and only if |#7| matches |#2| exactly.\footnote{It is obvious -% that if \texttt{\#7} matches \texttt{\#2} then the strings are equal. We +% are equal if and only if |#6| matches |#2| exactly.\footnote{It is obvious +% that if \texttt{\#6} matches \texttt{\#2} then the strings are equal. We % must check the converse. The right-hand-side of \cs{str_if_eq:onTF} does % not end with \texttt{\#3}, implying that the grabber function took % everything as its arguments. The first brace group can only be empty if -% \texttt{\#7} starts with \texttt{\#2}, otherwise the brace group preceding -% \texttt{\#7} would not vanish. The third brace group is empty, thus the +% \texttt{\#6} starts with \texttt{\#2}, otherwise the brace group preceding +% \texttt{\#6} would not vanish. The third brace group is empty, thus the % \cs{q_@@} that was used by our grabber \texttt{\#1} must be the one -% that we inserted (not some token in \texttt{\#7}), hence the second brace -% group contains the end of \texttt{\#7} followed by \texttt{\#2}. Since this +% that we inserted (not some token in \texttt{\#6}), hence the second brace +% group contains the end of \texttt{\#6} followed by \texttt{\#2}. Since this % is \texttt{\#2} on the right-hand-side, and no brace can be lost there, -% \texttt{\#7} must contain nothing else than its leading \texttt{\#2}.} If -% |#7| does not match |#2|, then the optional argument is missing, we use the -% default |#4|, and put back the argument |#7| in the input stream. -% %^^A There is probably a bug similar to the non-expandable O{\par} bug. +% \texttt{\#6} must contain nothing else than its leading \texttt{\#2}.} If +% |#6| does not match |#2|, then the optional argument is missing, we use the +% default |-NoValue-|, and put back the argument |#6| in the input stream. % % If it does match, then interesting things need to be done. We will grab the % argument piece by piece, with the following pattern: @@ -2825,19 +3223,24 @@ % \meta{piece 2}. We stop grabbing arguments once the \meta{piece 2} contains % no opening delimiter any more, hence the balance is reached, and the final % argument is \meta{piece 1} \meta{piece 2}. +% The indirection via \cs{@@_tmp:w} allows to insert |-NoValue-| expanded. % \begin{macrocode} -\cs_new:Npn \@@_expandable_grab_D:NNNnwNn #1#2#3#4#5 \q_@@ #6#7 +\cs_set_protected:Npn \@@_tmp:w #1 { - \str_if_eq:onTF - { #1 { } { } #7 #2 \q_@@ #3 } - { { } {#2} { } } + \cs_new:Npn \@@_expandable_grab_D:NNNwNn ##1##2##3##4 \q_@@ ##5##6 { - #1 - { \@@_expandable_grab_D:NNNwNnnn #1#2#3#5 \q_@@ #6 } - \q_nil { } #2 \ERROR \q_@@ \ERROR + \str_if_eq:onTF + { ##1 { } { } ##6 ##2 \q_@@ ##3 } + { { } {##2} { } } + { + ##1 + { \@@_expandable_grab_D:NNNwNnnn ##1##2##3##4 \q_@@ ##5 } + \q_nil { } ##2 \ERROR \q_@@ \ERROR + } + { ##4 {#1} \q_@@ ##5 {##6} } } - { #5 {#4} \q_@@ #6 {#7} } } +\exp_args:No \@@_tmp:w { \c_@@_no_value_tl } % \end{macrocode} % At this stage, |#6| is \cs{q_nil} \Arg{piece 1} \meta{more for piece 1}, % and we want to concatenate all that, removing \cs{q_nil}, and keeping the @@ -2896,26 +3299,30 @@ % \end{macro} % % \begin{macro}[EXP]{\@@_expandable_grab_D_alt:w} -% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:NNnwNn} -% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:Nw} +% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:NNwNn} +% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:Nwn} % When the delimiters are identical, nesting is not possible and a simplified % approach is used. The test concept here is the same as for the case where % the delimiters are different. % \begin{macrocode} \cs_new:Npn \@@_expandable_grab_D_alt:w #1 \q_@@ #2 - { #2 { \@@_expandable_grab_D_alt:NNnwNn #1 \q_@@ #2 } } -\cs_new:Npn \@@_expandable_grab_D_alt:NNnwNn #1#2#3#4 \q_@@ #5#6 + { #2 { \@@_expandable_grab_D_alt:NNwNn #1 \q_@@ #2 } } +\cs_set_protected:Npn \@@_tmp:w #1 { - \str_if_eq:onTF - { #1 { } #6 #2 #2 } - { { } #2 } + \cs_new:Npn \@@_expandable_grab_D_alt:NNwNn ##1##2##3 \q_@@ ##4##5 { - #1 - { \@@_expandable_grab_D_alt:Nwn #5 #4 \q_@@ } - #6 \ERROR + \str_if_eq:onTF + { ##1 { } ##5 ##2 ##2 } + { { } ##2 } + { + ##1 + { \@@_expandable_grab_D_alt:Nwn ##4 ##3 \q_@@ } + ##5 \ERROR + } + { ##3 {#1} \q_@@ ##4 {##5} } } - { #4 {#3} \q_@@ #5 {#6} } } +\exp_args:No \@@_tmp:w { \c_@@_no_value_tl } \cs_new:Npn \@@_expandable_grab_D_alt:Nwn #1#2 \q_@@ #3 { \tl_if_blank:oTF { \use_none:n #3 } @@ -2934,6 +3341,74 @@ % \end{macro} % \end{macro} % +% \begin{macro}[EXP]{\@@_expandable_grab_E:w} +% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_test:nnwn} +% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_loop:nnnNNw} +% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_aux:nnw} +% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_aux:nnnnn} +% \begin{macro}[EXP,aux]{\@@_expandable_grab_E_end:nnw} +% The function will be called repeatedly with two arguments: the set +% of pairs \meta{parser} \meta{token}, and the set of arguments found +% so far (initially all |{-NoValue-}|). At each step, grab what +% follows in the input stream then call the \texttt{loop:nnnNNwn} +% auxiliary to compare it with each possible embellishment in turn. +% This auxiliary's |#1| is what was found in the input, |#2| collects +% \meta{parser} \meta{token} pairs that did not match, |#3| collects +% the corresponding arguments found previously, |#4| and |#5| is the +% current pair, |#6| is the remaining pairs, |#7| is empty or two +% \cs{q_nil}, and |#8| is the current argument. If none of the pairs +% matched (determined by \cs{quark_if_nil:NTF}) then call the +% \texttt{end} auxiliary to stop looking for embellishments, +% remembering to put what was grabbed in the input back where it +% belongs, and storing the arguments found just before \cs{q_@@}. If +% the current argument |#8| is not |-NoValue-| or if the input |#1| +% does not match |#5| (see \texttt{t}-type arguments below for a +% similar \cs{str_if_eq:onTF} test) then carry on the loop. +% Otherwise, we found a new embellishment: grab the corresponding +% argument in the input using the \texttt{:w} auxiliary. To avoid +% losing braces around that auxiliary's argument |#4| we include a +% space, which will be eliminated in the next loop through +% embellishments. +% \begin{macrocode} +\cs_new:Npn \@@_expandable_grab_E:w #1 \q_@@ #2 + { #2 { \@@_expandable_grab_E_test:nnwn #1 \q_@@ #2 } } +\cs_new:Npn \@@_expandable_grab_E_test:nnwn #1#2#3 \q_@@ #4#5 + { + \@@_expandable_grab_E_loop:nnnNNw {#5} { } { } + #1 \q_nil \q_nil \q_nil \q_mark #2 \q_nil + #3 \q_@@ #4 + } +\cs_new:Npn \@@_expandable_grab_E_loop:nnnNNw + #1#2#3#4#5#6 \q_nil #7 \q_mark #8 + { + \quark_if_nil:NTF #4 + { \@@_expandable_grab_E_end:nnw {#1} {#3} } + { + \@@_if_no_value:nTF {#8} + { \str_if_eq:onTF { #4 { } #1 #5 } {#5} } + { \use_ii:nn } + { \@@_expandable_grab_E_aux:w { #2 #4 #5 #6 } {#3} ~ } + { + \@@_expandable_grab_E_loop:nnnNNw + {#1} { #2 #4 #5 } { #3 {#8} } + #6 \q_nil #7 \q_mark + } + } + } +\cs_new:Npn \@@_expandable_grab_E_aux:w #1 \q_@@ #2 + { #2 { \@@_expandable_grab_E_aux:nnw #1 \q_@@ #2 } } +\cs_new:Npn \@@_expandable_grab_E_aux:nnw #1#2#3 \q_nil #4 \q_@@ #5#6 + { \@@_expandable_grab_E:w {#1} { #2 {#6} #3 } #4 \q_@@ #5 } +\cs_new:Npn \@@_expandable_grab_E_end:nnw #1#2#3 \q_@@ #4 + { #3 {#2} \q_@@ #4 {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro}[EXP]{\@@_expandable_grab_m:w} % \begin{macro}[EXP, aux]{\@@_expandable_grab_m_aux:wNn} % The mandatory case is easy: find the auxiliary after the \cs{q_@@}, and @@ -2948,56 +3423,64 @@ % \end{macro} % % \begin{macro}[EXP]{\@@_expandable_grab_R:w} -% \begin{macro}[EXP, aux]{\@@_expandable_grab_R_aux:NNwn} +% \begin{macro}[EXP, aux]{\@@_expandable_grab_R_aux:NNNwNn} % Much the same as for the \texttt{D}-type argument, with only the lead-off % function varying. % \begin{macrocode} \cs_new:Npn \@@_expandable_grab_R:w #1 \q_@@ #2 - { #2 { \@@_expandable_grab_R_aux:NNNnwNn #1 \q_@@ #2 } } -\cs_new:Npn \@@_expandable_grab_R_aux:NNNnwNn #1#2#3#4#5 \q_@@ #6#7 + { #2 { \@@_expandable_grab_R_aux:NNNwNn #1 \q_@@ #2 } } +\cs_set_protected:Npn \@@_tmp:w #1 { - \str_if_eq:onTF - { #1 { } { } #7 #2 \q_@@ #3 } - { { } {#2} { } } - { - #1 - { \@@_expandable_grab_D:NNNwNnnn #1#2#3#5 \q_@@ #6 } - \q_nil { } #2 \ERROR \q_@@ \ERROR - } + \cs_new:Npn \@@_expandable_grab_R_aux:NNNwNn ##1##2##3##4 \q_@@ ##5##6 { - \__msg_kernel_expandable_error:nnn - { xparse } { missing-required } {#2} - #5 {#4} \q_@@ #6 {#7} + \str_if_eq:onTF + { ##1 { } { } ##6 ##2 \q_@@ ##3 } + { { } {##2} { } } + { + ##1 + { \@@_expandable_grab_D:NNNwNnnn ##1##2##3##4 \q_@@ ##5 } + \q_nil { } ##2 \ERROR \q_@@ \ERROR + } + { + \__msg_kernel_expandable_error:nnnn + { xparse } { missing-required } {##5} {##2} + ##4 {#1} \q_@@ ##5 {##6} + } } } +\exp_args:No \@@_tmp:w { \c_@@_no_value_tl } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[EXP]{\@@_expandable_grab_R_alt:w} -% \begin{macro}[EXP]{\@@_expandable_grab_R_alt_aux:NNnwNn} +% \begin{macro}[EXP]{\@@_expandable_grab_R_alt_aux:NNwNn} % When the delimiters are identical, nesting is not possible and a simplified % approach is used. The test concept here is the same as for the case where % the delimiters are different. % \begin{macrocode} \cs_new:Npn \@@_expandable_grab_R_alt:w #1 \q_@@ #2 { #2 { \@@_expandable_grab_R_alt_aux:NNnwNn #1 \q_@@ #2 } } -\cs_new:Npn \@@_expandable_grab_R_alt_aux:NNnwNn #1#2#3#4 \q_@@ #5#6 +\cs_set_protected:Npn \@@_tmp:w #1 { - \str_if_eq:onTF - { #1 { } #6 #2 #2 } - { { } #2 } - { - #1 - { \@@_expandable_grab_D_alt:Nwn #5 #4 \q_@@ } - #6 \ERROR - } + \cs_new:Npn \@@_expandable_grab_R_alt_aux:NNwNn ##1##2##3 \q_@@ ##4##5 { - \__msg_kernel_expandable_error:nnn - { xparse } { missing-required } {#2} - #4 {#3} \q_@@ #5 {#6} + \str_if_eq:onTF + { ##1 { } ##5 ##2 ##2 } + { { } ##2 } + { + ##1 + { \@@_expandable_grab_D_alt:Nwn ##4 ##3 \q_@@ } + ##5 \ERROR + } + { + \__msg_kernel_expandable_error:nnnn + { xparse } { missing-required } {##4} {##2} + ##3 {#1} \q_@@ ##4 {##5} + } } } +\exp_args:No \@@_tmp:w { \c_@@_no_value_tl } % \end{macrocode} % \end{macro} % \end{macro} @@ -3029,29 +3512,8 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_grab_expandable_end:wN} -% For the end of the grabbing sequence: get rid of the generic grabber and -% insert the code function followed by its arguments. -% \begin{macrocode} -\cs_new:Npn \@@_grab_expandable_end:wN #1 \q_@@ #2 {#1} -% \end{macrocode} -% \end{macro} -% % \subsection{Argument processors} % -% \begin{macro}{\@@_process_arg:n} -% Processors are saved for use later during the grabbing process. -% \begin{macrocode} -\cs_new_protected:Npn \@@_process_arg:n #1 - { - \int_incr:N \l_@@_processor_int - \cs_set_protected:cpx - { @@_processor_ \int_use:N \l_@@_processor_int :n } ##1 - { \exp_not:n {#1} {##1} } - } -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\@@_bool_reverse:N} % A simple reversal. % \begin{macrocode} @@ -3216,22 +3678,37 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_get_arg_spec:NTF} +% If the command is not an \pkg{xparse} command, complain. If it is, +% its second \enquote{item} is the argument specification. +% \begin{macrocode} +\cs_new_protected:Npn \@@_get_arg_spec:NTF #1#2#3 + { + \@@_cmd_if_xparse:NTF #1 + { + \tl_set:Nx \ArgumentSpecification { \tl_item:Nn #1 { 2 } } + #2 + } + {#3} + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\@@_get_arg_spec:N} % \begin{macro}{\@@_get_arg_spec:n} % \begin{variable}{\ArgumentSpecification} -% Recovering the argument specification is trivial, using the -% branching \cs{prop_get:NnN} function. +% Recovering the argument specification is now trivial. % \begin{macrocode} \cs_new_protected:Npn \@@_get_arg_spec:N #1 { - \prop_get:NnNF \l_@@_command_arg_specs_prop {#1} - \ArgumentSpecification + \@@_get_arg_spec:NTF #1 { } { \@@_get_arg_spec_error:N #1 } } \cs_new_protected:Npn \@@_get_arg_spec:n #1 { - \prop_get:NnNF \l_@@_environment_arg_specs_prop {#1} - \ArgumentSpecification + \exp_args:Nc \@@_get_arg_spec:NTF + { environment~ \tl_to_str:n {#1} } + { } { \@@_get_arg_spec_error:n {#1} } } \tl_new:N \ArgumentSpecification @@ -3247,15 +3724,14 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_show_arg_spec:N #1 { - \prop_get:NnNTF \l_@@_command_arg_specs_prop {#1} - \ArgumentSpecification + \@@_get_arg_spec:NTF #1 { \tl_show:N \ArgumentSpecification } { \@@_get_arg_spec_error:N #1 } } \cs_new_protected:Npn \@@_show_arg_spec:n #1 { - \prop_get:NnNTF \l_@@_environment_arg_specs_prop {#1} - \ArgumentSpecification + \exp_args:Nc \@@_get_arg_spec:NTF + { environment~ \tl_to_str:n {#1} } { \tl_show:N \ArgumentSpecification } { \@@_get_arg_spec_error:n {#1} } } @@ -3342,12 +3818,74 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_tl_mapthread_function:NNN, \@@_tl_mapthread_function:nnN} +% \begin{macro}[aux]{\@@_tl_mapthread_loop:w} +% Analogue of \cs{seq_mapthread_function:NNN} for token lists. +% \begin{macrocode} +\cs_new:Npn \@@_tl_mapthread_function:NNN #1#2#3 + { + \exp_after:wN \exp_after:wN + \exp_after:wN \@@_tl_mapthread_loop:w + \exp_after:wN \exp_after:wN + \exp_after:wN #3 + \exp_after:wN #1 + \exp_after:wN \q_recursion_tail + \exp_after:wN \q_mark + #2 + \q_recursion_tail + \q_recursion_stop + } +\cs_new:Npn \@@_tl_mapthread_function:nnN #1#2#3 + { + \@@_tl_mapthread_loop:w #3 + #1 \q_recursion_tail \q_mark + #2 \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \@@_tl_mapthread_loop:w #1#2#3 \q_mark #4 + { + \quark_if_recursion_tail_stop:n {#2} + \quark_if_recursion_tail_stop:n {#4} + #1 {#2} {#4} + \@@_tl_mapthread_loop:w #1#3 \q_mark + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_cmd_if_xparse:NTF} +% \begin{macro}[aux]{\@@_cmd_if_xparse_aux:N} +% To determine whether the command is an \pkg{xparse} command check +% 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:nNNNn} +% (expandable command). +% \begin{macrocode} +\cs_new_protected:Npn \@@_cmd_if_xparse:NTF #1 + { + \exp_args:Nf \str_case_x:nnTF + { + \exp_args:Nf \tl_if_empty:nT { \token_get_arg_spec:N #1 } + { + \exp_last_unbraced:Nf \@@_cmd_if_xparse_aux:w + { \token_get_replacement_spec:N #1 } ~ \q_stop + } + } + { + { \token_to_str:N \@@_start:nNNnnn } { } + { \token_to_str:N \@@_start_expandable:nNNNn } { } + } + } +\cs_new:Npn \@@_cmd_if_xparse_aux:w #1 ~ #2 \q_stop {#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Messages} % % Some messages intended as errors. % \begin{macrocode} \__msg_kernel_new:nnnn { xparse } { bad-arg-spec } - { Bad~argument~specification~'#1'. } + { Bad~argument~specification~'#2'~for~command~'#1'. } { \c__msg_coding_error_text_tl The~argument~specification~provided~was~not~valid:~ @@ -3384,7 +3922,8 @@ } \__msg_kernel_new:nnnn { xparse } { expandable-ending-optional } { - Argument~specification~for~expandable~command~ends~with~optional~argument. + Argument~specification~'#2'~for~expandable~command~'#1'~ + ends~with~optional~argument. } { \c__msg_coding_error_text_tl @@ -3393,27 +3932,33 @@ argument~with~expandable~commands. } \__msg_kernel_new:nnnn { xparse } { inconsistent-long } - { Inconsistent~long~arguments~for~expandable~command. } + { Inconsistent~long~arguments~for~expandable~command~'#1'. } { \c__msg_coding_error_text_tl The~arguments~for~an~expandable~command~must~either~all~be~ short~or~all~be~long.~You~have~tried~to~mix~the~two~types. } \__msg_kernel_new:nnnn { xparse } { invalid-expandable-argument-type } - { Argument~type~'#1'~not~available~for~an~expandable~function. } + { Argument~type~'#2'~not~available~for~expandable~command~'#1'. } { \c__msg_coding_error_text_tl - The~letter~'#1'~does~not~specify~an~argument~type~which~can~be~used~ - in~an~expandable~function. + The~letter~'#2'~does~not~specify~an~argument~type~which~can~be~used~ + in~an~expandable~command. \\ \\ - LaTeX~will~assume~you~want~a~standard~mandatory~argument~(type~'m'). + LaTeX~will~ignore~this~entire~definition. + } +\__msg_kernel_new:nnnn { xparse } { loop-in-defaults } + { Circular~dependency~in~defaults~of~'#1'. } + { + \c__msg_coding_error_text_tl + The~default~values~of~two~or~more~arguments~of~'#1'~depend~on~each~ + other~in~a~way~that~cannot~be~resolved. } \__msg_kernel_new:nnnn { xparse } { missing-required } - { Failed~to~find~required~argument~starting~with~'#1'. } + { Failed~to~find~required~argument~starting~with~'#2'~for~command~'#1'. } { - There~is~supposed~to~be~an~argument~to~the~current~function~starting~with~ - '#1'.~LaTeX~did~not~find~it,~and~will~insert~'#2'~as~the~value~to~be~ - processed. + The~current~command~'#1'~expects~an~argument~starting~with~'#2'.~ + LaTeX~did~not~find~it,~and~will~insert~a~default~value~to~be~processed. } \__msg_kernel_new:nnnn { xparse } { non-xparse-command } { Command~'#1'~not~defined~using~xparse. } @@ -3448,19 +3993,20 @@ LaTeX~will~ignore~this~entire~definition. } \__msg_kernel_new:nnnn { xparse } { not-single-token } - { Argument~delimiter~should~be~a~single~token:~'#1'. } + { Argument~delimiter~'#2'~for~the~command~'#1'~should~be~a~single~token. } { \c__msg_coding_error_text_tl The~argument~specification~provided~was~not~valid:~ - in~a~place~where~a~single~token~is~required,~LaTeX~found~'#1'. \\ \\ + in~a~place~where~a~single~token~is~required,~LaTeX~found~'#2'. \\ \\ LaTeX~will~ignore~this~entire~definition. } \__msg_kernel_new:nnnn { xparse } { processor-in-expandable } - { Argument~processors~cannot~be~used~with~expandable~functions. } + { Argument~processor~'>{#2}'~cannot~be~used~for~the~expandable~command~'#1'. } { \c__msg_coding_error_text_tl The~argument~specification~for~#1~contains~a~processor~function:~ - this~is~only~supported~for~standard~robust~functions. + this~is~only~supported~for~standard~robust~commands. \\ \\ + LaTeX~will~ignore~this~entire~definition. } \__msg_kernel_new:nnnn { xparse } { split-excess-tokens } { Too~many~'#1'~tokens~when~trying~to~split~argument. } @@ -3469,12 +4015,20 @@ at~each~occurrence~of~the~token~'#1',~up~to~a~maximum~of~#2~parts.~ There~were~too~many~'#1'~tokens. } +\__msg_kernel_new:nnnn { xparse } { too-many-arguments } + { Too~many~arguments~in~argument~specification~'#2'~of~command~'#1'. } + { + \c__msg_coding_error_text_tl + The~argument~specification~provided~has~more~than~9~arguments.~ + This~cannot~be~implemented. \\ \\ + LaTeX~will~ignore~this~entire~definition. + } \__msg_kernel_new:nnnn { xparse } { unknown-argument-type } - { Unknown~argument~type~'#1'~replaced~by~'m'. } + { Unknown~argument~type~'#2'~for~the~command~'#1'. } { \c__msg_coding_error_text_tl - The~letter~'#1'~does~not~specify~a~known~argument~type.~ - LaTeX~will~assume~you~want~a~standard~mandatory~argument~(type~'m'). + The~letter~'#2'~does~not~specify~a~known~argument~type.~ + LaTeX~will~ignore~this~entire~definition. } \__msg_kernel_new:nnnn { xparse } { unknown-command } { Unknown~document~command~'#1'. } @@ -3533,6 +4087,12 @@ Redefining~environment~'#1'~ with~sig.~'#2'~\msg_line_context:. } +\__msg_kernel_new:nnn { xparse } { optional-mandatory } + { + Since~the~mandatory~argument~'#1'~has~the~same~delimiter~'#2'~ + as~a~previous~optional~argument,~it~will~not~be~possible~to~ + omit~all~optional~arguments~when~calling~this~command. + } % \end{macrocode} % % \subsection{User functions} diff --git a/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx b/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx index 31a5c72bffd..430b5d9490e 100644 --- a/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx @@ -27,8 +27,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/02/07] -%\@ifpackagelater{expl3}{2017/02/07} +\RequirePackage{expl3}[2017/02/10] +%\@ifpackagelater{expl3}{2017/02/10} % {} % {% % \PackageError{xtemplate}{Support package l3kernel too old} @@ -42,8 +42,8 @@ % } \def\ExplFileName{xtemplate} \def\ExplFileDescription{L3 Experimental prototype document functions} -\def\ExplFileDate{2017/02/07} -\def\ExplFileVersion{6846} +\def\ExplFileDate{2017/02/10} +\def\ExplFileVersion{6878} % %<*driver> \documentclass[full]{l3doc} -- cgit v1.2.3