Ich versuche, eine Stapeldatenstruktur zu verwenden (wie hier beschrieben:Push/Pop oder Länge/Dimension speichern?), um die verschiedenen Namen einer Reihe von Tikzmark-Knotennamen zu speichern (wie intikzmark
Handbuch) über den gesamten Text verstreut.
Getrennt voneinander funktionieren die Stapelimplementierungen (WE1) und \tikzmark
(WE2) einwandfrei, ihr kombiniertes Verhalten führt jedoch zu Konflikten und zahlreichen Fehlern.
Ich kann beim besten Willen nicht herausfinden, was schief läuft, wenn ich versuche, die aus dem Stapel entfernten Datenelemente als Knotennamen innerhalb eines \tikzmark
Befehls zu übergeben (MWE weiter unten). Ist das ein Problem, das dadurch entsteht, dass mein LaTeX-Code die \pop-Befehle nicht sofort auswertet (ich habe damit herumgespielt, \expandafter
aber \edef
ohne Erfolg...)? Ich habe auch versucht, \pop{\latexstack}
an ein zu übergeben \newcommand{}
, aber ich habe es auch nicht geschafft, diese Methode zum Laufen zu bringen...
MWE[Falsches kombiniertes Verhalten...]
\documentclass{article}
\usepackage{blindtext, tikz}
\newtoks\latexstack
\latexstack={\empty}
\def\push#1#2{
\begingroup
\toks0={{#1}}
\edef\act{\endgroup\global#2={\the\toks0 \the#2}}\act
}
\def\pop#1{
\begingroup
\edef\act{\endgroup\noexpand\SplitOff\the#1(tail)#1}\act
}
\def\SplitOff#1#2(tail)#3{
\ifx#1\empty
\errhelp{Attempting to pop empty stack #3.}
\errmessage{You can't pop an empty stack.}
\else
#1\global#3={#2}
\fi
}
\newcommand\tikzmark[1]{\tikz[overlay,remember picture] \node(#1) {};}
\begin{document}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\blindtext \tikzmark{\pop{\latexstack}}\\
\blindtext \tikzmark{\pop{\latexstack}}\\
\begin{tikzpicture}[remember picture,overlay,scale=0.5]
\draw[red] (A) -- (B);
\end{tikzpicture}
\end{document}
WE1[Korrektes Verhalten der Stack-Datenstruktur: A1, B2, C3 und D4 werden in die Datenstruktur hineingepusht und nacheinander wieder herausgepoppt]
\documentclass{article}
\newtoks\latexstack
\latexstack={\empty}
\def\push#1#2{
\begingroup
\toks0={{#1}}
\edef\act{\endgroup\global#2={\the\toks0 \the#2}}\act
}
\def\pop#1{
\begingroup
\edef\act{\endgroup\noexpand\SplitOff\the#1(tail)#1}\act
}
\def\SplitOff#1#2(tail)#3{
\ifx#1\empty
\errhelp{Attempting to pop empty stack #3.}
\errmessage{You can't pop an empty stack.}
\else
#1\global#3={#2}
\fi
}
\begin{document}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\push{C3}{\latexstack}
\push{D4}{\latexstack}
\pop{\latexstack},\\
\pop{\latexstack},\\
\pop{\latexstack},\\
\pop{\latexstack}.
\end{document}
WE2[Richtiges Verhalten \tikzmark
: Die Punkte A und B werden markiert und mit einer roten Linie miteinander verbunden]
\documentclass{article}
\usepackage{blindtext, tikz}
\newcommand\tikzmark[1]{\tikz[overlay,remember picture] \node(#1) {};}
\begin{document}
\blindtext \tikzmark{A}\\
\blindtext \tikzmark{B}
\begin{tikzpicture}[remember picture,overlay,scale=0.5]
\draw[red] (A) -- (B);
\end{tikzpicture}
\end{document}
Antwort1
Ich denke, das Problem hier ist die Erweiterung. Wenn TikZ Knoten erstellt, wird der Knotenname vollständig mit erweitert \edef
.
Unter der Annahme des ursprünglichen Codes des OPs sollten Sie Folgendes berücksichtigen
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\edef\nodename{\pop{\latexstack}}
\show\nodename
Dies veranschaulicht die vollständige Erweiterung und ergibt (in der Protokolldatei):
! Undefined control sequence.
\pop #1^^@- \begingroup \edef \act
{\endgroup \noexpand \SplitOff \the #1(tail...
l.36 \edef\nodename{\pop{\latexstack}
}
! Undefined control sequence.
\pop ... \noexpand \SplitOff \the #1(tail)#1}\act
l.36 \edef\nodename{\pop{\latexstack}
}
> \nodename=macro:
-> \begingroup \edef {\endgroup \SplitOff {B2}{A1}\empty (tail)\latexstack }.
l.37 \show\nodename
Beachten Sie, dass das Problem istnichtdas \act
ist nicht definiert. Die Fehler verschwinden, wenn \let\act=\relax
irgendwo in der Präambel platziert wird, aber der Inhalt von \nodename
ist immer noch ein ganzer Haufen LaTeX-Code und nicht der gewünschte Knotenname.
Eine Lösung besteht darin, einen Befehl zu verwenden \popto
, der den Wert oben auf dem Stapel in ein Makro einfügt, das dann als Knotenname verwendet wird (NB. Ich habe das \push
Makro auch neu implementiert):
\def\push#1#2{%
\def\tmp{{#1}}%
\expandafter\expandafter\expandafter%
#2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
\ignorespaces}
\def\popto#1#2{%
\expandafter\SplitOffTo\the#1\stop{#1}{#2}%
}
\def\SplitOffTo#1#2\stop#3#4{%
\def\tmp{#1}%
\ifx\tmp\empty%
\errhelp{Attempting to pop empty stack #3.}%
\errmessage{You can't pop an empty stack.}%
\else%
\def#4{#1}\global#3={#2}%
\fi%
}
Dies kann wie folgt verwendet werden:
\newtoks\latexstack
\latexstack={\empty}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\popto{\latexstack}{\nodename}
\tikzmark{\nodename}
\show\nodename
Some text \tikzmark{\nodename}
\popto{\latexstack}{\nodename}
\tikzmark{\nodename}
\show\nodename
Some more text \tikzmark{\nodename}
In der Protokolldatei wird (ungefähr) Folgendes angezeigt:
> \nodename=macro:
->B2.
l.31 \show\nodename
> \nodename=macro:
->A1.
l.34 \show\nodename
Wenn Ihnen das alles zu lästig erscheint, \popto
können Sie es auch in einem Makro zusammenfassen \tikzmarkpop
:
\documentclass[border=5]{standalone}
\usepackage{tikz}
\def\push#1#2{%
\def\tmp{{#1}}%
\expandafter\expandafter\expandafter%
#2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
\ignorespaces}
\def\popto#1#2{%
\expandafter\SplitOffTo\the#1\stop{#1}{#2}%
}
\def\SplitOffTo#1#2\stop#3#4{%
\def\tmp{#1}
\ifx\tmp\empty%
\errhelp{Attempting to pop empty stack #3.}%
\errmessage{You can't pop an empty stack.}%
\else%
\def#4{#1}\global#3={#2}%
\fi}
\def\tikzmarkpop#1{%
\popto{#1}{\nodename}%
\tikz[remember picture, overlay]\coordinate(\nodename);}
\newtoks\latexstack
\latexstack={\empty}
\begin{document}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
Some text\tikzmarkpop{\latexstack}
Some more text\tikzmarkpop{\latexstack}
\begin{tikzpicture}[remember picture, overlay]
\draw [red, <->] (A1) -- (B2);
\end{tikzpicture}
\end{document}