Your request subsumes two tasks:
- A routine for mapping a comma-list to a list of undelimited arguments where a macro-token is prepended for processing the delimited arguments.
- A routine
\enhance{\command} which defines \commandEnhanced to apply the mapping-routine and hereby having the token \command prepended to the list of undelimited arguments which comes into being by the mapping.
Let's look at the first task:
In the example below the routine for mapping a comma-list to a list of undelimited arguments is called \PassCommaListAsUndelimitedListTo.
\PassCommaListAsUndelimitedListTo{⟨comma list⟩}{⟨code⟩} turns the ⟨comma list⟩ into a list of undelimited arguments where ⟨code⟩ is prepended.
E.g., \PassCommaListAsUndelimitedListTo{A, B, C}{⟨code⟩} yields ⟨code⟩{A}{B}{C}.
The code for \PassCommaListAsUndelimitedListTo is inspired by the function \clist_map_tokens:nn from expl3/LaTeX3 release 2021-05-05 or newer.
\clist_map_tokens:nn {⟨comma list⟩} {⟨code⟩} calls ⟨code⟩{⟨item⟩} for every ⟨item⟩ stored in the ⟨comma list⟩.
If an ⟨item⟩ of the ⟨comma list⟩ can be considered a set of tokens that is nested into a pair of matching curly braces, that outermost pair of surrounding matching curly braces will be stripped off.
\clist_map_tokens:nn ignores/discards/does not map empty ⟨item⟩s of the ⟨comma list⟩.
You can use something like \clist_map_tokens:nn for creating an expandable "mechanism"
\PassCommaListAsUndelimitedListTo{⟨comma list⟩}{⟨code⟩}
which turns a ⟨comma list⟩ into a list of undelimited arguments where ⟨code⟩ is prepended.
"Something like" because the circumstance of \clist_map_tokens:nn ignoring/discarding/not mapping empty ⟨item⟩s of the ⟨comma list⟩ might be a bit counter-intuitive—e.g., \PassCommaListAsUndelimitedListTo {A, , C}{\macro} would not yield \macro{A}{}{C} but would yield \macro{A}{C} if \clist_map_tokens:nn was used.
You can can easily derive a function from the definition of \clist_map_tokens:nn which does not ignore/discard empty ⟨item⟩s of the ⟨comma list⟩ by omitting the check for emptiness/blankness which is in \clist_map_tokens:nn's definition—if you do that, you need to be picky about the list having a trailing comma denoting an empty item behind that comma:
\ExpöSyntaxOn
\cs_new:Npn \PassCommaListAsUndelimitedList_clist_map_tokens:nn #1#2
{
\__PassCommaListAsUndelimitedList_clist_map_tokens_n:nw {#2}
\prg_do_nothing: #1 , \s__clist_stop \clist_map_break: ,
\prg_break_point:Nn \clist_map_break: { }
}
\cs_new:Npn \__PassCommaListAsUndelimitedList_clist_map_tokens_n:nw #1#2 ,
{
\__clist_use_none_delimit_by_s_stop:w #2 \s__clist_stop
\tl_trim_spaces_apply:oN {#2} \use_ii_i:nn
\__clist_map_unbrace:wn , {#1}
\__PassCommaListAsUndelimitedList_clist_map_tokens_n:nw {#1} \prg_do_nothing:
}
\ExplSyntaxOff
The function
\PassCommaListAsUndelimitedList_clist_map_tokens:nn {⟨comma list⟩} {⟨code⟩}
calls ⟨code⟩{⟨item⟩} for every ⟨item⟩ stored in the ⟨comma list⟩.
Unlike the function \clist_map_tokens:nn the function \PassCommaListAsUndelimitedList_clist_map_tokens:nn does not discard/ignore empty comma-list items but maps them to undelimited empty arguments.
Using \PassCommaListAsUndelimitedList_clist_map_tokens:nn you can define \PassCommaListAsUndelimitedListTo as follows:
As \PassCommaListAsUndelimitedList_clist_map_tokens:nn's ⟨code⟩-argument use a macro/function \__PassCommaListAsUndelimitedList_grab_next:nwn which grabs several arguments:
- the tokens forming the comma-list-item of the current iteration (n-type-argument)
- the tokens forming the next
\PassCommaListAsUndelimitedList_clist_map_tokens:nn-iteration as a delimited argument (w-type-argument) where the delimiter \__PassCommaListAsUndelimitedList_Reserved:n is trailed by
- an argument holding the macro-token/code that shall be prepended to the undelimited arguments and the undelimited arguments gathered so far (n-type-argument).
This macro/function reinserts the tokens forming the next \PassCommaListAsUndelimitedList_clist_map_tokens:nn-iteration, the \__PassCommaListAsUndelimitedList_Reserved:n-delimiter and the argument holding the macro-token/code that shall be prepended to the undelimited arguments and the undelimited arguments gathered so far with the tokens forming the comma-list-item of the current iteration appended.
This way the combination of \PassCommaListAsUndelimitedList_clist_map_tokens:nn and \__PassCommaListAsUndelimitedList_grab_next:nwn iteratively accumulates the comma-list-items within the undelimited argument behind the delimiter \__PassCommaListAsUndelimitedList_Reserved:n.
When iterating is done, expanding \__PassCommaListAsUndelimitedList_Reserved:n removes the braces that surround that undelimited argument.
\ExplSyntaxOn
\cs_new:Npn \__PassCommaListAsUndelimitedList_grab_next:nwn #1#2\__PassCommaListAsUndelimitedList_Reserved:n #3 {
% #1 - current comma-list-item
% #2 - tokens forming the next `\clist_map_tokens:nn`-iteration
% #3 - code that shall prepend undelimited arguments and undelimited arguments gathered so far
#2 \__PassCommaListAsUndelimitedList_Reserved:n {#3{#1}}
}
\cs_new:Npn \__PassCommaListAsUndelimitedList_Reserved:n #1 {#1}
\cs_new:Npn \PassCommaListAsUndelimitedListTo #1#2 {
\PassCommaListAsUndelimitedList_clist_map_tokens:nn {#1} {\__PassCommaListAsUndelimitedList_grab_next:nwn}
\__PassCommaListAsUndelimitedList_Reserved:n {#2}
}
\ExplSyntaxOff
With this code you can do, e.g.,
\PassCommaListAsUndelimitedListTo{A, B, C}{\macro}
for obtaining \macro{A}{B}{C}.
With this code you can do, e.g.,
\PassCommaListAsUndelimitedListTo{A, , C}{\macro}
for obtaining \macro{A}{}{C}.
With this code you can do, e.g.,
\PassCommaListAsUndelimitedListTo{A, B, }{\macro}
for obtaining \macro{A}{B}{}.
(You need to be picky about the list having a trailing comma denoting an empty item behind that comma.)
Let's look at the second task:
You can use \cs_to_str:N for obtaining the name of a control-sequence-token without leading backslash/escape-character. (As a special case with the nameless control-sequence-token, obtainable via \csname\endcsname or via having at the end of a line of .tex-input while the integer-parameter \endlinechar has a negative value, you get
csname⟨current escape-char⟩endcsname.)
Thus you can define \enhance in terms of \cs_to_str:N and \PassCommaListAsUndelimitedListTo:
\ExplSyntaxOn
\cs_new:Npn \enhance #1 {
\cs_new:cpn {\cs_to_str #1 Enhanced} ##1 {
\PassCommaListAsUndelimitedListTo { ##1 }{ #1 }
}
}
\ExplSyntaxOff
Putting the pieces together you get:
\documentclass{article}
% \PassCommaListAsUndelimitedList_clist_map_tokens:nn {⟨comma list⟩} {⟨code⟩}
% Calls ⟨code⟩ {⟨item⟩} for every ⟨item⟩ stored in the ⟨comma list⟩.
% Does - unlike \clist_map_tokens:nn - not discard empty comma-list items.
\ExplSyntaxOn
\cs_new:Npn __PassCommaListAsUndelimitedList_grab_next:nwn #1#2__PassCommaListAsUndelimitedList_Reserved:n #3 {
% #1 - current comma-list-item
% #2 - tokens forming the next \clist_map_tokens:nn-iteration
% #3 - code that shall prepend undelimited arguments and undelimited arguments gathered so far
#2 __PassCommaListAsUndelimitedList_Reserved:n {#3{#1}}
}
\cs_new:Npn __PassCommaListAsUndelimitedList_Reserved:n #1 {#1}
\cs_new:Npn \PassCommaListAsUndelimitedListTo #1#2 {
\PassCommaListAsUndelimitedList_clist_map_tokens:nn {#1} {__PassCommaListAsUndelimitedList_grab_next:nwn}
__PassCommaListAsUndelimitedList_Reserved:n {#2}
}
\cs_new:Npn \enhance #1 {
\cs_new:cpn {\cs_to_str:N #1 Enhanced} ##1 {
\PassCommaListAsUndelimitedListTo { ##1 }{ #1 }
}
}
\cs_new:Npn \PassCommaListAsUndelimitedList_clist_map_tokens:nn #1#2
{
__PassCommaListAsUndelimitedList_clist_map_tokens_n:nw {#2}
\prg_do_nothing: #1 , \s__clist_stop \clist_map_break: ,
\prg_break_point:Nn \clist_map_break: { }
}
\cs_new:Npn __PassCommaListAsUndelimitedList_clist_map_tokens_n:nw #1#2 ,
{
__clist_use_none_delimit_by_s_stop:w #2 \s__clist_stop
\tl_trim_spaces_apply:oN {#2} \use_ii_i:nn
__clist_map_unbrace:wn , {#1}
__PassCommaListAsUndelimitedList_clist_map_tokens_n:nw {#1} \prg_do_nothing:
}
%\cs_new:Npn __clist_map_unbrace:wn #1, #2 { #2 {#1} }
\ExplSyntaxOff
\newcommand\macro[3]{%
{\frenchspacing\textnormal{\detokenize{Arg 1: (#1) Arg 2: (#2) Arg 3: (#3)}}}%
}%
\enhance{\macro}
\begin{document}
\noindent \verb|\macroEnhanced{A, B, C}| yields\
\verb|\PassCommaListAsUndelimitedListTo{A, B, C}{\macro}|, which in turn yields\
\verb|\macro{A}{B}{C}|.
\smallskip
\noindent Thus the following three commands in the end yield the same:
\smallskip
\noindent \verb|\macroEnhanced{A, B, C}|:\
\macroEnhanced{A, B, C}
\smallskip
\noindent \verb|\PassCommaListAsUndelimitedListTo {A, B, C}{\macro}|:\
\PassCommaListAsUndelimitedListTo {A, B, C}{\macro}
\smallskip
\noindent \verb|\macro{A}{B}{C}|:\
\macro{A}{B}{C}.
\bigskip\hrule\bigskip
\noindent \verb|\macroEnhanced{A, , C}| yields\
\verb|\PassCommaListAsUndelimitedListTo{A, , C}{\macro}|, which in turn yields\
\verb|\macro{A}{}{C}|.
\smallskip
\noindent Thus the following three commands in the end yield the same:
\smallskip
\noindent \verb|\macroEnhanced{A, , C}|:\
\macroEnhanced{A, , C}
\smallskip
\noindent \verb|\PassCommaListAsUndelimitedListTo {A, , C}{\macro}|:\
\PassCommaListAsUndelimitedListTo {A, , C}{\macro}
\smallskip
\noindent \verb|\macro{A}{}{C}|:\
\macro{A}{}{C}.
\bigskip\hrule\bigskip
\noindent \verb|\macroEnhanced{A, , }| yields\
\verb|\PassCommaListAsUndelimitedListTo{A, , }{\macro}|, which in turn yields\
\verb|\macro{A}{}{}|.
\smallskip
\noindent Thus the following three commands in the end yield the same:
\smallskip
\noindent \verb|\macroEnhanced{A, , }|:\
\macroEnhanced{A, , }
\smallskip
\noindent \verb|\PassCommaListAsUndelimitedListTo {A, , }{\macro}|:\
\PassCommaListAsUndelimitedListTo {A, , }{\macro}
\smallskip
\noindent \verb|\macro{A}{}{}|:\
\macro{A}{}{}.
\end{document}

\commandhas been called with several arguments, that' s a bad idea.\textbf{Foo}{bar}is perfectly legitimate TeX syntax.baris simply inside a brace group. This plus the fact that in your question, there is a\commandwith two different syntaxes... – frougon Jun 09 '22 at 08:00\NewDocumentCommandwith\SplitArgument? https://tex.stackexchange.com/a/605337/263192 – Jun 09 '22 at 08:24}{into,. ... "command" has multiple meanings: control sequence, cs name, definition, syntax, meaning, argument specification, output or result; in sequence or in parallel?; across or within groups?; recursive?; ... – Cicada Jun 09 '22 at 10:59