在这个帖子,我发现了一个处理列表的好技巧。下面的代码允许使用可选分隔符参数打印列表。
\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\newcommand{\printlist}[2][,]{%
\def\itemdelim{\def\itemdelim{#1}}% Item delimiter delayed by one cycle
\renewcommand*{\do}[1]{\itemdelim##1}% How each item is processed
\docsvlist{#2}}% Process CSV list
\begin{document}
$\printlist{1,2,3,4,5,6,7}$ \par
$\printlist[;]{a,b,c,d,e,f}$
\end{document}
但是,如果我\printlist
在命令中使用\author
换行符,\\
则无法正常工作:仅为列表的第一个元素设置换行符。对于所有其他元素,换行符将被忽略:
\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\newcommand{\printlist}[2][;]{%
\def\itemdelim{\def\itemdelim{#1}}% Item delimiter delayed by one cycle
\renewcommand*{\do}[1]{\itemdelim##1}% How each item is processed
\docsvlist{#2}}% Process CSV list
\title{Test}
\author{\printlist[,\\]{abc,def,ghi,jkl}}
\begin{document}
\maketitle
\end{document}
如果我使用没有换行符的分隔符,例如::
,上述内容将按预期工作。
\\
在命令中添加额外的换行符\author
也会导致预期的结果:
\author{\printlisti[::]{abc,def,ghi}\\123\\456\\789}
看起来\printlist
与换行符的组合\\
导致了问题。这是怎么回事?
答案1
的参数\author
将排版在 中tabular
。每个单元格都形成自己的组,因此 的内部定义\itemdelim
和 的定义\do
将不会在第一行中保留。
本质上,发生的事情如下:
\begin{tabular}{c}
\def\itemdelim{test} \\
\itemdelim
\end{tabular}
和 也是一样\do
,尽管第二行中的 具有与 之外相同的定义tabular
,但不会导致错误消息。
\itemdelim
您将需要进行(对于非第一个条目)和\do
全局的定义:
\newcommand{\printlist}[2][;]{%
\def\itemdelim{\gdef\itemdelim{#1}}%
\gdef\do##1{\itemdelim##1}%
\docsvlist{#2}}
\author{\printlist[,\\]{abc,def,ghi,jkl}}
\itemdelim
不过,您可以直接应用“技巧”\do
并直接\itemdelim
使用来跳过#1
:
\newcommand{\printlist}[2][;]{%
\def\do##1{##1\gdef\do####1{#1####1}}%
\docsvlist{#2}}
\author{\printlist[,\\]{abc,def,ghi,jkl}}
使用另一个辅助宏,\defdo
我们可以避免定义\do
全局宏(以另一个文档范围定义的宏为代价):
\newcommand*\defdo[1]{%
\def\do##1{#1\defdo{#1}##1}}%
\newcommand{\printlist}[2][;]{%
\def\do##1{##1\defdo{#1}}%
\docsvlist{#2}}%
\author{\printlist[,\\]{abc,def,ghi,jkl}}
\do
这会将行与行之间的定义隐藏起来,\\
以便可以在下一行中使用。
或者,您可以预处理列表并将其转发至\author
:
\newcommand{\savelist}[3][;]{%
\renewcommand*\do[1]{%
\newcommand*#3{##1}%
\renewcommand*\do[1]{%
\appto#3{#1####1}%
}%
}%
\docsvlist{#2}}
\savelist[,\\]{abc,def,ghi,jkl}\authors
\author{\authors}
在这种情况下,的定义\do
也是“全局的”,因为它是在文档的顶层定义的。
定义\do
全局不应该产生冲突,因为每个使用的其他代码都\do
应该自己定义它,而不需要假设任何定义。混合全局和局部分配/定义可能会很混乱,所以使用\savelist
可能更可取。
除此之外etoolbox
,LaTeX3 的l3clist
包提供了\clist_use:Nn
不需要任何定义来在列表条目之间放置某些内容( #1
= )的功能:,\\
\documentclass{article}
\ExplSyntaxOn
\DeclareDocumentCommand{\printlist}{ O{;} m}{
\clist_set:Nn \l_tmpa_clist {#2}
\clist_use:Nn \l_tmpa_clist {#1}
}
\ExplSyntaxOff
\author{\printlist[,\\]{abc,def,ghi,jkl}}
\title{Test}
\begin{document}
\maketitle
\end{document}