summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3packages
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-03-04 03:02:32 +0000
committerNorbert Preining <norbert@preining.info>2020-03-04 03:02:32 +0000
commit19d25b8009801aa98ea2f46b45c37c257f990491 (patch)
treec0da70fbab26feff40e87df289ae797917df8419 /macros/latex/contrib/l3packages
parentb78f5a6705512314d6fe42fd5144c5f8e5d484ce (diff)
CTAN sync 202003040302
Diffstat (limited to 'macros/latex/contrib/l3packages')
-rw-r--r--macros/latex/contrib/l3packages/CHANGELOG.md9
-rw-r--r--macros/latex/contrib/l3packages/README.md2
-rw-r--r--macros/latex/contrib/l3packages/l3keys2e.dtx4
-rw-r--r--macros/latex/contrib/l3packages/l3keys2e.pdfbin347493 -> 347184 bytes
-rw-r--r--macros/latex/contrib/l3packages/xfp.dtx4
-rw-r--r--macros/latex/contrib/l3packages/xfp.pdfbin309855 -> 309529 bytes
-rw-r--r--macros/latex/contrib/l3packages/xfrac.dtx4
-rw-r--r--macros/latex/contrib/l3packages/xfrac.pdfbin454275 -> 480943 bytes
-rw-r--r--macros/latex/contrib/l3packages/xparse.dtx282
-rw-r--r--macros/latex/contrib/l3packages/xparse.pdfbin501940 -> 505523 bytes
-rw-r--r--macros/latex/contrib/l3packages/xtemplate.dtx4
-rw-r--r--macros/latex/contrib/l3packages/xtemplate.pdfbin416360 -> 416042 bytes
12 files changed, 248 insertions, 61 deletions
diff --git a/macros/latex/contrib/l3packages/CHANGELOG.md b/macros/latex/contrib/l3packages/CHANGELOG.md
index 2a56ece1a1..9b92b84018 100644
--- a/macros/latex/contrib/l3packages/CHANGELOG.md
+++ b/macros/latex/contrib/l3packages/CHANGELOG.md
@@ -7,6 +7,12 @@ this project uses date-based 'snapshot' version identifiers.
## [Unreleased]
+## [2020-03-03]
+
+### Changed
+- Delimited arguments (`DdRrEet`) now allow control sequence tokens
+ as delimiters (issues #367 and #368)
+
## [2020-02-25]
### Changed
@@ -81,7 +87,8 @@ this project uses date-based 'snapshot' version identifiers.
- Switch to ISO date format
- Improve cross-module use of internal functions
-[Unreleased]: https://github.com/latex3/latex3/compare/2020-02-25...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2020-03-03...HEAD
+[2020-03-03]: https://github.com/latex3/latex3/compare/2020-02-25...2020-03-03
[2020-02-25]: https://github.com/latex3/latex3/compare/2020-02-14...2020-02-25
[2020-02-14]: https://github.com/latex3/latex3/compare/2020-02-08...2020-02-14
[2020-02-08]: https://github.com/latex3/latex3/compare/2020-02-03...2020-02-08
diff --git a/macros/latex/contrib/l3packages/README.md b/macros/latex/contrib/l3packages/README.md
index b7712552ba..60647bde63 100644
--- a/macros/latex/contrib/l3packages/README.md
+++ b/macros/latex/contrib/l3packages/README.md
@@ -1,7 +1,7 @@
LaTeX3 High-Level Concepts
==========================
-Release 2020-02-25
+Release 2020-03-03
Overview
--------
diff --git a/macros/latex/contrib/l3packages/l3keys2e.dtx b/macros/latex/contrib/l3packages/l3keys2e.dtx
index 2022b0ac00..3b648b7bdd 100644
--- a/macros/latex/contrib/l3packages/l3keys2e.dtx
+++ b/macros/latex/contrib/l3packages/l3keys2e.dtx
@@ -62,7 +62,7 @@
% }^^A
% }
%
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
%
% \maketitle
%
@@ -139,7 +139,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3keys2e}{2020-02-25}{}
+\ProvidesExplPackage{l3keys2e}{2020-03-03}{}
{LaTeX2e option processing using LaTeX3 keys}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3packages/l3keys2e.pdf b/macros/latex/contrib/l3packages/l3keys2e.pdf
index ac7a187f8e..2a1c8fedbd 100644
--- a/macros/latex/contrib/l3packages/l3keys2e.pdf
+++ b/macros/latex/contrib/l3packages/l3keys2e.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3packages/xfp.dtx b/macros/latex/contrib/l3packages/xfp.dtx
index 6bd7eb53b2..023e0e2ed5 100644
--- a/macros/latex/contrib/l3packages/xfp.dtx
+++ b/macros/latex/contrib/l3packages/xfp.dtx
@@ -64,7 +64,7 @@
% }^^A
% }
%
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
%
% \maketitle
%
@@ -167,7 +167,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xfp}{2020-02-25}{}
+\ProvidesExplPackage{xfp}{2020-03-03}{}
{L3 Floating point unit}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3packages/xfp.pdf b/macros/latex/contrib/l3packages/xfp.pdf
index 74dc6b73c3..e5896aa5e8 100644
--- a/macros/latex/contrib/l3packages/xfp.pdf
+++ b/macros/latex/contrib/l3packages/xfp.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3packages/xfrac.dtx b/macros/latex/contrib/l3packages/xfrac.dtx
index 287c27a744..abbce7d8d1 100644
--- a/macros/latex/contrib/l3packages/xfrac.dtx
+++ b/macros/latex/contrib/l3packages/xfrac.dtx
@@ -65,7 +65,7 @@
% }^^A
% }
%
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
%
% \maketitle
%
@@ -535,7 +535,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xfrac}{2020-02-25}{}
+\ProvidesExplPackage{xfrac}{2020-03-03}{}
{L3 Experimental split-level fractions}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3packages/xfrac.pdf b/macros/latex/contrib/l3packages/xfrac.pdf
index 4031e6c18e..4c26aa4286 100644
--- a/macros/latex/contrib/l3packages/xfrac.pdf
+++ b/macros/latex/contrib/l3packages/xfrac.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3packages/xparse.dtx b/macros/latex/contrib/l3packages/xparse.dtx
index fc0164a8cd..279b2e58c0 100644
--- a/macros/latex/contrib/l3packages/xparse.dtx
+++ b/macros/latex/contrib/l3packages/xparse.dtx
@@ -67,7 +67,7 @@
% }^^A
% }
%
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
%
% \maketitle
%
@@ -130,12 +130,12 @@
% Regardless of the input, the argument will be passed to the
% internal code without the outer braces. This is the \pkg{xparse}
% type specifier for a normal \TeX{} argument.
-% \item[r] Given as \texttt{r}\meta{char1}\meta{char2}, this denotes a
+% \item[r] Given as \texttt{r}\meta{token1}\meta{token2}, this denotes a
% \enquote{required} delimited argument, where the delimiters are
-% \meta{char1} and \meta{char2}. If the opening delimiter
-% \meta{char1} is missing, the default marker |-NoValue-| will be
+% \meta{token1} and \meta{token2}. If the opening delimiter
+% \meta{token1} is missing, the default marker |-NoValue-| will be
% inserted after a suitable error.
-% \item[R] Given as \texttt{R}\meta{char1}\meta{char2}\marg{default},
+% \item[R] Given as \texttt{R}\meta{token1}\meta{token2}\marg{default},
% this is a \enquote{required} delimited argument as for~\texttt{r},
% but it has a user-definable recovery \meta{default} instead of
% |-NoValue-|.
@@ -158,30 +158,30 @@
% \item[o] A standard \LaTeX{} optional argument, surrounded with square
% brackets, which will supply
% the special |-NoValue-| marker if not given (as described later).
-% \item[d] Given as \texttt{d}\meta{char1}\meta{char2}, an optional
-% argument which is delimited by \meta{char1} and \meta{char2}.
+% \item[d] Given as \texttt{d}\meta{token1}\meta{token2}, an optional
+% argument which is delimited by \meta{token1} and \meta{token2}.
% As with \texttt{o}, if no
% value is given the special marker |-NoValue-| is returned.
% \item[O] Given as \texttt{O}\marg{default}, is like \texttt{o}, but
% returns \meta{default} if no value is given.
-% \item[D] Given as \texttt{D}\meta{char1}\meta{char2}\marg{default},
+% \item[D] Given as \texttt{D}\meta{token1}\meta{token2}\marg{default},
% it is as for \texttt{d}, but returns \meta{default} if no value is given.
% Internally, the \texttt{o}, \texttt{d} and \texttt{O} types are
% short-cuts to an appropriated-constructed \texttt{D} type argument.
% \item[s] An optional star, which will result in a value
% \cs{BooleanTrue} if a star is present and \cs{BooleanFalse}
% otherwise (as described later).
-% \item[t] An optional \meta{char}, which will result in a value
-% \cs{BooleanTrue} if \meta{char} is present and \cs{BooleanFalse}
-% otherwise. Given as \texttt{t}\meta{char}.
-% \item[e] Given as \texttt{e}\marg{chars}, a set of optional
+% \item[t] An optional \meta{token}, which will result in a value
+% \cs{BooleanTrue} if \meta{token} is present and \cs{BooleanFalse}
+% otherwise. Given as \texttt{t}\meta{token}.
+% \item[e] Given as \texttt{e}\marg{tokens}, a set of optional
% \emph{embellishments}, each of which requires a \emph{value}.
% If an embellishment is not present, |-NoValue-| is returned. Each
% embellishment gives one argument, ordered as for the list of
-% \meta{chars} in the argument specification. All \meta{chars}
+% \meta{tokens} in the argument specification. All \meta{tokens}
% must be distinct. \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{chars}\marg{defaults}. See
+% if values are not given: \texttt{E}\marg{tokens}\marg{defaults}. See
% Section~\ref{sec:embellishment} for more details.
% \end{itemize}
%
@@ -213,7 +213,9 @@
% \foo[[] % Error: missing closing "]"
% \end{verbatim}
% Also note that |{| and |}| cannot be used as delimiters as they are used
-% by \TeX{} as grouping tokens. Arguments to be grabbed inside these tokens
+% by \TeX{} as grouping tokens. Implicit begin- or end-group tokens (\emph{e.g.},
+% |\bgroup| and |\egroup|) are not allowed for delimited argument tipes.
+% Arguments to be grabbed inside these tokens
% must be created as either \texttt{m}- or \texttt{g}-type arguments.
%
% Within delimited arguments, non-balanced or otherwise awkward tokens may
@@ -371,13 +373,13 @@
% \subsection{Default values for \enquote{embellishments}}
% \label{sec:embellishment}
%
-% The \texttt{E}-type argument allows one default value per test character.
+% 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 characters,
+% If the list of default values is \emph{shorter} than the list of test tokens,
% the special |-NoValue-| marker will be returned (as for the \texttt{e}-type
% argument). Thus for example
% \begin{verbatim}
@@ -487,6 +489,66 @@
% is given: \texttt{G}\marg{default}.
% \end{itemize}
%
+% \subsection{Details about argument delimiters}
+%
+% In normal (non-expandable) commands, the delimited types look for the
+% initial delimiter by peeking ahead (using \pkg{expl3}'s |\peek_...|
+% functions) looking for the delimiter token. The token has to have the
+% same meaning and \enquote{shape} of the token defined as delimiter.
+% There are three possible cases of delimiters: character tokens, control
+% sequence tokens, and active character tokens. For all practical purposes
+% of this description, active character tokens will behave exactly as
+% control sequence tokens.
+%
+% \subsubsection{Character tokens}
+%
+% A character token is characterised by its character code, and its meaning
+% is the category code~(|\catcode|). When a command is defined, the meaning
+% of the character token is fixed into the definition of the command and
+% cannot change. A command will correctly see an argument delimiter if
+% the open delimiter has the same character and category codes as at the
+% time of the definition. For example in:
+% \begin{verbatim}
+% \NewDocumentCommand { \foobar } { D<>{default} } {(#1)}
+% \foobar <hello> \par
+% \char_set_catcode_letter:N <
+% \foobar <hello>
+% \end{verbatim}
+% the output would be:
+% \begin{verbatim}
+% (hello)
+% (default)<hello>
+% \end{verbatim}
+% as the open-delimter |<| changed in meaning between the two calls to
+% |\foobar|, so the second one doesn't see the |<| as a valid delimiter.
+% Commands assume that if a valid open-delimiter was found, a matching
+% close-delimiter will also be there. If it is not (either by being
+% omitted or by changing in meaning), a low-level \TeX{} error is raised
+% and the command call is aborted.
+%
+% \subsubsection{Control sequence tokens}
+%
+% A control sequence (or control character) token is characterised by is
+% its name, and its meaning is its definition.
+% A token cannot have two different meanings at the same time.
+% When a control sequence is defined as delimiter in a command,
+% it will be detected as delimiter whenever the control sequence name
+% is found in the document regardless of its current definition.
+% For example in:
+% \begin{verbatim}
+% \cs_set:Npn \x { abc }
+% \NewDocumentCommand { \foobar } { D\x\y{default} } {(#1)}
+% \foobar \x hello\y \par
+% \cs_set:Npn \x { def }
+% \foobar \x hello\y
+% \end{verbatim}
+% the output would be:
+% \begin{verbatim}
+% (hello)
+% (hello)
+% \end{verbatim}
+% with both calls to the command seeing the delimiter |\x|.
+%
% \section{Declaring commands and environments}
%
% With the concept of an argument specifier defined, it is now
@@ -916,7 +978,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xparse}{2020-02-25}{}
+\ProvidesExplPackage{xparse}{2020-03-03}{}
{L3 Experimental document command parser}
% \end{macrocode}
%
@@ -1906,8 +1968,8 @@
\cs_new_protected:Npn \@@_normalize_type_D:w #1#2#3
{
\quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
- \@@_single_char_check:n {#1}
- \@@_single_char_check:n {#2}
+ \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
+ \@@_single_token_check:n {#2}
\@@_add_arg_spec:n { D #1 #2 {#3} }
\tl_put_right:Nn \l_@@_last_delimiters_tl {#1}
\bool_set_false:N \l_@@_grab_expandably_bool
@@ -1917,7 +1979,8 @@
{
\quark_if_recursion_tail_stop_do:nn {#2} { \@@_bad_arg_spec:wn }
\tl_if_blank:nT {#1} { \@@_bad_arg_spec:wn }
- \tl_map_function:nN {#1} \@@_single_char_check:n
+ \tl_map_function:nN {#1} \@@_single_token_check:n
+ \tl_map_function:nN {#1} \@@_allowed_token_check:N
\@@_normalize_E_unique_check:w #1 \q_nil \q_stop
\int_compare:nNnT { \tl_count:n {#2} } > { \tl_count:n {#1} }
{ \@@_bad_arg_spec:wn }
@@ -1946,7 +2009,7 @@
\cs_new_protected:Npn \@@_normalize_type_t:w #1
{
\quark_if_recursion_tail_stop_do:Nn #1 { \@@_bad_arg_spec:wn }
- \@@_single_char_check:n {#1}
+ \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
\tl_put_right:Nx \l_@@_arg_spec_tl
{
\bool_if:NT \l_@@_obey_spaces_bool { ! }
@@ -1994,8 +2057,8 @@
\cs_new_protected:Npn \@@_normalize_type_R:w #1#2#3
{
\quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
- \@@_single_char_check:n {#1}
- \@@_single_char_check:n {#2}
+ \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
+ \@@_single_token_check:n {#2}
\@@_delimiter_check:nnn {#1} { R/r } { \tl_to_str:n {#1} }
\bool_set_false:N \l_@@_grab_expandably_bool
\@@_add_arg_spec_mandatory:n { R #1 #2 {#3} }
@@ -2042,27 +2105,53 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@@_single_char_check:n}
-% Checks that what should be single characters really are single
-% characters (possibly surrounded by spaces).
+% \begin{macro}{\@@_single_token_check:n}
+% Checks that the argument is a single (non-space) token (possibly
+% surrounded by spaces), and aborts the definition otherwise.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_single_char_check:n #1
+\cs_new_protected:Npn \@@_single_token_check:n #1
{
- \tl_trim_spaces_apply:nN {#1} \tl_if_single_token:nTF
+ \tl_trim_spaces_apply:nN {#1} \tl_if_single_token:nF
{
- \group_begin:
- \tex_escapechar:D = 92 \scan_stop:
- \exp_args:Nx \tl_if_single_token:nF
- { \exp_args:No \tl_to_str:n { \use:nn #1 { } } }
- {
- \__kernel_msg_warning:nnxx { xparse } { not-single-char }
- { \@@_environment_or_command: } { \tl_to_str:n {#1} }
- }
- \group_end:
+ \__kernel_msg_error:nnxx { xparse } { not-single-token }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_allowed_token_check:N}
+% Some tokens are now allowed as delimiters for some argument types,
+% notably implicit begin/end-group tokens (|\bgroup|/|\egroup|).
+% The major problem with these tokens is that for |\peek_...| functions,
+% a literal~|{|$_1$. is virtually indistinguishable from a |\bgroup| or
+% other token which was |\let| to a~|{|$_1$, and the same goes
+% for~|}|$_2$. All other tokens can be easily distingushed from their
+% implicit counterparts by grabbing them and looking at the string
+% length (see \cs{@@_token_if_cs:NTF}), but for begin/end group tokens
+% that is not possible without the risk of mistakenly grabbing the
+% entire brace group (potentially leading to a~\texttt{!~Runaway argument}
+% error) or trying to grab a |}|$_2$, leading to a~\texttt{!~Argument
+% of~\dots~has an extra~|}|}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_allowed_token_check:N #1
+ {
+ \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+ { \use:n }
+ {
+ \token_if_eq_meaning:NNTF #1 \c_group_end_token
+ { \use:n }
+ { \use_none:n }
+ }
{
- \__kernel_msg_error:nnxx { xparse } { not-single-char }
+ \__kernel_msg_error:nnxxx
+ { xparse } { forbidden-implicit-group-token }
{ \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ {
+ \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+ { begin } { end }
+ }
\@@_bad_def:wn
}
}
@@ -2853,12 +2942,12 @@
\cs_new_protected:Npn \@@_grab_D_obey_spaces:w #1#2#3 \@@_run_code:
{
\@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected_nopar:Npn
- \peek_meaning_remove:NTF
+ \@@_peek_meaning_remove:NTF
}
\cs_new_protected:Npn \@@_grab_D_long_obey_spaces:w #1#2#3 \@@_run_code:
{
\@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected:Npn
- \peek_meaning_remove:NTF
+ \@@_peek_meaning_remove:NTF
}
% \end{macrocode}
% \begin{macro}{\@@_grab_D_aux:NNnNN}
@@ -2991,6 +3080,12 @@
% 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.)
+% An exception is when |#1| is a control sequence token, in which case the
+% character-token treatment is no good because if hit with \cs{token_to_str:N}
+% it would add sputios tokens to the argument. In this case a different
+% branch is taken. The token inserted is then the same \meta{csname} as |#1|,
+% but with a space appended, so that the grabber don't see it as another
+% of the same delimiter.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_grab_D_call:Nw #1
{
@@ -3000,8 +3095,15 @@
\l_@@_fn_tl \char_generate:nn { `#1 } { 11 }
}
{
- \exp_after:wN \l_@@_fn_tl
- \token_to_str:N #1
+ \@@_token_if_cs:NTF #1
+ {
+ \exp_after:wN \l_@@_fn_tl
+ \cs:w \cs_to_str:N #1 ~ \cs_end:
+ }
+ {
+ \exp_after:wN \l_@@_fn_tl
+ \token_to_str:N #1
+ }
}
}
% \end{macrocode}
@@ -3033,13 +3135,13 @@
{
\@@_grab_E:nnNN {#1} {#2}
\cs_set_protected_nopar:Npn
- \peek_meaning_remove:NTF
+ \@@_peek_meaning_remove:NTF
}
\cs_new_protected:Npn \@@_grab_E_long_obey_spaces:w #1#2 \@@_run_code:
{
\@@_grab_E:nnNN {#1} {#2}
\cs_set_protected:Npn
- \peek_meaning_remove:NTF
+ \@@_peek_meaning_remove:NTF
}
% \end{macrocode}
% A loop is needed here to allow a random ordering of keys. These are
@@ -3294,7 +3396,7 @@
\cs_new_protected:Npn \@@_grab_t:w
{ \@@_grab_t_aux:NNw \@@_peek_nonspace_remove:NTF }
\cs_new_protected:Npn \@@_grab_t_obey_spaces:w
- { \@@_grab_t_aux:NNw \peek_meaning_remove:NTF }
+ { \@@_grab_t_aux:NNw \@@_peek_meaning_remove:NTF }
\cs_new_protected:Npn \@@_grab_t_aux:NNw #1#2#3 \@@_run_code:
{
\tl_set:Nn \l_@@_signature_tl {#3}
@@ -4282,6 +4384,28 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_token_if_cs:NTF}
+% Based on the definition of \cs{@@_check_definable_aux:nN} above, but
+% only checks for an actual control sequence (\emph{i.e.},
+% \cs[no-index]{\meta{anything}}). \cs{tex_escapechar:D} is
+% temporarily changed to a known value and then it checks if
+% |\string#1| contains more than one character: if it does, it's a
+% control sequence. This test differs from \cs{token_if_cs:NTF} for
+% example in \verb|\token_if_cs:NTF \c_group_begin_token {T}{F}|,
+% where \cs{token_if_cs:NTF} returns false.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_token_if_cs:NTF #1
+ {
+ \group_begin:
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \exp_args:Nx \tl_if_empty:nTF
+ { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
+ { \group_end: \use_ii:nn }
+ { \group_end: \use_i:nn }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_tl_mapthread_function:NNN, \@@_tl_mapthread_function:nnN}
% \begin{macro}{\@@_tl_mapthread_loop:w}
% Analogue of \cs{seq_mapthread_function:NNN} for token lists.
@@ -4351,9 +4475,9 @@
% \cs{peek_meaning_remove:NTF}.
% \begin{macrocode}
\cs_new_protected:Npn \@@_peek_nonspace:NTF
- { \@@_peek_nonspace_aux:nNNTF { } \peek_meaning:NTF }
+ { \@@_peek_nonspace_aux:nNNTF { } \@@_peek_meaning:NTF }
\cs_new_protected:Npn \@@_peek_nonspace_remove:NTF
- { \@@_peek_nonspace_aux:nNNTF { } \peek_meaning_remove:NTF }
+ { \@@_peek_nonspace_aux:nNNTF { } \@@_peek_meaning_remove:NTF }
\cs_new_protected:Npn \@@_peek_nonspace_aux:nNNTF #1#2#3#4#5
{
\peek_meaning_remove:NTF \c_space_token
@@ -4363,6 +4487,55 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_peek_meaning:NTF, \@@_peek_meaning_remove:NTF}
+% \begin{macro}{\@@_peek_cs_check_equal:NNN, \@@_peek_meaning_aux:NNTF, \@@_peek_true_remove:NNw}
+% Peek ahead for a token with a given meaning. In case the search
+% token is a control sequence, also check that the \meta{csname} is
+% the same as the control sequence peeked at. This extra verification
+% is necessary when the command is delimited by control sequence tokens
+% (as opposed to character tokens), and we want the the exact same
+% control sequence to match.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_peek_meaning:NTF
+ { \@@_peek_meaning_aux:NNTF \c_false_bool }
+\cs_new_protected:Npn \@@_peek_meaning_remove:NTF
+ { \@@_peek_meaning_aux:NNTF \c_true_bool }
+\cs_new_protected:Npn \@@_peek_meaning_aux:NNTF #1#2#3#4
+ {
+ \tl_set:Nn \l_@@_tmpa_tl {#3}
+ \tl_set:Nn \l_@@_tmpb_tl {#4}
+ \peek_meaning:NTF #2
+ {
+ \token_if_eq_meaning:NNTF #2 \c_group_begin_token
+ { \@@_peek_true_remove:Nw #1 }
+ {
+ \@@_token_if_cs:NTF #2
+ { \@@_peek_cs_check_equal:NNN #1 #2 }
+ { \@@_peek_true_remove:Nw #1 }
+ }
+ }
+ { \l_@@_tmpb_tl }
+ }
+\cs_new_protected:Npn \@@_peek_cs_check_equal:NNN #1#2#3
+ {
+ \str_if_eq:nnTF {#2} {#3}
+ { \@@_peek_true_remove:Nw #1 }
+ { \l_@@_tmpb_tl }
+ #3
+ }
+\cs_new_protected:Npn \@@_peek_true_remove:Nw #1
+ {
+ \bool_if:NTF #1
+ {
+ \tex_afterassignment:D \l_@@_tmpa_tl
+ \cs_set_eq:NN \@@_tmp:w
+ }
+ { \l_@@_tmpa_tl }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Messages}
%
% \begin{macro}{\@@_environment_or_command:}
@@ -4493,14 +4666,21 @@
token.~Perhaps~a~backslash~is~missing?
\c_@@_ignore_def_tl
}
-\__kernel_msg_new:nnnn { xparse } { not-single-char }
+\__kernel_msg_new:nnnn { xparse } { not-single-token }
{
Argument~delimiter~'#2'~for~the~#1~should~be~
- a~single~character.
+ a~single~non-space~token.
}
{
The~argument~specification~provided~was~not~valid:~in~a~place~
- where~a~single~character~is~required,~LaTeX~found~'#2'.
+ where~a~single~token~is~required,~LaTeX~found~'#2'.
+ \c_@@_ignore_def_tl
+ }
+\__kernel_msg_new:nnnn { xparse } { forbidden-implicit-group-token }
+ { Argument~delimiter~'#2'~for~the~#1~is~not~allowed. }
+ {
+ The~argument~specification~provided~was~not~valid:~the~implicit~
+ #3-group~token~'#2'~is~not~allowed~as~an~argument~delimiter.
\c_@@_ignore_def_tl
}
\__kernel_msg_new:nnnn { xparse } { processor-in-expandable }
diff --git a/macros/latex/contrib/l3packages/xparse.pdf b/macros/latex/contrib/l3packages/xparse.pdf
index b9bf02a381..98e62db0e1 100644
--- a/macros/latex/contrib/l3packages/xparse.pdf
+++ b/macros/latex/contrib/l3packages/xparse.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3packages/xtemplate.dtx b/macros/latex/contrib/l3packages/xtemplate.dtx
index 9a10fbca81..d0ced34962 100644
--- a/macros/latex/contrib/l3packages/xtemplate.dtx
+++ b/macros/latex/contrib/l3packages/xtemplate.dtx
@@ -63,7 +63,7 @@
% }^^A
% }
%
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
%
% \maketitle
%
@@ -682,7 +682,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xtemplate}{2020-02-25}{}
+\ProvidesExplPackage{xtemplate}{2020-03-03}{}
{L3 Experimental prototype document functions}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3packages/xtemplate.pdf b/macros/latex/contrib/l3packages/xtemplate.pdf
index 40f55ded1a..20ae5c9d3f 100644
--- a/macros/latex/contrib/l3packages/xtemplate.pdf
+++ b/macros/latex/contrib/l3packages/xtemplate.pdf
Binary files differ