我正在嘗試將堆疊資料結構與\newcounter{}
定義結合起來,以便我可以自動將分散在文字中的點的集合配對在一起。
每個點都標記為 an\openbracket
或 a \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
;實際上它可能會導致不合時宜的擴張(不是在這種情況下)。