在這個帖子,我發現了一個處理清單的好技巧。下面的程式碼允許使用可選的分隔符號參數列印清單。
\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
命令中與 newline 結合使用\\
,則這將無法正常工作:僅為列表的第一個元素設定換行符。對於所有其他元素,換行符號將被忽略:
\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}
和 for 相同\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
for\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
這會將from row的定義隱藏在 the 後面\\
,以便它在下一行中可用。
或者,您可以預處理清單並將其轉發到\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
global 不應產生衝突,因為使用的所有其他程式碼都\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}