Pasar datos de la pila a nombres de nodos tikz

Pasar datos de la pila a nombres de nodos tikz

Estoy intentando utilizar una estructura de datos de pila (como se explica aquí:¿Empujar/pop o guardar una longitud/dimensión?) para almacenar los distintos nombres de un conjunto de nombres de nodos de tikzmark (como se explica entikzmarkmanual) dispersos a lo largo de mi texto.

Por separado, la implementación de la pila (WE1) y \tikzmark(WE2) funcionan perfectamente, pero sus comportamientos combinados de alguna manera chocan con múltiples errores.

Por mi vida, no puedo descubrir qué está saliendo mal cuando intento pasar los elementos de datos de la pila emergente como nombres de nodos dentro de un \tikzmarkcomando (MWE a continuación). ¿Es este un problema que surge de que mi código LaTeX no evalúa inmediatamente los comandos \pop (he intentado jugar con ellos \expandaftery \edefsin éxito...)? También intenté pasar \pop{\latexstack}a a \newcommand{}, pero tampoco logré que ese método funcione...

MWE[Comportamientos combinados incorrectos...]

\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[Comportamiento correcto de la estructura de datos de la pila: A1, B2, C3 y D4 se insertan y extraen secuencialmente de la estructura de datos]

\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[Comportamiento correcto de \tikzmark: Los puntos A y B están marcados y conectados entre sí con una línea roja]

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

Respuesta1

Creo que el problema aquí es la expansión. Cuando TikZ crea nodos, el nombre del nodo se expande completamente usando \edef.

Suponiendo el código original de los OP, considere lo siguiente

\push{A1}{\latexstack}
\push{B2}{\latexstack}
\edef\nodename{\pop{\latexstack}}
\show\nodename

Esto ilustra la expansión completa y dará (en el archivo de registro):

! 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

Tenga en cuenta que el problema esnoeso \actno está definido. Los errores desaparecerán si \let\act=\relaxse colocan en algún lugar del preámbulo, pero el contenido \nodenamesigue siendo un montón de código LaTeX, no el nombre del nodo deseado.

Una solución es tener un \poptocomando que muestre el valor en la parte superior de la pila en una macro que luego se use como nombre de nodo (NB. También reimplementé la \pushmacro):

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

Esto se puede utilizar así:

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

El archivo de registro mostrará (algo como) esto:

> \nodename=macro:
->B2.
l.31 \show\nodename

> \nodename=macro:
->A1.
l.34 \show\nodename

Si todo eso parece un poco molesto, entonces \poptotodo podría estar vinculado en una \tikzmarkpopmacro:

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

ingrese la descripción de la imagen aquí

información relacionada