我想定义一个带有xparse
's的命令\NewDocumentCommand
,它接收以逗号分隔的列表作为参数,但能够以某种方式发出信号表示该列表上的某些项目应该特殊处理。
我对此的第一个想法是使用支撑。我想到了类似的东西:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand \mylist { > { \SplitList { , } } m }
{
\tl_map_inline:nn {#1}
{
\tl_if_head_is_group:nTF {##1}
{ Hi,~I'm~special~##1! \par }
{ ##1 \par }
}
}
\ExplSyntaxOff
\begin{document}
\mylist{item1,item2,{{item3}},item4,{{item5}},item6}
\end{document}
正如预期的那样,打印结果如下:
而且,如果我不能依赖排版中展开的额外括号,就像上面的例子一样,我可以使用类似这样的方法:
\cs_new:Npn \__my_tl_set_unbraced:Nn #1#2
{
\tl_if_head_is_group:nTF {#2}
{ \tl_set:Nn #1 #2 }
{ \tl_set:Nn #1 {#2} }
}
在我检索到“信号”之后,可以传递一个包含该函数的变量集作为参数,使其像列表中的任何其他“非特殊”项一样工作。
虽然这一切确实有效,乍一看感觉还不错,但我发现它有点太“有创意”了,甚至有点让人厌烦,我想知道是否还有其他选择。因此我提出了这个问题。
我想知道的是:这是一个合理的程序吗?(从技术方面和用户界面方面来看)。你认为其中有什么明显的警告吗?有没有好的替代方案?
答案1
您的代码是合理并且可以工作,但是需要{{special item}}
,因为 TeX 的规则是,当不平衡的标记列表不会出现时,参数周围的一对括号会被剥离。
我会使用|special item|
更简单的类型并避免\SplitList
:无论如何你都需要达到该expl3
级别。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand \mylist { m }
{
\gusbrs_mylist:n { #1 }
}
\cs_new_protected:Nn \gusbrs_mylist:n
{
\clist_map_inline:nn {#1}
{
\str_if_eq:eeTF { \tl_head:n { ##1 } } { | }
{ \__gusbrs_mylist_special:w ##1 }
{ ##1 \par }
}
}
\cs_new:Npn \__gusbrs_mylist_special:w | #1 |
{
Hi,~I'm~special~#1! \par
}
\ExplSyntaxOff
\begin{document}
\mylist{item1,item2,|item3|,item4,|item5|,item6}
\end{document}
|
作为练习,您可以在调用函数之前添加尾随测试:w
并引发警告或错误。
阅读评论后,您还可以在此处仅使用前缀字符来标记特殊项目|
。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand \mylist { m }
{
\gusbrs_mylist:n { #1 }
}
\cs_new_protected:Nn \gusbrs_mylist:n
{
\clist_map_inline:nn {#1}
{
\str_if_eq:eeTF { \tl_head:n { ##1 } } { | }
{ \__gusbrs_mylist_special:e { \tl_tail:n { ##1 } } }
{ ##1 \par }
}
}
\cs_new:Nn \__gusbrs_mylist_special:n
{
Hi,~I'm~special~#1! \par
}
\cs_generate_variant:Nn \__gusbrs_mylist_special:n { e }
\ExplSyntaxOff
\begin{document}
\mylist{item1,item2,|item3,item4,|item5,item6}
\end{document}
答案2
这是 latex2e 的一种方式,使用listofitems
。特殊项目包含*
,它应该出现在项目的末尾。可以通过编辑\setsepchar
列表中的最后一个条目来更改特殊字符表示符。
\documentclass{article}
\usepackage{listofitems}
\newcommand\processmylist[1]{%
\setsepchar{,/*}%
\readlist*\mylist{#1}%
\foreachitem\z\in\mylist[]{%
\ifnum\listlen\mylist[\zcnt]=1
\z
\else
SPECIAL: \mylist[\zcnt,1]%
\fi
\\
}%
}
\begin{document}
\noindent\processmylist{item1, item2, item3*, item4, item 5*}
\end{document}