如果 \author 处理另一个命令的输出,则其中缺少换行符

如果 \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
\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}

失败案例

如果我使用没有换行符的分隔符,例如::,上述内容将按预期工作。

成功测试 1

\\在命令中添加额外的换行符\author也会导致预期的结果:

\author{\printlisti[::]{abc,def,ghi}\\123\\456\\789}

成功测试 2

看起来\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}

相关内容