(这个问题在某种程度上与这个答案。
我想创建一个具有任意数量(以逗号分隔)参数的文档命令,每个参数都是一个逗号列表,其中的项目必须进行处理。
以下 MCE:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand\signature{m}
{
\__mymodule_process_list:n {#1}
}
\seq_new:N \l__mymodule_items_seq
\cs_new_protected:Npn \__mymodule_process_list:n #1
{
\seq_clear:N \l__mymodule_items_seq
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\seq_map_inline:Nn \l_tmpa_seq {
\seq_set_from_clist:Nn \l_tmpb_seq {##1}
\seq_get_right:NN \l_tmpb_seq \l_tmpa_tl
\seq_get_left:NN \l_tmpb_seq \l_tmpb_tl
\seq_put_right:Nx \l__mymodule_items_seq {
% \seq_put_right:NV \l__mymodule_items_seq {
\l_tmpa_tl
\c_space_tl \l_tmpb_tl
% \c_space_tl \textsc{\l_tmpb_tl}
}
}
\seq_use:Nn \l__mymodule_items_seq { ~ \& ~ }
}
\ExplSyntaxOff
\begin{document}
\signature{
{Last1, First1}
}
\signature{
{Last1, First1},
{Last2, First2}
}
\signature{
{Last1, First1},
{Last2, First2},
{Last3, First3}
}
\end{document}
效果很好,也就是说结果是:
First1 Last1
First1 Last1 & First2 Last2
First1 Last1 & First2 Last2 & First3 Last3
但是,如果我\c_space_tl \l_tmpb_tl
用替换\c_space_tl \textsc{\l_tmpb_tl}
以便将姓氏变为小写,LaTeX 会抱怨:
! Missing control sequence inserted. <inserted text> \inaccessible ```
在这种情况下,如果我\seq_put_right:Nx
用例如替换\seq_put_right:NV
,编译会顺利进行,但结果不是预期的结果(每行的姓氏相同):
First1 Lᴀꜱᴛ1
First1 Lᴀꜱᴛ2 & First2 Lᴀꜱᴛ2
First1 Lᴀꜱᴛ3 & First2 Lᴀꜱᴛ3 & First3 Lᴀꜱᴛ3
使用\seq_put_right:Nx
和 ,而不是\textsc{\l_tmpb_tl}
,{\scshape \l_tmpb_tl}
它可以按预期工作,但为什么不使用 呢\textsc{\l_tmpb_tl}
?
答案1
\textsc
您需要使用 来防止(或任何其他不应扩展的宏)的扩展\exp_not:N
,因此
\seq_put_right:Nx \l__mymodule_items_seq
{ \c_space_tl \exp_not:N \textsc { \l_tmpb_tl } }
% ^^^^^^^^^^
你对NV
变体的使用是错误的。V
-type 应该采用单变量作为参数,因此这是正确的:
\seq_put_right:NV \l__mymodule_items_seq \l_tmpb_tl
这是一个有点奇怪的语法(但不一定是错误的):
\seq_put_right:NV \l__mymodule_items_seq { \l_tmpb_tl }
这完全不对
\seq_put_right:NV \l__mymodule_items_seq { \l_tmpa_tl \l_tmpb_tl }
\scshape
有效(在 之后\begin{document}
),因为它是用 定义的\protected
。如果你执行\ShowCommand\scshape
,你会看到\scshape=\protected macro:->[...]
,所以它不会在 中扩展(由中的扩展\edef
使用)。x
\seq_put_right:Nx
\textsc
另一方面,是一个robust
宏(\ShowCommand\textsc
):
> \textsc=robust macro:
->\protect \textsc .
> \textsc =\long macro:
#1->[...]
所以它会在内部破裂\edef
(它需要\protected@edef
不爆炸)。
答案2
您可以使用\exp_not:N \textsc
,但名称中的标记也可能会引发问题。我建议使用\text_expand:n
可能包含危险标记的文本输入部分进行包装。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand\signature{m}
{
\__mymodule_process_list:n {#1}
}
\seq_new:N \l__mymodule_items_seq
\cs_new_protected:Npn \__mymodule_process_list:n #1
{
\seq_clear:N \l__mymodule_items_seq
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\seq_map_inline:Nn \l_tmpa_seq
{
\seq_set_from_clist:Nn \l_tmpb_seq {##1}
\seq_get_right:NN \l_tmpb_seq \l_tmpa_tl
\seq_get_left:NN \l_tmpb_seq \l_tmpb_tl
\seq_put_right:Nx \l__mymodule_items_seq
{
\text_expand:n { \l_tmpa_tl \c_space_tl \textsc { \l_tmpb_tl } }
}
}
\seq_use:Nn \l__mymodule_items_seq { ~ \& ~ }
}
\ExplSyntaxOff
\begin{document}
\signature{
{Last1, First1}
}
\signature{
{Last1, First1},
{Last2, First2}
}
\signature{
{Last1, First1},
{Last2, First2},
{La\'st3, F\'irst3}
}
\end{document}