
私はスタックデータ構造を使用しようとしています(ここで説明されているように:プッシュ/ポップ、または長さ/寸法を保存しますか?)は、tikzmarkノード名のセットのさまざまな名前を格納するために使用します(tikzmark
マニュアル)が私のテキスト全体に散りばめられています。
スタック実装 (WE1) と\tikzmark
(WE2) は別々に完璧に動作しますが、それらの組み合わせた動作は、何らかの理由で複数のエラーと衝突します。
ポップされたスタック データ要素をコマンド内のノード名として渡そうとすると、何が問題になるのかまったくわかりません\tikzmark
(以下の MWE)。これは、LaTeX コードが \pop コマンドをすぐに評価しないことから生じる問題でしょうか ( と を試してみましたが\expandafter
、成功しませんでした...)?に\edef
渡すことも試みましたが、その方法もうまくいきませんでした...\pop{\latexstack}
\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
。
OPの元のコードを前提として、次のことを考慮してください。
\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
とエラーは消えますが、 の内容は依然として一連の LaTeX コードであり、目的のノード名ではありません。\let\act=\relax
\nodename
\popto
1 つの解決策は、スタックの一番上の値をマクロにポップし、それをノード名として使用するコマンドを用意することです(注:\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}