[latex3-commits] [git/LaTeX3-latex3-latex2e] gh569: Move code a couple of sections below (82907a05)

PhelypeOleinik phelype.oleinik at latex-project.org
Mon Aug 9 04:46:03 CEST 2021


Repository : https://github.com/latex3/latex2e
On branch  : gh569
Link       : https://github.com/latex3/latex2e/commit/82907a05b776758cfa02207d9f428661ac2edfda

>---------------------------------------------------------------

commit 82907a05b776758cfa02207d9f428661ac2edfda
Author: PhelypeOleinik <phelype.oleinik at latex-project.org>
Date:   Sun Aug 8 23:46:03 2021 -0300

    Move code a couple of sections below


>---------------------------------------------------------------

82907a05b776758cfa02207d9f428661ac2edfda
 base/ltcmd.dtx | 1038 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 519 insertions(+), 519 deletions(-)

diff --git a/base/ltcmd.dtx b/base/ltcmd.dtx
index cdec69ee..c3c04378 100644
--- a/base/ltcmd.dtx
+++ b/base/ltcmd.dtx
@@ -856,282 +856,6 @@
 % \end{macro}
 % \end{macro}
 %
-% \subsubsection{Copying a command and its internal structure}
-%
-%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_copy:NN}%
-%<latexrelease>  {Support \NewCommandCopy and \ShowCommand in ltcmd}
-% Since the 2020-10-01 \LaTeXe{} release, support for copying and
-% showing the definition of robust commands is available, but the
-% specifics of each command is implemented separately.  Here we'll add
-% support for copying and showing \pkg{ltcmd} definitions.
-%
-% To fully support copying, we need two commands:  a conditional to test
-% if a command is in fact an \pkg{ltcmd} command, and another to
-% actually copy the command.  The conditional is defined later as
-% \cs{__kernel_cmd_if_xparse:NTF}, so now to the copying:
-%
-% \begin{macro}{\@@_copy:NN}
-% \begin{macro}{\@@_set_eq_if_exist:NN,\@@_set_eq_if_exist:cc}
-%   This macro just branches to the proper copying command by using
-%   \cs{@@_cmd_type_cases:NnnnF}.  The copying command takes the names
-%   of the commands to be copied to and from, and the actual commands
-%   as its four arguments.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy:NN #1 #2
-  {
-    \use:x
-      {
-        \int_set:Nn \tex_escapechar:D { 92 }
-        \exp_not:N \@@_cmd_type_cases:NnnnF \exp_not:N #2
-          { \@@_copy_command:nnNN }
-          { \@@_copy_expandable:nnNN }
-          { \@@_copy_environment:nnNN }
-          { \@@_cant_copy:nwn { non-ltcmd } }
-            { \cs_to_str:N #1 } { \cs_to_str:N #2 }
-            \exp_not:N #1 \exp_not:N #2
-        \exp_not:N \@@_break_point:n { \cs_to_str:N #2 }
-        \int_set:Nn \tex_escapechar:D { \int_use:N \tex_escapechar:D }
-      }
-  }
-\cs_new_protected:Npn \@@_set_eq_if_exist:NN #1 #2
-  { \cs_if_exist:NTF #2 { \cs_set_eq:NN } { \use_none:nn } #1 #2 }
-\cs_generate_variant:Nn \@@_set_eq_if_exist:NN { cc }
-%    \end{macrocode}
-%
-% \begin{macro}{\@@_cant_copy:nwn}
-%   An utility macro similar to \cs{@@_bad_def:wn} to abort a command
-%   copy.  Contrary to \cs{@@_bad_def:wn} though, when this happens the
-%   issue is most likely internal, because the command was already
-%   (supposedly) correcly defined so it should be copyable.  Hopefully
-%   this macro will never be used ever, but if it does, apologise and
-%   give the reason for the failure so the user can report.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_cant_copy:nwn #1 #2 \@@_break_point:n #3
-  { \msg_error:nnnn { cmd } { copy-bug } {#1} {#3} }
-\msg_new:nnn { cmd } { copy-bug }
-  {
-    Internal~error~while~copying~command~\iow_char:N\\#2:\\
-    \str_case:nn {#1}
-      {
-        { non-ltcmd } { Command~is~not~a~valid~ltcmd~command. }
-        { unknown-type } { Found~an~unknown~argument~type. }
-      }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-%   And, of course, add \cs{__kernel_cmd_if_xparse:NTF} and
-%   \cs{@@_copy:NN} to \cs{@declarecommandcopylisthook}:
-%    \begin{macrocode}
-\tl_gput_right:Nn \@declarecommandcopylisthook
-  { { \__kernel_cmd_if_xparse:NTF \@@_copy:NN } }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_copy_command:nnNN,\@@_copy_command:NnNNnnnn}
-%   A normal (non-expandable) command has a pretty straightforward
-%   structure.  Its definition is stored in
-%   \cs{\meta{cmd}\textvisiblespace code}, its defaults (if any) are
-%   stored in \cs{\meta{cmd}\textvisiblespace defaults}, and its
-%   top-level definition contains its signature, which can just be
-%   copied over.  \cs{@@_copy_command:nnNN} copies the command code and
-%   defaults, and then defines the top-level command using the auxiliary
-%   \cs{@@_copy_command:NnNNnnnn}.  This macro takes the signature of
-%   the command being copied from its top-level definition, and replaces
-%   the named bits with the new name.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_command:nnNN #1 #2 #3 #4
-  {
-    \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
-    \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults }
-    \cs_set_protected_nopar:Npx #3
-      { \exp_after:wN \@@_copy_command:NnNNnnnn #4 {#1} }
-  }
-\cs_new:Npn \@@_copy_command:NnNNnnnn #1 #2 #3 #4 #5 #6 #7 #8
-  {
-    #1 \exp_not:n { {#2} }
-    \exp_not:c { #8 ~ } \exp_not:c { #8 ~ code }
-    \exp_not:n { {#5} {#6} {#7} }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_copy_expandable:nnNN,\@@_copy_expandable:NnNNNNnnn}
-%   An expandable command is slightly more complicated.  Besides the
-%   \cs{\meta{cmd}\textvisiblespace code}, and
-%   \cs{\meta{cmd}\textvisiblespace defaults}, it also has an auxiliary
-%   \cs{\meta{cmd}\textvisiblespace} for grabbing delimited arguments,
-%   and possibly another auxiliary
-%   \cs{\meta{cmd}\textvisiblespace\textvisiblespace}, if the command
-%   has both long and short arguments.  Then, its signature has also
-%   several specific bits that are unique to that command, contrary to
-%   non-expandable commands which use a common set of parsing functions.
-%
-%   We'll start by copying the basics, then call
-%   \cs{@@_copy_expandable_signature:NnNNNNnnn} to parse the signature
-%   of the command and make the modified copy in a temporary token list,
-%   then we call \cs{@@_copy_expandable:NnNNNNnnn} that will copy the
-%   top-level definition of the command, with the proper internal
-%   renames.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_expandable:nnNN #1 #2 #3 #4
-  {
-    \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
-    \@@_set_eq_if_exist:cc { #1 ~ } { #2 ~ }
-    \@@_set_eq_if_exist:cc { #1 ~ \c_space_tl } { #2 ~ \c_space_tl }
-    \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults }
-    \exp_after:wN \@@_copy_expandable_signature:NnNNNNnnn #4 {#1} {#2}
-    \cs_set_nopar:Npx #3
-      { \exp_after:wN \@@_copy_expandable:NnNNNNnnn #4 {#1} {#2} }
-  }
-\cs_new:Npn \@@_copy_expandable:NnNNNNnnn #1 #2 #3 #4 #5 #6 #7 #8 #9
-  {
-    \exp_not:N #1 \exp_not:n { {#2} }
-    \exp_not:c { #8 ~ }
-    \exp_not:c
-      {
-        #8 ~
-        \str_if_eq:eeT
-            { \exp_not:c { #9 ~ \c_space_tl } } { \exp_not:N #4 }
-          { \c_space_tl }
-      }
-    \exp_not:c { #8 ~ code }
-    \str_if_eq:eeTF { \exp_not:N #6 } { ? }
-      { ? }
-      { \exp_not:c { #8 ~ defaults } }
-    { \exp_not:V \l_@@_tmpa_tl }
-  }
-%    \end{macrocode}
-%
-% \begin{macro}{
-%     \@@_copy_expandable_signature:NnNNNNnnn,
-%     \@@_copy_expandable:nnN,
-%     \@@_copy_parse_grabber:w,
-%   }
-%   A signature for an expandable command contains as many
-%   \cs{expandable_grab_\meta{type}:w} as there are arguments, and what
-%   follows this macro depends on the \meta{type}.  We'll start a loop
-%   through the signature, and at each argument grabber, we'll step the
-%   argument count, and look for the \meta{type} with
-%   \cs{@@_copy_parse_grabber:w} so we know which
-%   \cs{@@_copy_grabber_\meta{type}:w} to call next.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_expandable_signature:NnNNNNnnn
-    #1 #2 #3 #4 #5 #6 #7 #8 #9
-  {
-    \int_zero:N \l_@@_current_arg_int
-    \tl_clear:N \l_@@_tmpa_tl
-    \@@_copy_expandable:nnN {#8} {#9} #7
-      \q_recursion_tail \q_recursion_stop
-  }
-\cs_new_protected:Npn \@@_copy_expandable:nnN #1 #2 #3
-  {
-    \quark_if_recursion_tail_stop:n {#3}
-    \int_incr:N \l_@@_current_arg_int
-    \exp_after:wN \@@_copy_parse_grabber:w \token_to_str:N #3 {#1} {#2}
-  }
-\use:x
-  {
-    \cs_new_protected:Npn \exp_not:N \@@_copy_parse_grabber:w ##1
-        \tl_to_str:n { expandable_grab_ } ##2 \tl_to_str:n { :w }
-      {
-        \tl_put_right:Nx \exp_not:N \l_@@_tmpa_tl
-          { \exp_not:N \exp_not:c { @@_expandable_grab_##2:w } }
-        \exp_not:N \cs_if_exist_use:cF { @@_copy_grabber_##2:w }
-          { \@@_cant_copy:nwn { unknown-type } }
-      }
-  }
-%    \end{macrocode}
-%
-% \begin{macro}{
-%     \@@_copy_grabber_D:w,\@@_copy_grabber_D_alt:w,
-%     \@@_copy_grabber_R:w,\@@_copy_grabber_R_alt:w,
-%     \@@_copy_grabber_E:w,\@@_copy_grabber_E_long:w,
-%     \@@_copy_grabber_t:w,
-%     \@@_copy_grabber_m:w,\@@_copy_grabber_m_long:w,
-%   }
-%   The most complicated is the |D|elimited argument:  each argument has
-%   a dedicated grabbing function named after the command that has to be
-%   copied over (of the form
-%   \cs{\meta{cmd}\textvisiblespace(arg\textvisiblespace\meta{num})}).
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_grabber_D:w #1 #2 #3 #4 #5
-  {
-    \tl_put_right:Nx \l_@@_tmpa_tl
-      {
-        \exp_not:c { #1 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
-        \exp_not:n { #4 #5 }
-      }
-    \cs_set_eq:cc
-      { #1 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
-      { #2 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
-    \@@_copy_expandable:nnN {#1} {#2}
-  }
-%    \end{macrocode}
-%
-%   |D_alt| is just a special case of |D| that uses a single delimiter
-%   (used when both delimiters of the argument are identical):
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_grabber_D_alt:w #1 #2 #3 #4
-  { \@@_copy_grabber_D:w {#1} {#2} {#3} {#4} { } }
-%    \end{macrocode}
-%
-%   |R|, as far as copying is concerned, is identical to |D|:
-%    \begin{macrocode}
-\cs_new_eq:NN \@@_copy_grabber_R:w \@@_copy_grabber_D:w
-\cs_new_eq:NN \@@_copy_grabber_R_alt:w \@@_copy_grabber_D_alt:w
-%    \end{macrocode}
-%
-%   |E| is straightforward: we just copy the embellishments over, and
-%   increase the current argument number \cs{l_@@_current_arg_int} by
-%   the number of embellishments (minus one because there is a
-%   \cs{int_incr:N} down the line).
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_grabber_E:w #1 #2 #3 #4
-  {
-    \tl_put_right:Nn \l_@@_tmpa_tl { {#3} {#4} }
-    \int_add:Nn \l_@@_current_arg_int { \tl_count:n {#4} - 1 }
-    \@@_copy_expandable:nnN {#1} {#2}
-  }
-\cs_new_eq:NN \@@_copy_grabber_E_long:w \@@_copy_grabber_E:w
-%    \end{macrocode}
-%
-%   |t| just needs copying the token to be tested for:
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_grabber_t:w #1 #2 #3 #4
-  {
-    \tl_put_right:Nn \l_@@_tmpa_tl { #3 #4 }
-    \@@_copy_expandable:nnN {#1} {#2}
-  }
-%    \end{macrocode}
-%
-%   And last but not least, |m| is the simplest;  the grabber is just
-%   \cs{@@_expandable_grab_m:w}, which is already added to the new
-%   command so here we just resume the loop:
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_grabber_m:w { \@@_copy_expandable:nnN }
-\cs_new_eq:NN \@@_copy_grabber_m_long:w \@@_copy_grabber_m:w
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_copy_environment:nnNN}
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_copy_environment:nnNN #1 #2 #3 #4
-  { \msg_error:nn { cmd } { env-copy } }
-\msg_new:nnn { cmd } { env-copy }
-  { Copying~environments~is~not~possible. }
-%    \end{macrocode}
-%
-%<latexrelease>\EndIncludeInRelease
-%
-%<latexrelease>\IncludeInRelease{0000/00/00}{\@@_copy:NN}%
-%<latexrelease>  {Support \NewCommandCopy and \ShowCommand in ltcmd}
-%
-%<latexrelease>\EndIncludeInRelease
-%
 % \subsection{Normalizing the argument specifications}
 %
 % The goal here is to expand aliases and check that the argument
@@ -1878,336 +1602,612 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_add_type_t:w}
-%   Setting up a \texttt{t} argument means collecting one token for the test,
-%   and adding it along with the grabber to the signature.
+% \begin{macro}{\@@_add_type_t:w}
+%   Setting up a \texttt{t} argument means collecting one token for the test,
+%   and adding it along with the grabber to the signature.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_t:w #1
+  {
+    \@@_flush_m_args:
+    \@@_add_default:
+    \@@_add_grabber:N t
+    \tl_put_right:Nn \l_@@_signature_tl {#1}
+    \@@_prepare_signature:N
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_v:w}
+%   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_novalue_tl
+    \@@_add_grabber:N v
+    \@@_prepare_signature:N
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_flush_m_args:}
+%   As \texttt{m} arguments are simply counted, there is a need to add
+%   them to the token register in a block. As this function can only
+%   be called if something other than \texttt{m} turns up, the flag can
+%   be switched here.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_flush_m_args:
+  {
+    \int_compare:nNnT \l_@@_m_args_int > 0
+      {
+        \tl_put_right:Nx \l_@@_signature_tl
+          { \exp_not:c { @@_grab_m_ \int_use:N \l_@@_m_args_int :w } }
+        \tl_put_right:Nx \l_@@_process_all_tl
+          { \prg_replicate:nn { \l_@@_m_args_int } { { } } }
+      }
+    \int_zero:N \l_@@_m_args_int
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_grabber:N}
+%   To keep the various checks needed in one place, adding the grabber
+%   to the signature is done here.  The only questions are whether the
+%   grabber should be long or not, and whether to obey spaces.  The
+%   \cs{l_@@_obey_spaces_bool} boolean can only be \texttt{true} for
+%   trailing optional arguments.  In that case spaces will not be
+%   ignored when looking for that optional argument.
+% \changes{v1.0g}{2021/08/07}
+%         {Replicate argument processors for all embellishments (gh/639)}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_add_grabber:N #1
+  {
+    \tl_put_right:Nx \l_@@_signature_tl
+      {
+        \exp_not:c
+          {
+            @@_grab_ #1
+            \bool_if:NT \l_@@_long_bool { _long }
+            \bool_if:NT \l_@@_obey_spaces_bool { _obey_spaces }
+            :w
+          }
+      }
+    \bool_set_false:N \l_@@_long_bool
+    \bool_set_false:N \l_@@_obey_spaces_bool
+    \tl_put_right:Nx \l_@@_process_all_tl
+      {
+        {
+          \if_charcode:w E #1 \use_i:nn \fi:
+          \exp_not:o \l_@@_process_one_tl
+        }
+      }
+    \tl_clear:N \l_@@_process_one_tl
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_default:n, \@@_add_default:, \@@_add_default_E:nn}
+%   Store the default value of an argument, or rather code that gives
+%   that default value (it may involve other arguments).  This is
+%   \cs{c_novalue_tl} for arguments with no actual default or with
+%   default |-NoValue-|; and (in a brace group) \cs{prg_do_nothing:}
+%   followed by a default value for others.  For \texttt{E}-type
+%   arguments, pad the defaults |#2| with some \cs{c_novalue_tl}
+%   until there are as many as embellishments~|#1|.  These functions are
+%   also used when defining expandable commands.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_add_default:n #1
+  {
+    \tl_if_novalue:nTF {#1}
+      { \@@_add_default: }
+      {
+        \int_incr:N \l_@@_current_arg_int
+        \bool_set_true:N \l_@@_defaults_bool
+        \tl_put_right:Nn \l_@@_defaults_tl { { \prg_do_nothing: #1 } }
+      }
+  }
+\cs_new_protected:Npn \@@_add_default:
+  {
+    \int_incr:N \l_@@_current_arg_int
+    \tl_put_right:Nn \l_@@_defaults_tl { \c_novalue_tl }
+  }
+\cs_new_protected:Npn \@@_add_default_E:nn #1#2
+  {
+    \tl_map_function:nN {#2} \@@_add_default:n
+    \prg_replicate:nn
+      { \tl_count:n {#1} - \tl_count:n {#2} }
+      { \@@_add_default: }
+  }
+%    \end{macrocode}
+% \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}
+%   We have already checked that short arguments are before long
+%   arguments, so \cs{l_@@_long_bool} only changes from \texttt{false}
+%   to \texttt{true} once (and there is no need to reset it after each
+%   argument).  Continue the loop.
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_add_expandable_type_+:w }
+  {
+    \bool_set_true:N \l_@@_long_bool
+    \@@_prepare_signature:N
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_D:w}
+% \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: |#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
+  { \@@_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 }
+    \@@_prepare_signature:N
+  }
+\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNN #1#2#3
+  {
+    \bool_if:NTF \l_@@_long_bool
+      { \cs_set:cpx }
+      { \cs_set_nopar:cpx }
+      { \l_@@_expandable_aux_name_tl } ##1 ##2 #2 ##3 \q_@@ ##4 #3
+      { ##1 {##2} {##3} {##4} }
+    \@@_add_expandable_grabber:nn {#1}
+      {
+        \exp_not:c  { \l_@@_expandable_aux_name_tl }
+        \exp_not:n { #2 #3 }
+      }
+  }
+\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NN #1#2
+  {
+    \bool_if:NTF \l_@@_long_bool
+      { \cs_set:cpx }
+      { \cs_set_nopar:cpx }
+      { \l_@@_expandable_aux_name_tl } ##1 #2 ##2 #2
+      { ##1 {##2} }
+    \@@_add_expandable_grabber:nn { #1_alt }
+      {
+        \exp_not:c  { \l_@@_expandable_aux_name_tl }
+        \exp_not:n {#2}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_E:w}
+% \begin{macro}{\@@_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).  Set the current argument appropriately.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_E:w #1#2
+  {
+    \@@_add_default_E:nn {#1} {#2}
+    \tl_clear:N \l_@@_tmpb_tl
+    \tl_map_function:nN {#1} \@@_add_expandable_type_E_aux:n
+    \@@_add_expandable_grabber:nn
+      { E \bool_if:NT \l_@@_long_bool { _long } }
+      {
+        { \exp_not:o \l_@@_tmpb_tl }
+        {
+          \prg_replicate:nn { \tl_count:n {#1} }
+            { { \c_novalue_tl } }
+        }
+      }
+    \@@_prepare_signature:N
+  }
+\cs_new_protected:Npn \@@_add_expandable_type_E_aux:n #1
+  {
+    \@@_get_grabber:NN #1 \l_@@_tmpa_tl
+    \tl_put_right:Nx \l_@@_tmpb_tl
+      { \exp_not:o \l_@@_tmpa_tl \exp_not:N #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_m:w}
+%   Unlike the standard case, when working expandably each argument is always
+%   grabbed separately.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_m:w
+  {
+    \@@_add_default:
+    \@@_add_expandable_grabber:nn
+      { m \bool_if:NT \l_@@_long_bool { _long } } { }
+    \@@_prepare_signature:N
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_R:w}
+%   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
+  { \@@_add_expandable_type_D_aux:NNNn R }
+%    \end{macrocode}
+% \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_type_t:w #1
+\cs_new_protected:Npn \@@_add_expandable_type_t:w #1
   {
-    \@@_flush_m_args:
     \@@_add_default:
-    \@@_add_grabber:N t
-    \tl_put_right:Nn \l_@@_signature_tl {#1}
+    \@@_get_grabber:NN #1 \l_@@_tmpa_tl
+    \@@_add_expandable_grabber:nn { t }
+      {
+        \exp_not:o \l_@@_tmpa_tl
+        \exp_not:N #1
+      }
     \@@_prepare_signature:N
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_add_type_v:w}
-%   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{macro}{\@@_add_expandable_grabber:nn}
+%   This is called for all arguments to place the right grabber in the
+%   signature.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_type_v:w
+\cs_new_protected:Npn \@@_add_expandable_grabber:nn #1#2
   {
-    \@@_flush_m_args:
-    \exp_args:No \@@_add_default:n \c_novalue_tl
-    \@@_add_grabber:N v
-    \@@_prepare_signature:N
+    \tl_put_right:Nx \l_@@_signature_tl
+      { \exp_not:c { @@_expandable_grab_ #1 :w } #2 }
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_flush_m_args:}
-%   As \texttt{m} arguments are simply counted, there is a need to add
-%   them to the token register in a block. As this function can only
-%   be called if something other than \texttt{m} turns up, the flag can
-%   be switched here.
+% \begin{macro}{\@@_get_grabber:NN}
+% \begin{macro}{\@@_get_grabber_auxi:NN}
+% \begin{macro}{\@@_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 \@@_flush_m_args:
+\cs_new_protected:Npn \@@_get_grabber:NN #1#2
   {
-    \int_compare:nNnT \l_@@_m_args_int > 0
+    \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 \@@_get_grabber_auxi:NN #1#2
+  {
+    \cs_if_eq:NNTF \@@_tmp:w #1
+      { \tl_set:Nn #2 {#1} }
       {
-        \tl_put_right:Nx \l_@@_signature_tl
-          { \exp_not:c { @@_grab_m_ \int_use:N \l_@@_m_args_int :w } }
-        \tl_put_right:Nx \l_@@_process_all_tl
-          { \prg_replicate:nn { \l_@@_m_args_int } { { } } }
+        \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 }
       }
-    \int_zero:N \l_@@_m_args_int
+  }
+\cs_new_protected:Npn \@@_get_grabber_auxii:NN #1#2
+  {
+    \cs_set_eq:NN #1 \@@_tmp:w
+    \tl_set:Nn #2 {#1}
   }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
+% \end{macro}
 %
-% \begin{macro}{\@@_add_grabber:N}
-%   To keep the various checks needed in one place, adding the grabber
-%   to the signature is done here.  The only questions are whether the
-%   grabber should be long or not, and whether to obey spaces.  The
-%   \cs{l_@@_obey_spaces_bool} boolean can only be \texttt{true} for
-%   trailing optional arguments.  In that case spaces will not be
-%   ignored when looking for that optional argument.
-% \changes{v1.0g}{2021/08/07}
-%         {Replicate argument processors for all embellishments (gh/639)}
+% \subsubsection{Copying a command and its internal structure}
+%
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_copy:NN}%
+%<latexrelease>  {Support \NewCommandCopy and \ShowCommand in ltcmd}
+% Since the 2020-10-01 \LaTeXe{} release, support for copying and
+% showing the definition of robust commands is available, but the
+% specifics of each command is implemented separately.  Here we'll add
+% support for copying and showing \pkg{ltcmd} definitions.
+%
+% To fully support copying, we need two commands:  a conditional to test
+% if a command is in fact an \pkg{ltcmd} command, and another to
+% actually copy the command.  The conditional is defined later as
+% \cs{__kernel_cmd_if_xparse:NTF}, so now to the copying:
+%
+% \begin{macro}{\@@_copy:NN}
+% \begin{macro}{\@@_set_eq_if_exist:NN,\@@_set_eq_if_exist:cc}
+%   This macro just branches to the proper copying command by using
+%   \cs{@@_cmd_type_cases:NnnnF}.  The copying command takes the names
+%   of the commands to be copied to and from, and the actual commands
+%   as its four arguments.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_grabber:N #1
+\cs_new_protected:Npn \@@_copy:NN #1 #2
   {
-    \tl_put_right:Nx \l_@@_signature_tl
-      {
-        \exp_not:c
-          {
-            @@_grab_ #1
-            \bool_if:NT \l_@@_long_bool { _long }
-            \bool_if:NT \l_@@_obey_spaces_bool { _obey_spaces }
-            :w
-          }
-      }
-    \bool_set_false:N \l_@@_long_bool
-    \bool_set_false:N \l_@@_obey_spaces_bool
-    \tl_put_right:Nx \l_@@_process_all_tl
+    \use:x
       {
-        {
-          \if_charcode:w E #1 \use_i:nn \fi:
-          \exp_not:o \l_@@_process_one_tl
-        }
+        \int_set:Nn \tex_escapechar:D { 92 }
+        \exp_not:N \@@_cmd_type_cases:NnnnF \exp_not:N #2
+          { \@@_copy_command:nnNN }
+          { \@@_copy_expandable:nnNN }
+          { \@@_copy_environment:nnNN }
+          { \@@_cant_copy:nwn { non-ltcmd } }
+            { \cs_to_str:N #1 } { \cs_to_str:N #2 }
+            \exp_not:N #1 \exp_not:N #2
+        \exp_not:N \@@_break_point:n { \cs_to_str:N #2 }
+        \int_set:Nn \tex_escapechar:D { \int_use:N \tex_escapechar:D }
       }
-    \tl_clear:N \l_@@_process_one_tl
   }
+\cs_new_protected:Npn \@@_set_eq_if_exist:NN #1 #2
+  { \cs_if_exist:NTF #2 { \cs_set_eq:NN } { \use_none:nn } #1 #2 }
+\cs_generate_variant:Nn \@@_set_eq_if_exist:NN { cc }
 %    \end{macrocode}
-% \end{macro}
 %
-% \begin{macro}{\@@_add_default:n, \@@_add_default:, \@@_add_default_E:nn}
-%   Store the default value of an argument, or rather code that gives
-%   that default value (it may involve other arguments).  This is
-%   \cs{c_novalue_tl} for arguments with no actual default or with
-%   default |-NoValue-|; and (in a brace group) \cs{prg_do_nothing:}
-%   followed by a default value for others.  For \texttt{E}-type
-%   arguments, pad the defaults |#2| with some \cs{c_novalue_tl}
-%   until there are as many as embellishments~|#1|.  These functions are
-%   also used when defining expandable commands.
+% \begin{macro}{\@@_cant_copy:nwn}
+%   An utility macro similar to \cs{@@_bad_def:wn} to abort a command
+%   copy.  Contrary to \cs{@@_bad_def:wn} though, when this happens the
+%   issue is most likely internal, because the command was already
+%   (supposedly) correcly defined so it should be copyable.  Hopefully
+%   this macro will never be used ever, but if it does, apologise and
+%   give the reason for the failure so the user can report.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_default:n #1
+\cs_new_protected:Npn \@@_cant_copy:nwn #1 #2 \@@_break_point:n #3
+  { \msg_error:nnnn { cmd } { copy-bug } {#1} {#3} }
+\msg_new:nnn { cmd } { copy-bug }
   {
-    \tl_if_novalue:nTF {#1}
-      { \@@_add_default: }
+    Internal~error~while~copying~command~\iow_char:N\\#2:\\
+    \str_case:nn {#1}
       {
-        \int_incr:N \l_@@_current_arg_int
-        \bool_set_true:N \l_@@_defaults_bool
-        \tl_put_right:Nn \l_@@_defaults_tl { { \prg_do_nothing: #1 } }
+        { non-ltcmd } { Command~is~not~a~valid~ltcmd~command. }
+        { unknown-type } { Found~an~unknown~argument~type. }
       }
   }
-\cs_new_protected:Npn \@@_add_default:
+%    \end{macrocode}
+% \end{macro}
+%
+%   And, of course, add \cs{__kernel_cmd_if_xparse:NTF} and
+%   \cs{@@_copy:NN} to \cs{@declarecommandcopylisthook}:
+%    \begin{macrocode}
+\tl_gput_right:Nn \@declarecommandcopylisthook
+  { { \__kernel_cmd_if_xparse:NTF \@@_copy:NN } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_copy_command:nnNN,\@@_copy_command:NnNNnnnn}
+%   A normal (non-expandable) command has a pretty straightforward
+%   structure.  Its definition is stored in
+%   \cs{\meta{cmd}\textvisiblespace code}, its defaults (if any) are
+%   stored in \cs{\meta{cmd}\textvisiblespace defaults}, and its
+%   top-level definition contains its signature, which can just be
+%   copied over.  \cs{@@_copy_command:nnNN} copies the command code and
+%   defaults, and then defines the top-level command using the auxiliary
+%   \cs{@@_copy_command:NnNNnnnn}.  This macro takes the signature of
+%   the command being copied from its top-level definition, and replaces
+%   the named bits with the new name.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_command:nnNN #1 #2 #3 #4
   {
-    \int_incr:N \l_@@_current_arg_int
-    \tl_put_right:Nn \l_@@_defaults_tl { \c_novalue_tl }
+    \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
+    \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults }
+    \cs_set_protected_nopar:Npx #3
+      { \exp_after:wN \@@_copy_command:NnNNnnnn #4 {#1} }
   }
-\cs_new_protected:Npn \@@_add_default_E:nn #1#2
+\cs_new:Npn \@@_copy_command:NnNNnnnn #1 #2 #3 #4 #5 #6 #7 #8
   {
-    \tl_map_function:nN {#2} \@@_add_default:n
-    \prg_replicate:nn
-      { \tl_count:n {#1} - \tl_count:n {#2} }
-      { \@@_add_default: }
+    #1 \exp_not:n { {#2} }
+    \exp_not:c { #8 ~ } \exp_not:c { #8 ~ code }
+    \exp_not:n { {#5} {#6} {#7} }
   }
 %    \end{macrocode}
 % \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}{\@@_copy_expandable:nnNN,\@@_copy_expandable:NnNNNNnnn}
+%   An expandable command is slightly more complicated.  Besides the
+%   \cs{\meta{cmd}\textvisiblespace code}, and
+%   \cs{\meta{cmd}\textvisiblespace defaults}, it also has an auxiliary
+%   \cs{\meta{cmd}\textvisiblespace} for grabbing delimited arguments,
+%   and possibly another auxiliary
+%   \cs{\meta{cmd}\textvisiblespace\textvisiblespace}, if the command
+%   has both long and short arguments.  Then, its signature has also
+%   several specific bits that are unique to that command, contrary to
+%   non-expandable commands which use a common set of parsing functions.
 %
-% \begin{macro}{\@@_add_expandable_type_+:w}
-%   We have already checked that short arguments are before long
-%   arguments, so \cs{l_@@_long_bool} only changes from \texttt{false}
-%   to \texttt{true} once (and there is no need to reset it after each
-%   argument).  Continue the loop.
+%   We'll start by copying the basics, then call
+%   \cs{@@_copy_expandable_signature:NnNNNNnnn} to parse the signature
+%   of the command and make the modified copy in a temporary token list,
+%   then we call \cs{@@_copy_expandable:NnNNNNnnn} that will copy the
+%   top-level definition of the command, with the proper internal
+%   renames.
 %    \begin{macrocode}
-\cs_new_protected:cpn { @@_add_expandable_type_+:w }
+\cs_new_protected:Npn \@@_copy_expandable:nnNN #1 #2 #3 #4
+  {
+    \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
+    \@@_set_eq_if_exist:cc { #1 ~ } { #2 ~ }
+    \@@_set_eq_if_exist:cc { #1 ~ \c_space_tl } { #2 ~ \c_space_tl }
+    \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults }
+    \exp_after:wN \@@_copy_expandable_signature:NnNNNNnnn #4 {#1} {#2}
+    \cs_set_nopar:Npx #3
+      { \exp_after:wN \@@_copy_expandable:NnNNNNnnn #4 {#1} {#2} }
+  }
+\cs_new:Npn \@@_copy_expandable:NnNNNNnnn #1 #2 #3 #4 #5 #6 #7 #8 #9
   {
-    \bool_set_true:N \l_@@_long_bool
-    \@@_prepare_signature:N
+    \exp_not:N #1 \exp_not:n { {#2} }
+    \exp_not:c { #8 ~ }
+    \exp_not:c
+      {
+        #8 ~
+        \str_if_eq:eeT
+            { \exp_not:c { #9 ~ \c_space_tl } } { \exp_not:N #4 }
+          { \c_space_tl }
+      }
+    \exp_not:c { #8 ~ code }
+    \str_if_eq:eeTF { \exp_not:N #6 } { ? }
+      { ? }
+      { \exp_not:c { #8 ~ defaults } }
+    { \exp_not:V \l_@@_tmpa_tl }
   }
 %    \end{macrocode}
-% \end{macro}
 %
-% \begin{macro}{\@@_add_expandable_type_D:w}
-% \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: |#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{macro}{
+%     \@@_copy_expandable_signature:NnNNNNnnn,
+%     \@@_copy_expandable:nnN,
+%     \@@_copy_parse_grabber:w,
+%   }
+%   A signature for an expandable command contains as many
+%   \cs{expandable_grab_\meta{type}:w} as there are arguments, and what
+%   follows this macro depends on the \meta{type}.  We'll start a loop
+%   through the signature, and at each argument grabber, we'll step the
+%   argument count, and look for the \meta{type} with
+%   \cs{@@_copy_parse_grabber:w} so we know which
+%   \cs{@@_copy_grabber_\meta{type}:w} to call next.
 %    \begin{macrocode}
-\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
+\cs_new_protected:Npn \@@_copy_expandable_signature:NnNNNNnnn
+    #1 #2 #3 #4 #5 #6 #7 #8 #9
   {
-    \@@_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 }
-    \@@_prepare_signature:N
+    \int_zero:N \l_@@_current_arg_int
+    \tl_clear:N \l_@@_tmpa_tl
+    \@@_copy_expandable:nnN {#8} {#9} #7
+      \q_recursion_tail \q_recursion_stop
   }
-\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNN #1#2#3
+\cs_new_protected:Npn \@@_copy_expandable:nnN #1 #2 #3
   {
-    \bool_if:NTF \l_@@_long_bool
-      { \cs_set:cpx }
-      { \cs_set_nopar:cpx }
-      { \l_@@_expandable_aux_name_tl } ##1 ##2 #2 ##3 \q_@@ ##4 #3
-      { ##1 {##2} {##3} {##4} }
-    \@@_add_expandable_grabber:nn {#1}
-      {
-        \exp_not:c  { \l_@@_expandable_aux_name_tl }
-        \exp_not:n { #2 #3 }
-      }
+    \quark_if_recursion_tail_stop:n {#3}
+    \int_incr:N \l_@@_current_arg_int
+    \exp_after:wN \@@_copy_parse_grabber:w \token_to_str:N #3 {#1} {#2}
   }
-\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NN #1#2
+\use:x
   {
-    \bool_if:NTF \l_@@_long_bool
-      { \cs_set:cpx }
-      { \cs_set_nopar:cpx }
-      { \l_@@_expandable_aux_name_tl } ##1 #2 ##2 #2
-      { ##1 {##2} }
-    \@@_add_expandable_grabber:nn { #1_alt }
+    \cs_new_protected:Npn \exp_not:N \@@_copy_parse_grabber:w ##1
+        \tl_to_str:n { expandable_grab_ } ##2 \tl_to_str:n { :w }
       {
-        \exp_not:c  { \l_@@_expandable_aux_name_tl }
-        \exp_not:n {#2}
+        \tl_put_right:Nx \exp_not:N \l_@@_tmpa_tl
+          { \exp_not:N \exp_not:c { @@_expandable_grab_##2:w } }
+        \exp_not:N \cs_if_exist_use:cF { @@_copy_grabber_##2:w }
+          { \@@_cant_copy:nwn { unknown-type } }
       }
   }
 %    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
 %
-% \begin{macro}{\@@_add_expandable_type_E:w}
-% \begin{macro}{\@@_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).  Set the current argument appropriately.
+% \begin{macro}{
+%     \@@_copy_grabber_D:w,\@@_copy_grabber_D_alt:w,
+%     \@@_copy_grabber_R:w,\@@_copy_grabber_R_alt:w,
+%     \@@_copy_grabber_E:w,\@@_copy_grabber_E_long:w,
+%     \@@_copy_grabber_t:w,
+%     \@@_copy_grabber_m:w,\@@_copy_grabber_m_long:w,
+%   }
+%   The most complicated is the |D|elimited argument:  each argument has
+%   a dedicated grabbing function named after the command that has to be
+%   copied over (of the form
+%   \cs{\meta{cmd}\textvisiblespace(arg\textvisiblespace\meta{num})}).
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_expandable_type_E:w #1#2
+\cs_new_protected:Npn \@@_copy_grabber_D:w #1 #2 #3 #4 #5
   {
-    \@@_add_default_E:nn {#1} {#2}
-    \tl_clear:N \l_@@_tmpb_tl
-    \tl_map_function:nN {#1} \@@_add_expandable_type_E_aux:n
-    \@@_add_expandable_grabber:nn
-      { E \bool_if:NT \l_@@_long_bool { _long } }
+    \tl_put_right:Nx \l_@@_tmpa_tl
       {
-        { \exp_not:o \l_@@_tmpb_tl }
-        {
-          \prg_replicate:nn { \tl_count:n {#1} }
-            { { \c_novalue_tl } }
-        }
+        \exp_not:c { #1 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
+        \exp_not:n { #4 #5 }
       }
-    \@@_prepare_signature:N
-  }
-\cs_new_protected:Npn \@@_add_expandable_type_E_aux:n #1
-  {
-    \@@_get_grabber:NN #1 \l_@@_tmpa_tl
-    \tl_put_right:Nx \l_@@_tmpb_tl
-      { \exp_not:o \l_@@_tmpa_tl \exp_not:N #1 }
+    \cs_set_eq:cc
+      { #1 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
+      { #2 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
+    \@@_copy_expandable:nnN {#1} {#2}
   }
 %    \end{macrocode}
-% \end{macro}
-% \end{macro}
 %
-% \begin{macro}{\@@_add_expandable_type_m:w}
-%   Unlike the standard case, when working expandably each argument is always
-%   grabbed separately.
+%   |D_alt| is just a special case of |D| that uses a single delimiter
+%   (used when both delimiters of the argument are identical):
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_expandable_type_m:w
-  {
-    \@@_add_default:
-    \@@_add_expandable_grabber:nn
-      { m \bool_if:NT \l_@@_long_bool { _long } } { }
-    \@@_prepare_signature:N
-  }
+\cs_new_protected:Npn \@@_copy_grabber_D_alt:w #1 #2 #3 #4
+  { \@@_copy_grabber_D:w {#1} {#2} {#3} {#4} { } }
 %    \end{macrocode}
-% \end{macro}
 %
-% \begin{macro}{\@@_add_expandable_type_R:w}
-%   The \texttt{R}-type is very similar to the \texttt{D}-type
-%   argument, and so the same internals are used.
+%   |R|, as far as copying is concerned, is identical to |D|:
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_expandable_type_R:w
-  { \@@_add_expandable_type_D_aux:NNNn R }
+\cs_new_eq:NN \@@_copy_grabber_R:w \@@_copy_grabber_D:w
+\cs_new_eq:NN \@@_copy_grabber_R_alt:w \@@_copy_grabber_D_alt:w
 %    \end{macrocode}
-% \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.
+%   |E| is straightforward: we just copy the embellishments over, and
+%   increase the current argument number \cs{l_@@_current_arg_int} by
+%   the number of embellishments (minus one because there is a
+%   \cs{int_incr:N} down the line).
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_expandable_type_t:w #1
+\cs_new_protected:Npn \@@_copy_grabber_E:w #1 #2 #3 #4
   {
-    \@@_add_default:
-    \@@_get_grabber:NN #1 \l_@@_tmpa_tl
-    \@@_add_expandable_grabber:nn { t }
-      {
-        \exp_not:o \l_@@_tmpa_tl
-        \exp_not:N #1
-      }
-    \@@_prepare_signature:N
+    \tl_put_right:Nn \l_@@_tmpa_tl { {#3} {#4} }
+    \int_add:Nn \l_@@_current_arg_int { \tl_count:n {#4} - 1 }
+    \@@_copy_expandable:nnN {#1} {#2}
   }
+\cs_new_eq:NN \@@_copy_grabber_E_long:w \@@_copy_grabber_E:w
 %    \end{macrocode}
-% \end{macro}
 %
-% \begin{macro}{\@@_add_expandable_grabber:nn}
-%   This is called for all arguments to place the right grabber in the
-%   signature.
+%   |t| just needs copying the token to be tested for:
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_add_expandable_grabber:nn #1#2
+\cs_new_protected:Npn \@@_copy_grabber_t:w #1 #2 #3 #4
   {
-    \tl_put_right:Nx \l_@@_signature_tl
-      { \exp_not:c { @@_expandable_grab_ #1 :w } #2 }
+    \tl_put_right:Nn \l_@@_tmpa_tl { #3 #4 }
+    \@@_copy_expandable:nnN {#1} {#2}
   }
 %    \end{macrocode}
-% \end{macro}
 %
-% \begin{macro}{\@@_get_grabber:NN}
-% \begin{macro}{\@@_get_grabber_auxi:NN}
-% \begin{macro}{\@@_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.
+%   And last but not least, |m| is the simplest;  the grabber is just
+%   \cs{@@_expandable_grab_m:w}, which is already added to the new
+%   command so here we just resume the loop:
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_get_grabber:NN #1#2
-  {
-    \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 \@@_get_grabber_auxi:NN #1#2
-  {
-    \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 \@@_get_grabber_auxii:NN #1#2
-  {
-    \cs_set_eq:NN #1 \@@_tmp:w
-    \tl_set:Nn #2 {#1}
-  }
+\cs_new_protected:Npn \@@_copy_grabber_m:w { \@@_copy_expandable:nnN }
+\cs_new_eq:NN \@@_copy_grabber_m_long:w \@@_copy_grabber_m:w
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\@@_copy_environment:nnNN}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_environment:nnNN #1 #2 #3 #4
+  { \msg_error:nn { cmd } { env-copy } }
+\msg_new:nnn { cmd } { env-copy }
+  { Copying~environments~is~not~possible. }
+%    \end{macrocode}
+%
+%<latexrelease>\EndIncludeInRelease
+%
+%<latexrelease>\IncludeInRelease{0000/00/00}{\@@_copy:NN}%
+%<latexrelease>  {Support \NewCommandCopy and \ShowCommand in ltcmd}
+%
+%<latexrelease>\EndIncludeInRelease
+%
 % \subsection{Grabbing arguments}
 %
 % All of the grabbers follow the same basic pattern. The initial





More information about the latex3-commits mailing list.