我正在嘗試使用堆疊資料結構(如此處討論的:推/彈出或保存長度/尺寸?)來儲存一組 tikzmark 節點名稱的各種名稱(如tikzmark
手動的)散佈在我的整個文本中。
單獨的堆疊實作(WE1)和\tikzmark
(WE2)運作得很好,但它們的組合行為在某種程度上與多個錯誤發生衝突。
\tikzmark
當我嘗試將彈出的堆疊資料元素作為命令中的節點名稱傳遞時(下面的 MWE),我無法弄清楚出了什麼問題。這是由於我的 LaTeX 代碼沒有立即評估 \pop 命令而引起的問題(我嘗試過使用\expandafter
但\edef
沒有成功...)?我也嘗試過傳遞\pop{\latexstack}
給 a \newcommand{}
,但我也沒有設法讓該方法起作用......
微量元素[不正確的組合行為...]
\documentclass{article}
\usepackage{blindtext, tikz}
\newtoks\latexstack
\latexstack={\empty}
\def\push#1#2{
\begingroup
\toks0={{#1}}
\edef\act{\endgroup\global#2={\the\toks0 \the#2}}\act
}
\def\pop#1{
\begingroup
\edef\act{\endgroup\noexpand\SplitOff\the#1(tail)#1}\act
}
\def\SplitOff#1#2(tail)#3{
\ifx#1\empty
\errhelp{Attempting to pop empty stack #3.}
\errmessage{You can't pop an empty stack.}
\else
#1\global#3={#2}
\fi
}
\newcommand\tikzmark[1]{\tikz[overlay,remember picture] \node(#1) {};}
\begin{document}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\blindtext \tikzmark{\pop{\latexstack}}\\
\blindtext \tikzmark{\pop{\latexstack}}\\
\begin{tikzpicture}[remember picture,overlay,scale=0.5]
\draw[red] (A) -- (B);
\end{tikzpicture}
\end{document}
WE1[堆疊資料結構的正確行為:A1、B2、C3和D4從資料結構中依序壓入和彈出]
\documentclass{article}
\newtoks\latexstack
\latexstack={\empty}
\def\push#1#2{
\begingroup
\toks0={{#1}}
\edef\act{\endgroup\global#2={\the\toks0 \the#2}}\act
}
\def\pop#1{
\begingroup
\edef\act{\endgroup\noexpand\SplitOff\the#1(tail)#1}\act
}
\def\SplitOff#1#2(tail)#3{
\ifx#1\empty
\errhelp{Attempting to pop empty stack #3.}
\errmessage{You can't pop an empty stack.}
\else
#1\global#3={#2}
\fi
}
\begin{document}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\push{C3}{\latexstack}
\push{D4}{\latexstack}
\pop{\latexstack},\\
\pop{\latexstack},\\
\pop{\latexstack},\\
\pop{\latexstack}.
\end{document}
WE2[正確行為\tikzmark
:A點和B點被標記,並用紅線連接在一起]
\documentclass{article}
\usepackage{blindtext, tikz}
\newcommand\tikzmark[1]{\tikz[overlay,remember picture] \node(#1) {};}
\begin{document}
\blindtext \tikzmark{A}\\
\blindtext \tikzmark{B}
\begin{tikzpicture}[remember picture,overlay,scale=0.5]
\draw[red] (A) -- (B);
\end{tikzpicture}
\end{document}
答案1
我認為這裡的問題是擴張。當 TikZ 建立節點時,節點名稱使用 完全擴展\edef
。
假設OPs原始程式碼然後考慮以下內容
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\edef\nodename{\pop{\latexstack}}
\show\nodename
這說明了完整的擴展並將給出(在日誌文件中):
! Undefined control sequence.
\pop #1^^@- \begingroup \edef \act
{\endgroup \noexpand \SplitOff \the #1(tail...
l.36 \edef\nodename{\pop{\latexstack}
}
! Undefined control sequence.
\pop ... \noexpand \SplitOff \the #1(tail)#1}\act
l.36 \edef\nodename{\pop{\latexstack}
}
> \nodename=macro:
-> \begingroup \edef {\endgroup \SplitOff {B2}{A1}\empty (tail)\latexstack }.
l.37 \show\nodename
注意問題是不是這\act
是未定義的。如果將 放在序言中的某個位置,錯誤就會消失\let\act=\relax
,但內容\nodename
仍然是一大堆 LaTeX 程式碼,而不是所需的節點名稱。
一種解決方案是使用\popto
命令將堆疊頂部的值彈出到巨集中,然後將其用作節點名稱(注意。我還重新實現了該\push
巨集):
\def\push#1#2{%
\def\tmp{{#1}}%
\expandafter\expandafter\expandafter%
#2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
\ignorespaces}
\def\popto#1#2{%
\expandafter\SplitOffTo\the#1\stop{#1}{#2}%
}
\def\SplitOffTo#1#2\stop#3#4{%
\def\tmp{#1}%
\ifx\tmp\empty%
\errhelp{Attempting to pop empty stack #3.}%
\errmessage{You can't pop an empty stack.}%
\else%
\def#4{#1}\global#3={#2}%
\fi%
}
可以這樣使用:
\newtoks\latexstack
\latexstack={\empty}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
\popto{\latexstack}{\nodename}
\tikzmark{\nodename}
\show\nodename
Some text \tikzmark{\nodename}
\popto{\latexstack}{\nodename}
\tikzmark{\nodename}
\show\nodename
Some more text \tikzmark{\nodename}
日誌檔案將顯示(類似):
> \nodename=macro:
->B2.
l.31 \show\nodename
> \nodename=macro:
->A1.
l.34 \show\nodename
如果所有這些看起來有點麻煩,那麼\popto
可以將這些內容綁定在\tikzmarkpop
巨集中:
\documentclass[border=5]{standalone}
\usepackage{tikz}
\def\push#1#2{%
\def\tmp{{#1}}%
\expandafter\expandafter\expandafter%
#2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
\ignorespaces}
\def\popto#1#2{%
\expandafter\SplitOffTo\the#1\stop{#1}{#2}%
}
\def\SplitOffTo#1#2\stop#3#4{%
\def\tmp{#1}
\ifx\tmp\empty%
\errhelp{Attempting to pop empty stack #3.}%
\errmessage{You can't pop an empty stack.}%
\else%
\def#4{#1}\global#3={#2}%
\fi}
\def\tikzmarkpop#1{%
\popto{#1}{\nodename}%
\tikz[remember picture, overlay]\coordinate(\nodename);}
\newtoks\latexstack
\latexstack={\empty}
\begin{document}
\push{A1}{\latexstack}
\push{B2}{\latexstack}
Some text\tikzmarkpop{\latexstack}
Some more text\tikzmarkpop{\latexstack}
\begin{tikzpicture}[remember picture, overlay]
\draw [red, <->] (A1) -- (B2);
\end{tikzpicture}
\end{document}