我想实现对用户定义命令的\FooTwo{a|b|c}
调用扩展为\shortstack{\texttt{a}\\\texttt{b}\\\texttt{c}}
。这是我的 MWE:
\documentclass{article}
\usepackage{xparse}
\makeatletter
\newcommand{\Bar}[1]{\ItemDelim\texttt{#1}}
\NewDocumentCommand{\FooOne}{>{\SplitList{|}}m}{%
\def\ItemDelim{\def\ItemDelim{,}}
(\ProcessList{#1}{\Bar})}
\NewDocumentCommand{\FooTwo}{>{\SplitList{|}}m}{%
\def\ItemDelim{\def\ItemDelim{\@stackcr}}
\shortstack{\ProcessList{#1}{\Bar}}}
\makeatother
\begin{document}
xxx
xxx \FooOne{a|b|c} xxx
xxx
xxx \FooTwo{a|b|c} xxx
xxx
\end{document}
我采用的技术似乎对 很有效\FooOne{a|b|c}
,但对 则不然\FooTwo{a|b|c}
。下图显示字符b
和c
未放在单独的行中。
这是什么原因呢?
附录:可能有更好的方法来实现我在本问题第一段中提出的目标。无论是否使用该xparse
软件包,我都愿意听取任何建议。
答案1
这个\def\ItemDelim{\def\ItemDelim{...}}
技巧不起作用,因为\shortstack
它是用来实现的\halign
,并且每个单元格都形成一个组。
最好使用更强大的expl3
函数。使用\seq_use:Nn
,\\
仅插入在项目之间。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_matthias_foo_seq
\NewDocumentCommand{\Foo}{m}
{
\group_begin:
\ttfamily
\seq_set_split:Nnn \l_matthias_foo_seq { | } { #1 }
\shortstack
{
\seq_use:Nn \l_matthias_foo_seq { \\ }
}
\group_end:
}
\ExplSyntaxOff
\begin{document}
xxx \Foo{a|b|c} xxx
\end{document}
如果这只是一个玩具问题,而您想要以某种方式处理这些物品,则可以使用两阶段方法:首先设置一个包含“裸体”物品的序列,然后将另一个序列设置为物品“装扮”的序列。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\Foo}{m}
{
\matthias_foo:n { #1 }
}
\seq_new:N \l_matthias_foo_in_seq
\seq_new:N \l_matthias_foo_out_seq
\cs_new_protected:Nn \matthias_foo:n
{
\seq_set_split:Nnn \l_matthias_foo_in_seq { | } { #1 }
\seq_set_map:NNn \l_matthias_foo_out_seq \l_matthias_foo_in_seq
{
\exp_not:n { \texttt { ##1 } }
}
\shortstack
{
\seq_use:Nn \l_matthias_foo_out_seq { \\ }
}
}
\ExplSyntaxOff
\begin{document}
xxx \Foo{a|b|c} xxx
\end{document}
答案2
它按照这个定义正确工作:
\NewDocumentCommand{\FooTwo}{>{\SplitList{|}}m}{%
\def\ItemDelim{\gdef\ItemDelim{\\}}
\shortstack{\ProcessList{#1}{\Bar}}
}