对 TeX 宏进行编程,使其输出指令来重新运行编译

对 TeX 宏进行编程,使其输出指令来重新运行编译

这个问题的提出源于tikzmarkAndrew Stacey 创建的宏的行为,以及最近与 David Carlisle 在聊天中的讨论。

我注意到使用 LaTeX 代码tikzmark通常需要多次编译运行。第一次运行后,会绘制一个图片,但 LaTeX 输出中没有迹象表明需要第二次运行。自动化工具和人类也依赖 LaTeX 输出来确定是否需要更多重新编译。David 告诉我,可以将代码添加到宏中,以便它向 LaTeX 日志输出适当的消息,说明代码需要重新运行或类似情况。我在 emacs 中使用 AucTeX,它肯定会使用输出中的信息来确定是否需要再次运行 LaTeX。

我不知道tikzmark宏是如何工作的,也不知道判断何时需要重新运行代码有多困难,但是有人知道如何向宏添加代码tikzmark来实现这一点吗?

例如,参见 Peter Grill 的解决方案如何在等式各部分之间画箭头来显示数学分配律(乘法)?

注:Andrew Stacey 已添加tikzmarkLaunchpad 上的 tex-sx 项目。存储库位于http://bazaar.launchpad.net/~tex-sx/tex-sx/development/files. 实际文件是tikzmark.dtxtex 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.pdfhopgf-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}%

因此,在第一次警告之后,宏将恢复到其原始定义,并且不再进行进一步的检查。

相关内容