Zeilenumbrüche fehlen in \author, wenn es die Ausgabe eines anderen Befehls verarbeitet

Zeilenumbrüche fehlen in \author, wenn es die Ausgabe eines anderen Befehls verarbeitet

Indieser BeitragIch habe einen netten Trick für den Umgang mit Listen gefunden. Der folgende Code ermöglicht das Drucken von Listen mit einem optionalen Trennzeichenargument.

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

Verwende ich es allerdings \printlistinnerhalb des \authorBefehls in Kombination mit einem newline \\, funktioniert das nicht: Der Zeilenumbruch wird nur für das erste Element der Liste gesetzt. Für alle anderen Elemente wird der Zeilenumbruch ignoriert:

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

Scheiternder Fall

Wenn ich ein Trennzeichen ohne Zeilenumbruch verwende, z. B. ::, funktioniert das oben genannte wie erwartet.

Erfolgreicher Test 1

Das Einfügen zusätzlicher Zeilenumbrüche \\in den \authorBefehl führt ebenfalls zum erwarteten Ergebnis:

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

Erfolgreicher Test 2

Es scheint, dass die Kombination \printlistmit Zeilenumbrüchen \\ein Problem verursacht. Wie kommt das?

Antwort1

Das Argument für \authorwird in einem gesetzt tabular. Jede Zelle bildet ihre eigene Gruppe, daher bleiben die interne Definition von \itemdelimund die Definition von \donicht in Ihrer ersten Zeile erhalten.

Im Wesentlichen passiert Folgendes:

\begin{tabular}{c}
  \def\itemdelim{test} \\
  \itemdelim
\end{tabular}

und dasselbe für \do, wobei die zweite Zeile jedoch die gleiche Definition wie außerhalb von hat tabularund nicht zu einer Fehlermeldung führt.


Sie müssen die Definitionen \itemdelim(für den nicht ersten Eintrag) und \doglobal vornehmen:

\newcommand{\printlist}[2][;]{%
  \def\itemdelim{\gdef\itemdelim{#1}}%
  \gdef\do##1{\itemdelim##1}%
  \docsvlist{#2}}
\author{\printlist[,\\]{abc,def,ghi,jkl}}

Sie können jedoch den „Trick“ anwenden, \itemdelimdirekt für \dound überspringen, \itemdelimindem Sie #1direkt verwenden:

\newcommand{\printlist}[2][;]{%
  \def\do##1{##1\gdef\do####1{#1####1}}%
  \docsvlist{#2}}
\author{\printlist[,\\]{abc,def,ghi,jkl}}

Mit einem weiteren Hilfsmakro wie \defdokönnen wir eine \doglobale Definition vermeiden (auf Kosten eines weiteren dokumentweit definierten Makros):

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

Dadurch wird die Definition von \dovon Zeile zu Zeile hinter das verschoben \\, sodass sie in der nächsten Zeile verfügbar ist.


Alternativ können Sie die Liste vorverarbeiten und einfach weiterleiten an \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}

In diesem Fall ist die Definition \doauch „global“, da sie auf der obersten Ebene des Dokuments definiert ist.

Die Definition \dovon global sollte keinen Konflikt verursachen, da jeder andere Code, der es verwendet, \does selbst definiert haben sollte, ohne eine Definition anzunehmen. Mischen von globalen und lokalen Zuweisungen/Definitionenkönnte chaotisch sein, daher \savelistist die Verwendung möglicherweise vorzuziehen.


Darüber hinaus bietet etoolboxdas LaTeX3- l3clistPaket Folgendes \clist_use:Nn, das keine Definitionen benötigt, um einfach etwas ( #1= ,\\) zwischen die Einträge einer Liste zu setzen:

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

verwandte Informationen