Estou tentando combinar uma estrutura de dados de pilha com uma \newcounter{}
definição para poder emparelhar automaticamente uma coleção de pontos espalhados pelo meu texto.
Cada ponto é marcado como um \openbracket
ou um \closebracket
e automaticamente emparelhado com um ponto definido de forma oposta para formar \openbracket
pares \closebracket
. Pares fechados podem ser aninhados dentro de outros pares de colchetes fechados, e cada par de pontos abertos/fechados são marcados com os nós tikz \node(openX) {};
e \node(closeX) {};
respectivamente [onde X é um número inteiro definido por um contador externo].
Por exemplo:
\openbraket First tier
\openbraket Second tier A
\openbraket Third tier
\closebracket
\closebracket
\openbracket Second tier B
\closebracket
\closebracket
deve emparelhar automaticamente os \openbracket
\closebracket
pontos acima em 4 pares de colchetes fechados; um colchete de primeiro nível, contendo dois colchetes de segundo nível, o primeiro (A) dos quais contém um único colchete de terceiro nível. Meu MWE também deve extrair dados da estrutura da pilha para que os nós tikz no exemplo acima sejam definidos como:
(open0) First tier (open1) Second tier A (open2) Third tier
(close2) (close1) (open3) Second tier B (close3) (close0)
Usando a ajuda deEmpurrar/Pop ou salvar um comprimento/dimensão?,Salva o valor atual do contador em um comando, ePassando dados da pilha para nomes de nós tikz, consegui definir uma estrutura de dados de pilha funcional e descobri um método para passar corretamente os dados da pilha para minha \tikzmark
macro.
No entanto, o MWE abaixo não envia explicitamente o valor atual de bracketpairingcounter
para bracketpairingstack
e envia a string de comando literal em vez do número inteiro necessário. Assim, quando cada \node(closeX) {};
marca tikz é retirada da pilha de dados, cada número de nó é avaliado no último valor de bracketpairingcounter
, em vez dos diferentes números inteiros colocados sequencialmente na pilha.
Espero que o problema de numeração possa ser corrigido forçando de alguma forma meu código LaTeX a avaliar imediatamente o valor \openbracketname
abaixo, mas não consigo, de forma alguma, obter \expandafter
ou \edef{}
trabalhar neste 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}
Responder1
Você deseja fazer isso \edef\temp{{#1}}
, mas também pode simplificar a definição \push
e outras partes do código.
\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}
Com \edef\tmp{{#1}\the#2}
expandimos #1
e adicionamos completamente o conteúdo não expandido do registrador token #2, já que \the\tokenregister
não continua expandindo após \the
ter agido para entregar o conteúdo do registrador. Então definimos #2
para conter a expansão (apenas um nível) de \tmp
.
Observe que isso \ignorespaces
é desnecessário, pois a chamada de \push
will find \tikzmark
; na verdade, isso poderia causar expansões prematuras (não neste caso).