Übergeben von Stapeldaten an Tikz-Knotennamen

Übergeben von Stapeldaten an Tikz-Knotennamen

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 intikzmarkHandbuch) ü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 \tikzmarkBefehls 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, \expandafteraber \edefohne 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 \actist nicht definiert. Die Fehler verschwinden, wenn \let\act=\relaxirgendwo in der Präambel platziert wird, aber der Inhalt von \nodenameist 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 \pushMakro 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, \poptokö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}

Bildbeschreibung hier eingeben

verwandte Informationen