Estoy intentando combinar una estructura de datos de pila con una \newcounter{}
definición para poder emparejar automáticamente una colección de puntos dispersos por todo mi texto.
Cada punto se marca como \openbracket
o \closebracket
y se empareja automáticamente con un punto definido de manera opuesta para formar \openbracket
pares \closebracket
. Los pares cerrados pueden anidarse dentro de otros pares de corchetes cerrados, y cada par de puntos abiertos/cerrados están marcados con los nodos tikz \node(openX) {};
y \node(closeX) {};
respectivamente [donde X es un número entero definido por un contador externo].
Por ejemplo:
\openbraket First tier
\openbraket Second tier A
\openbraket Third tier
\closebracket
\closebracket
\openbracket Second tier B
\closebracket
\closebracket
debería emparejar automáticamente los \openbracket
\closebracket
puntos anteriores en 4 pares de corchetes cerrados; un grupo de primer nivel, que contiene dos grupos de segundo nivel, el primero (A) de los cuales contiene un único grupo de tercer nivel. Mi MWE también debería extraer datos de la estructura de la pila para que los nodos tikz en el ejemplo anterior se definan como:
(open0) First tier (open1) Second tier A (open2) Third tier
(close2) (close1) (open3) Second tier B (close3) (close0)
Usando la ayuda de¿Empujar/pop o guardar una longitud/dimensión?,Guardar el valor actual del contador en un comando, yPasar datos de la pila a nombres de nodos tikz, Logré definir una estructura de datos de pila funcional y descubrí un método con el cual pasar correctamente los datos de la pila a mi \tikzmark
macro.
Sin embargo, el MWE a continuación no inserta explícitamente el valor actual de bracketpairingcounter
en bracketpairingstack
e inserta la cadena de comando textual en lugar del número entero requerido. Por lo tanto, cuando cada \node(closeX) {};
marca tikz se extrae de la pila de datos, cada número de nodo se evalúa con el último valor de bracketpairingcounter
, en lugar de los diferentes números enteros insertados secuencialmente en la pila.
Espero que el problema de numeración pueda solucionarse obligando de alguna manera a mi código LaTeX a evaluar inmediatamente el valor de \openbracketname
abajo, pero no puedo por mi vida conseguir \expandafter
o \edef{}
trabajar en este caso...
MWE
\documentclass[openany]{article}
\usepackage{tikz}
%Define stack data structure commands (\push, \pop, \splitstack)
\newtoks\braketpairingstack
\braketpairingstack={\empty}
\def\push#1#2{%
\def\tmp{{#1}}%
\expandafter\expandafter\expandafter%
#2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
\ignorespaces}
\def\pop#1#2{%
\expandafter\splitstack\the#1\stop{#1}{#2}%
}
\def\splitstack#1#2\stop#3#4{%
\def\tmp{#1}
\ifx\tmp\empty
\else
\def#4{#1}\global#3={#2}%
\fi
}
%Define \tikzmark command
\def\tikzmark#1{%
\tikz[remember picture, overlay]\node[red](#1) {#1};%
}
%Define bracket pair counting commands (\openbracket, \closebracket)
\newcounter{bracketpairingcounter}
\newcommand{\openbraket}{%
\expandafter\edef\csname openbracketname\endcsname{\thebracketpairingcounter}%
\push{\openbracketname}{\braketpairingstack}%
\tikzmark{open\openbracketname}%
\stepcounter{bracketpairingcounter}%
}
\newcommand{\closebraket}{%
\pop{\braketpairingstack}{\closebracketname}%
\tikzmark{close\closebracketname}%
}
%Begin MWE document
\begin{document}
\openbraket Open first bracket.\\ %Correctly marked as open0
\openbraket Open second bracket.\\ %Correctly marked as open1
Close second bracket. \closebraket\\ %Correctly marked as close1
Close first bracket. \closebraket\\ %Incorrectly marked as close1
\end{document}
Respuesta1
Quieres hacerlo , pero también \edef\temp{{#1}}
puedes simplificar la definición y otras partes del código.\push
\documentclass[openany]{article}
\usepackage{tikz}
%Define stack data structure commands (\push, \pop, \splitstack)
\newtoks\braketpairingstack
\braketpairingstack={\empty}
\def\push#1#2{%
\edef\tmp{{#1}\the#2}%
#2=\expandafter{\tmp}%
}
\def\pop#1#2{%
\expandafter\splitstack\the#1\stop{#1}{#2}%
}
\def\splitstack#1#2\stop#3#4{%
\def\tmp{#1}%
\ifx\tmp\empty
\else
\def#4{#1}\global#3={#2}%
\fi
}
%Define \tikzmark command
\def\tikzmark#1{%
\tikz[remember picture, overlay]\node[red](#1) {#1};%
}
%Define bracket pair counting commands (\openbracket, \closebracket)
\newcounter{bracketpairingcounter}
\newcommand{\openbraket}{%
\edef\openbracketname{\thebracketpairingcounter}%
\push{\openbracketname}{\braketpairingstack}%
\tikzmark{open\openbracketname}%
\stepcounter{bracketpairingcounter}%
}
\newcommand{\closebraket}{%
\pop{\braketpairingstack}{\closebracketname}%
\tikzmark{close\closebracketname}%
}
%Begin MWE document
\begin{document}
\openbraket Open first bracket. %Correctly marked as open0
\openbraket Open second bracket. %Correctly marked as open1
Close second bracket. \closebraket %Correctly marked as close1
Close first bracket. \closebraket %Correctly marked as close0
\end{document}
Con \edef\tmp{{#1}\the#2}
expandimos #1
y agregamos completamente el contenido no expandido del registro de token #2, ya que \the\tokenregister
no continúa expandiéndose después de \the
haber actuado para entregar el contenido del registro. Luego configuramos #2
para contener la expansión (solo un nivel) de \tmp
.
Tenga en cuenta que \ignorespaces
es innecesario, ya que la llamada de \push
will find \tikzmark
; de hecho podría provocar ampliaciones inoportunas (no en este caso).