Я пытаюсь объединить структуру данных стека с \newcounter{}
определением, чтобы иметь возможность автоматически объединять вместе набор точек, разбросанных по всему тексту.
Каждая точка либо помечена как \openbracket
или \closebracket
, и автоматически спаривается с противоположно определенной точкой для формирования пар \openbracket
- \closebracket
. Закрытые пары могут быть вложены в другие пары закрытых скобок, и каждая пара открытых/закрытых точек помечена узлами tikz \node(openX) {};
и \node(closeX) {};
соответственно [где X - целое число, определяемое внешним счетчиком].
Например:
\openbraket First tier
\openbraket Second tier A
\openbraket Third tier
\closebracket
\closebracket
\openbracket Second tier B
\closebracket
\closebracket
должен автоматически объединить вышеуказанные \openbracket
\closebracket
точки в 4 пары закрытых скобок; одна скобка первого уровня, содержащая две скобки второго уровня, первая из которых (A) содержит одну скобку третьего уровня. Мой MWE должен также извлечь данные из структуры стека, чтобы узлы tikz в приведенном выше примере были определены как:
(open0) First tier (open1) Second tier A (open2) Third tier
(close2) (close1) (open3) Second tier B (close3) (close0)
Используя помощьВставить/вытащить или сохранить длину/размер?,Сохранить текущее значение счетчика в команде, иПередача данных стека в имена узлов tikzМне удалось определить рабочую структуру данных стека и придумать метод, с помощью которого можно правильно передавать данные стека в мой \tikzmark
макрос.
Однако MWE ниже явно не помещает текущее значение в bracketpairingcounter
, bracketpairingstack
а помещает дословную командную строку вместо требуемого целого числа. Таким образом, когда каждая \node(closeX) {};
метка tikz выталкивается из стека данных, каждый номер узла оценивается по последнему значению bracketpairingcounter
, вместо различных целых чисел, последовательно помещаемых в стек.
Я надеюсь, что проблему с нумерацией можно решить, заставив мой код LaTeX немедленно вычислять значение, \openbracketname
указанное ниже, но я не могу заставить себя \expandafter
работать \edef{}
в этом случае...
МВЭ
\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}
решение1
Вы хотите сделать \edef\temp{{#1}}
, но вы также можете упростить определение \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}
С \edef\tmp{{#1}\the#2}
мы полностью расширяем #1
и добавляем нерасширенное содержимое регистра токена #2, так как \the\tokenregister
не продолжает расширяться после того, \the
как действовал, чтобы доставить содержимое регистра. Затем мы устанавливаем, #2
чтобы содержать расширение (только один уровень) \tmp
.
Обратите внимание, что это \ignorespaces
не нужно, так как вызов \push
обнаружит \tikzmark
; на самом деле это может привести к несвоевременным расширениям (не в этом случае).