
Ich möchte einenMakro&
um die Trennzeichen ( , \\
) festzulegenin einer tabellarischen Umgebung. Das Makro soll dabei als Boolescher Schalter mit drei Zuständen fungieren. Leider erhalte ich immer wieder folgendes Ergebnis:
Ich habe das Makro bereits außerhalb der tabellarischen Umgebung ausprobiert und es funktionierte einwandfrei. Ich glaube, das Problem tritt aufgrund eines Erweiterungsproblems auf, weiß aber nicht, wie ich es beheben kann. Ich habe auch versucht, ein \DeclareRobustCommand
oder zu verwenden \protect
, aber das Ergebnis wurde dadurch nicht beeinflusst.
Hier ist der Code, den ich verwendet habe:
\documentclass{article}
\usepackage{etoolbox}
% Define command for automatic setting of delimeters
% Usage: \setdelim{<delim1>}{<delim2>}
\newbool{startflag}
\newbool{delimflag}
\newcommand*{\setdelim}[2]{%
\ifbool{startflag}{
\ifbool{delimflag}{% if true
#1
\boolfalse{delimflag}\ignorespaces
}{}% false is somehow not working in tabular environment}
\notbool{delimflag}{% if false
#2
\booltrue{delimflag}\ignorespaces
}{}% true is as well not working in tabular environment}
}{%
\setbool{startflag}{true}
\setbool{delimflag}{true}\ignorespaces
}
}
\begin{document}
\begin{tabular}{|l|l|}
\setdelim{init}{init} a
\setdelim{\span}{\cr} b
\setdelim{\span}{\cr} c
\setdelim{\span}{\cr} d
\end{tabular}
\end{document}
Bearbeiten:
Für diejenigen unter Ihnen, die sich immer noch fragen, was der Grund für diese ganze Cargo-Kult-Programmierung ist. Ich verwende \setdelim
den folgenden Befehl (modifizierter Befehl von posquit0s awesome-cv), um einige optionale Informationen für den CV-Header abzutrennen.
\newcommand*{\@headersocial}[3][unframed]{%
\global\boolfalse{startflag}% reset startflag
\ifthenelse{\isundefined{\@address}}%
{}{%
\@setdelim{##2}{##3}%
\icon[##1]{\acvHeaderIconSize}{MapMarker}{\@address}%
}%
\ifthenelse{\isundefined{\@mobile}}%
{}{%
\@setdelim{##2}{##3}%
\icon[##1]{\acvHeaderIconSize}{Mobile}{\@mobile}%
}%
\ifthenelse{\isundefined{\@email}}%
{}{%
\@setdelim{##2}{##3}%
\href{mailto:\@email}{\icon[##1]{\acvHeaderIconSize}{Envelope}{\@email}}%
}%
\ifthenelse{\isundefined{\@homepage}}%
{}{%
\@setdelim{##2}{##3}%
\href{http://\@homepage}{\icon[##1]{\acvHeaderIconSize}{Home}{\@homepage}}%
}%
\ifthenelse{\isundefined{\@github}}%
{}{%
\@setdelim{##2}{##3}%
\href{https://github.com/\@github}{\icon[##1]{\acvHeaderIconSize}{GithubSquare}{\@github}}%
}%
\ifthenelse{\isundefined{\@linkedin}}%
{}{%
\@setdelim{##2}{##3}%
\href{https://www.linkedin.com/in/\@linkedin}{\icon[##1]{\acvHeaderIconSize}{Linkedin}{\@linkedin}}%
}%
\ifthenelse{\isundefined{\@skype}}%
{}{%
\@setdelim{##2}{##3}%
\icon[##1]{\acvHeaderIconSize}{Skype}{\@skype}%
}%
\ifthenelse{\isundefined{\@extrainfo}}%
{}{%
\@setdelim{##2}{##3}%
\@extrainfo%
}%
}
Mit diesem Befehl kann ich eine Kopfzeile in einer tabellarischen Umgebung drucken, wie in der folgenden Abbildung gezeigt:
Oder so mit normalen Trennzeichen:
Antwort1
Das Problem besteht darin, dass Ihre booleschen Zustände nicht über Spalten und Zeilen hinweg gespeichert werden, da jede Zelle eine Gruppe bildet. Das Voranstellen der \booltrue
und \boolfalse
-Aufrufe mit \global
sollte dieses Problem lösen. Denken Sie daran, dass Sie die booleschen Werte für ein neues Array auf „false“ zurücksetzen müssen.
\documentclass{article}
\usepackage{etoolbox}
% Define command for automatic setting of delimeters
% Usage: \setdelim{<delim1>}{<delim2>}
\newbool{startflag}
\newbool{delimflag}
\newcommand*{\setdelim}[2]
{%
\ifbool{startflag}
{%
\ifbool{delimflag}
{%
#1%
\global\boolfalse{delimflag}%
}
{%
#2%
\global\booltrue{delimflag}%
}%
}
{%
\global\booltrue{startflag}%
\global\booltrue{delimflag}%
}%
\ignorespaces
}
\begin{document}
\begin{tabular}{|l|l|}
\setdelim{init}{init} a
\setdelim{&}{\\} b
\setdelim{&}{\\} c
\setdelim{&}{\\} d
\end{tabular}
\end{document}
Mit der Idee von@UlrichDiezUm die Argumente {init}{init}
als weiteres Flag zu verwenden, können wir es auch ohne globale Zuweisungen zum Laufen bringen. Im Folgenden muss jede neue Zelle mit gestartet werden \setdelim
. Da der Boolean immer erst gesetzt wird, nachdem die nächste Zelle gestartet wurde (nach #1
und #2
), wird der Status auf die nächste Zelle übertragen.
Ich habe expl3
für dieses Beispiel Syntax verwendet, um einfachen Zugriff auf \str_if_eq:nnTF
(eine Funktion, die die beiden Argumente als Zeichenfolgen vergleicht) zu haben. Auf diese Weise brauche ich nicht den ziemlich komplizierten Test für beide Argumente, init
den @UlrichDiez bereitstellt. Andere Lösungen, um diesen Test ohne zu erhalten, expl3
sind natürlich möglich. Beachten Sie, dass Leerzeichen zwischen \ExplSyntaxOn
und \ExplSyntaxOff
ignoriert werden, sodass ich nicht jedes Zeilenende kommentieren muss.
\documentclass[]{article}
\ExplSyntaxOn
\bool_new:N \l__erdinale_setdelim_bool
\cs_new_protected:Npn \erdinale_setdelim:nn #1#2
{
\str_if_eq:nnTF { {#1} {#2} } { {init} {init} }
{ \bool_set_true:N \l__erdinale_setdelim_bool }
{
\bool_if:NTF \l__erdinale_setdelim_bool
{
#1
\bool_set_false:N \l__erdinale_setdelim_bool
}
{
#2
\bool_set_true:N \l__erdinale_setdelim_bool
}
}
}
\cs_new_eq:NN \setdelim \erdinale_setdelim:nn
\ExplSyntaxOff
\begin{document}
\begin{tabular}{|l|l|}
\setdelim{init}{init} a
\setdelim{&}{\\} b
\setdelim{&}{\\} c
\setdelim{&}{\\} d
\end{tabular}
\begin{tabular}{|l|l|}
\setdelim{init}{init} a
\setdelim{&}{\\} b
\setdelim{&}{\\} c
\setdelim{&}{\\} d
\end{tabular}
\end{document}
Antwort2
Wenn Sie bereit sind, den Hauptteil jeder tabellarischen Umgebung mit zu beginnen , können Sie den Fall der Verkettung des ersten und zweiten Arguments von \setdelim{init}{init}
herausarbeiten, was die Sequenz ergibt , und mit nur einem Flag auskommen.\setdelim
initinit
\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\newcommand\CheckWhetherinitinit[1]{%
\ifcat$\detokenize\expandafter{\gobbletoexclam#1!}$%
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
% As #1 can contain & and \\ \@firstofone{...} is needed to "hide" #1 from the tabular/alignment.
{\expandafter\@firstofone\expandafter{\forkinitinit#1!{\@firstoftwo}initinit!{\@secondoftwo}!!!}}%
{\@secondoftwo}%
}%
\@ifdefinable\forkinitinit{\long\def\forkinitinit#1initinit!#2#3!!!{#2}}%
\@ifdefinable\gobbletoexclam{\long\def\gobbletoexclam#1!{}}%
\makeatother
% Define command for automatic setting of delimeters
% Usage: \setdelim{<delim1>}{<delim2>}
\newbool{delimflag}
\newcommand*{\setdelim}[2]{%
\CheckWhetherinitinit{#1#2}{%
\booltrue{delimflag}%
}{%
\ifbool{delimflag}{%
#1%
\boolfalse{delimflag}%
}{%
#2%
\booltrue{delimflag}%
}%
}%
}%
\begin{document}
\begin{tabular}{|l|l|}
\setdelim{init}{init} a
\setdelim{&}{\\} b
\setdelim{&}{\\} c
\setdelim{&}{\\} d
\end{tabular}
\begin{tabular}{|l|l|}
\setdelim{init}{init} a
\setdelim{&}{\\} b
\setdelim{&}{\\} c
\setdelim{&}{\\} d
\end{tabular}
\end{document}
(Ehrlich gesagt, ich weiß nicht, was der Vorteil von
\begin{tabular}{|l|l|}
\setdelim{init}{init} a
\setdelim{&}{\\} b
\setdelim{&}{\\} c
\setdelim{&}{\\} d
\end{tabular}
gegenüber der deutlich kürzeren
\begin{tabular}{|l|l|}
a&b\\
c&d
\end{tabular}
Ist.)