\newcounter{}
나는 텍스트 전체에 흩어져 있는 포인트 모음을 자동으로 쌍으로 연결할 수 있도록 스택 데이터 구조를 정의와 결합하려고 합니다 .
각 포인트는 \openbracket
또는 a 로 표시되며 쌍 을 \closebracket
형성하기 위해 반대로 정의된 포인트와 자동으로 쌍을 이룹니다 . 닫힌 쌍은 다른 닫힌 괄호 쌍 안에 중첩될 수 있으며, 열린/닫힌 점의 각 쌍은 각각 tikz 노드로 표시됩니다 ( 여기서 X는 외부 카운터에 의해 정의된 정수임).\openbracket
\closebracket
\node(openX) {};
\node(closeX) {};
예를 들어:
\openbraket First tier
\openbraket Second tier A
\openbraket Third tier
\closebracket
\closebracket
\openbracket Second tier B
\closebracket
\closebracket
위의 \openbracket
\closebracket
점을 4개의 닫힌 브래킷 쌍으로 자동으로 쌍을 이루어야 합니다. 두 개의 두 번째 계층 브래킷을 포함하는 첫 번째 계층 브래킷 1개, 첫 번째(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{}
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}
답변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}
우리는 토큰 레지스터 #2의 확장되지 않은 콘텐츠를 \edef\tmp{{#1}\the#2}
완전히 확장 하고 추가합니다. 왜냐하면 레지스터의 콘텐츠를 전달한 후에는 확장이 진행되지 않기 때문입니다. 그런 다음 .#1
\the\tokenregister
\the
#2
\tmp
를 \ignorespaces
호출 \push
하면 \tikzmark
; 실제로는 시기적절하지 않은 확장이 발생할 수 있습니다(이 경우는 아님).