这个问题的提出源于tikzmark
Andrew Stacey 创建的宏的行为,以及最近与 David Carlisle 在聊天中的讨论。
我注意到使用 LaTeX 代码tikzmark
通常需要多次编译运行。第一次运行后,会绘制一个图片,但 LaTeX 输出中没有迹象表明需要第二次运行。自动化工具和人类也依赖 LaTeX 输出来确定是否需要更多重新编译。David 告诉我,可以将代码添加到宏中,以便它向 LaTeX 日志输出适当的消息,说明代码需要重新运行或类似情况。我在 emacs 中使用 AucTeX,它肯定会使用输出中的信息来确定是否需要再次运行 LaTeX。
我不知道tikzmark
宏是如何工作的,也不知道判断何时需要重新运行代码有多困难,但是有人知道如何向宏添加代码tikzmark
来实现这一点吗?
例如,参见 Peter Grill 的解决方案到如何在等式各部分之间画箭头来显示数学分配律(乘法)?
注:Andrew Stacey 已添加tikzmark
到Launchpad 上的 tex-sx 项目。存储库位于http://bazaar.launchpad.net/~tex-sx/tex-sx/development/files. 实际文件是tikzmark.dtx(tex tikzmark.dtx
生成文件)。还有tikzmark_测试.tex这是测试文件,可能会提供一些关于如何使用它的提示。
更新:对于 AucTeX 用户,请注意 AucTeX 会寻找非常具体的字符串,正如 Heiko 所指出的那样。更改
\immediate\write\@auxout{Rerun Latex tikz mark #1 changed}
到
\immediate\write\@auxout{LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.}
在 David 的例子中,AucTeX 会注意到并强制重新运行 LaTeX。
关于 Heiko 的解决方案,您可以在 PDF 文件的第 4.5 节中找到hopgf.dtx
有关分离的说明。我不知道如何使用 Acrobat Reader 分离文件,但替代方法是hopgf-1.0.pdf
hopgf-1.0.pdf
pdftk hopgf-1.0.pdf unpack_files output .
hopgf.sty
有效。然后使用以下方法提取样式文件:
tex hopgf.dtx
然后只需\usepackage{hopgf}
输入任何使用的示例\tikzmark
,就像 Peter Grill 之前在这个问题中链接的示例一样,就会出现通常的 LaTeX 警告
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
出现,正如 Heiko 所说。这是可行的,因为正如 cyberSingularity 在评论中提到的那样,\tikzmark
通过写入\pgfsyspdfmark
辅助文件来工作,hopgf.sty
如果我理解正确的话,重写此宏以输出此警告。这似乎是一个很好的通用解决方案,我希望 Heiko 的补丁可以纳入 PGF/TikZ。
答案1
我编写了一个新包hopgf
,尝试在其中收集一些针对 PGF/TikZ 的修复。同时还解决了缺少重新运行警告的问题。通过使用\@newl@bel
为 LaTeX 参考系统工作的 LaTeX 解决了这个问题。通过使用pgf@sys@df@mark@pos
作为参考类,参考不需要新的内部宏。
如果 PGF 的定位标签发生变化,则会给出通常的 LaTeX 警告:
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
该软件包目前可用hopgf-1.0.pdf下次我更新我的软件包时,它将被放到 CTAN 上。.dtx
附加到 PDF 文件,运行tex
(不是latex
)提取包文件hopgf.sty
。
欢迎对可以添加到软件包的内容提出评论和其他建议。当然,如果可以在 PGF/TikZ 上游添加修复和功能,那就更好了。
答案2
以发布的示例为例,添加以下检查似乎有效
\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{calc,shapes}
\makeatletter
\AtEndDocument{%
\let\oldpgfsyspdfmark\pgfsyspdfmark
\def\pgfsyspdfmark#1#2#3{%
\expandafter\let\expandafter\tmp\csname pgf@sys@pdf@mark@pos@#1\endcsname
\oldpgfsyspdfmark{#1}{#2}{#3}%
\expandafter\ifx\csname pgf@sys@pdf@mark@pos@#1\endcsname\tmp\else
\immediate\write\@auxout{Rerun Latex tikz mark #1 changed}%
\fi
}}
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}
\newcommand{\DrawBox}[4]{%
\begin{tikzpicture}[overlay,remember picture,-latex,shorten >=5pt,shorten <=5pt,out=70,in=130]
\draw[distance=0.45cm,#1] (a.north) to (b.north);
\draw[distance=0.65cm,#2] (a.north) to (c.north);
\draw[distance=0.9cm, #3] (a.north) to (d.north);
\draw[distance=1.1cm, #4] (a.north) to (e.north);
\end{tikzpicture}
}
\begin{document}
\begin{gather*}
(\tikzmark{a}l_{1}) \vee \big( (p \vee\tikzmark{b} q) \wedge (\neg p \vee\tikzmark{c} q) \wedge (p \vee\tikzmark{d} \neg q) \wedge (\neg p \vee\tikzmark{e} \neg q)\big) \DrawBox{red}{blue}{green}{orange}\\
(l_{1} \vee p \vee q) \wedge (l_{1} \vee \neg p \vee q) \wedge (l_{1} \vee p \vee \neg q) \wedge (l_{1} \vee \neg p \vee \neg q)
\end{gather*}
\end{document}
第一次运行你会得到
$ grep Rerun tk93.log
Rerun Latex tikz mark pgfid7 changed
Rerun Latex tikz mark pgfid8 changed
Rerun Latex tikz mark pgfid9 changed
Rerun Latex tikz mark pgfid10 changed
Rerun Latex tikz mark pgfid11 changed
Rerun Latex tikz mark pgfid12 changed
第二次运行
$ grep Rerun tk93.log
如果你希望第一次运行只更改一条消息
\immediate\write\@auxout{Rerun Latex tikz mark #1 changed}%
到
\let\pgfsyspdfmark\oldpgfsyspdfmark
\immediate\write\@auxout{Rerun Latex tikz marks changed}%
因此,在第一次警告之后,宏将恢复到其原始定义,并且不再进行进一步的检查。