SplitArgument{<sep>}
我正在尝试在 内做类似的事情expl3
。现在我修复了<sep>=;
。但我没有取得很大进展:
\documentclass{report}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Nn \__erw_inner:nnn{(#1)(#2)(#3)}
\cs_new:Nn \__erw_outer:n
{
% \seq_clear:N \l_tmpa_seq
\seq_set_split:Nnn \l_tmpa_seq { ; }{#1}
%\seq_use:Nnnn \l_tmpa_seq{,}{,}{,} % EXPECT a,b,c % OK
%\seq_map_inline:Nn \l_tmpa_seq{(##1)} % EXPECT (a)(b)(c) % OK
%wishful thinking?
\exp_last_unbraced:Nf
\__erw_inner:nnn
{
\seq_map_inline:Nn \l_tmpa_seq{\exp_not:n{{##1}}}
}
} %WANT: \erw_inner:nnn{a}{b}{c} % GET: ERROR: You can't use a prefix with `the character )'
\NewDocumentCommand\Test{m}
{
\__erw_outer:n{#1}
}
\begin{document}
\Test{a;b;c}
\ExplSyntaxOff
\end{document}
答案1
我不太明白你为什么要使用“辅助函数” \__erw_inner:nnn
,\__erw_outer:N
但我认为这是你心中实际应用程序的一部分。在我看来,你误用了 expl3 语法:当你使用
\seq_set_split:Nnn \l_tmpa_seq { ; }{#1}
拆分输入,然后您可以\l_tmpa_seq
使用 expl3 提供的工具处理数据。特别是,我不明白为什么您\exp_last_unbraced:Nf
的代码中有这个。
为了获得所需的输出,您可以使用以下命令:
\documentclass{report}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand\Test{m}
{
\seq_set_split:Nnn \l_tmpa_seq { ; }{#1} % split the input
\seq_map_inline:Nn \l_tmpa_seq {(##1)} % print bracket enclosed input
}
\ExplSyntaxOff
\begin{document}
\Test{a;b;c}
\end{document}
如果这不符合您的用例,您能否提供更多有关您真正想要做的事情的信息?
请注意,应将其\ExplSyntaxOff
放在 expl3 宏定义的末尾。如果它位于文档末尾(如在 MWE 中),则所有特殊 expl3 字符都将无法在文档中使用。
答案2
不,你不是在尝试做该\SplitArgument
做的事情。这个预处理器想要二参数:一个数字和一个分隔符。数字是必需的。
如果你
\NewDocumentCommand{\test}{ >{\SplitArgument{2}{;}}m } {...#1...}
那么你可以相信它将#1
被传递为三支撑群。因此
\test{a;b;c}
\test{a;b}
\test{a}
将分别通过
{a}{b}{c}
{a}{b}{-NoValue-}
{a}{-NoValue-}{-NoValue-}
该论点不应是空洞的。
当然,替换文本\test
将包含类似
...\Command#1...
其中\Command
是一个包含三个参数的命令,它将测试每个参数是否-NoValue-
通过测试\IfNoValueTF
。
如果参数\test
包含两个以上的分号,则会出现错误,因为宏\Command
无法合理地处理其后跟的四个括号组。
你的目标似乎更相似\SplitList
。假设你有
\NewDocumentCommand{\test}{ >{\SplitList{;}}m } { ... }
那么替换文本应该包含类似
\ProcessList{#1}{\Command}
其中\Command
是一个单参数宏,列表中的每个项目将依次传递给它。因此,例如,
\NewDocumentCommand{\test}{ >{\SplitList{;}}m }{%
\ProcessList{#1}{\Command}%
}
\NewDocumentCommand{\Command}{m}{(#1)}
调用如下
\test{a;b;c;d;e}
将导致输出
(一)(二)(三)(四)(五)
分号分隔的项目数量没有限制,但参数不能为空。
例子
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\testA}{ >{\SplitArgument{2}{;}}m }{%
\CommandA#1%
}
\NewDocumentCommand{\CommandA}{mmm}{%
#1--%
\IfNoValueTF{#2}{???}{#2}--%
\IfNoValueTF{#3}{???}{#3}%
}
\NewDocumentCommand{\testB}{ >{\SplitList{;}}m }{%
\ProcessList{#1}{\CommandB}%
}
\NewDocumentCommand{\CommandB}{m}{%
(#1)%
}
\begin{document}
Here we look at \verb+\SplitArgument+
\testA{a;b;c}\par
\testA{a;b}\par
\testA{a}\par
\bigskip
Here we look at \verb+\SplitList+
\testB{a;b;c;d;e}\par
\testB{a;b;c;d}\par
\testB{a;b;c}\par
\testB{a;b}\par
\testB{a}\par
\end{document}
如果您想模仿后一种行为该怎么办?
\ExplSyntaxOn
\NewDocumentCommand{\test}{m}
{
\seq_set_split:Nnn \l_tmpa_seq { ; } { #1 }
\seq_map_function:NN \l_tmpa_seq \__erwann_parens:n
}
\cs_new:Nn \__erwann_parens:n { (#1) }
\ExplSyntaxOff
答案3
正如问题中给出的代码中所述,我想要\__erw_outer:n{a;b;c}
输出\__erw_inner:nnn{a}{b}{c}
需要类似 的内容\SplitArgument
。我应该补充说,这样做的动机是为了能够对外部参数进行参数扩展。这是一个糟糕的解决方案,在expl3
和之间来回切换xparse
。一切都应该在expl3
(也许\__xparse_split_argument:nnn
?)
\documentclass{report}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Nn \__erw_inner:nnn{(#1)(#2)(#3)}
\NewDocumentCommand\ErwOuter
{> { \SplitArgument { 2 } { ; } } m }
{
\__erw_inner:nnn#1
}
\cs_new:Nn \__erw_outer:n
{
\ErwOuter{#1}
} %WANT: \erw_inner:nnn{a}{b}{c}
\cs_generate_variant:Nn \__erw_outer:n {e}
\NewDocumentCommand\Test{m}
{
\tl_set:Nn \l_tmpa_tl{#1}
\__erw_outer:n{\l_tmpa_tl}\\
\__erw_outer:e{\l_tmpa_tl}
}
\begin{document}
\Test{a;b;c}
\ExplSyntaxOff
\end{document}