下面实际上是一个大型作业的简化版本。
\documentclass{memoir}
\AtBeginDocument{First}
\AtBeginDocument{Second}
\AtBeginDocument{Third}
% I want to cancel the above at this point
\AtBeginDocument{New First}
\AtBeginDocument{New Second}
\AtBeginDocument{New Third}
\begin{document}
\end{document}
我需要\AtBeginDocument
在某个中点取消当前的累积(来自另一个我需要使用的自制风格文件一些宏),然后再添加一些。
我该怎么做呢?
答案1
我不确定我是否准确理解了您的用例。就我个人而言,我非常不愿意直接摆弄\AtBeginDocument
(或\@begindocumenthook
),因为许多软件包(以及 LaTeX 本身的内部工作原理)将它们用于各种目的,而且我看不出如何确保我不会无意中破坏某些东西。
定义一个单独的累加器宏,然后执行它,是不是更好\AtBeginDocument
?然后,您就可以随心所欲地随意摆弄该宏,而不会破坏无意中使用了的任何其他内容\AtBeginDocument
。
就像是:
\documentclass{memoir}
\makeatletter
\def\MyAtBeginDocument{\g@addto@macro\my@begindocumenthook}
\let\my@begindocumenthook\@empty
\def\MyResetBeginDocument{\global\let\my@begindocumenthook\@empty}
\AtBeginDocument{\my@begindocumenthook}
\makeatother
\AtBeginDocument{THAT\par}
\MyAtBeginDocument{NOT THIS\par}
\MyResetBeginDocument
\MyAtBeginDocument{THIS\par}
\begin{document}
We should see THIS then THAT!
\end{document}
请注意,THIS 位于 THAT 之前,因为它是在由 所添加的附加材料之前\my@begindocument
执行的,因为它是通过 THAT 进入的,而 THAT 又是先被添加到 THAT 的。您可能需要(并且能够)将该添加延迟到稍后。\@begindocumenthook
\AtBeginDocument{THAT\par}
\my@begindocumenthook
\@begindocumenthook
答案2
\AtBeginDocument
只是将代码添加(附加)到“钩子” \@begindocumenthook
,在文档的开头执行收集的代码。
理论上你可以随时使用
\makeatletter
\let\@begindocumenthook\@empty
\makeatother
但这可能有点冒险,因为许多软件包都希望\AtBeginDocument
正常工作。
\AtBeginDocument
如果你只想跳过几个,那么使用以下命令暂时禁用该命令可能会更安全
\makeatletter
\let\AtBeginDocument\@gobble
\makeatother
当然你也可以保存钩子的内容
\makeatletter
\let\@masroor@saved@begindocumenthook\@begindocumenthook
\makeatother
然后过了几\AtBeginDocument
秒钟你想忽略它再次恢复
\makeatletter
\let\@begindocumenthook\@masroor@saved@begindocumenthook
\makeatother
答案3
这与 Paul Stanley 的答案类似,但 UI 略有不同。这定义了\AllowAtBeginDocumentToBeResetable
哪些全部可重置的后续使用\AtBeginDocument
。要重置这些,请调用\ClearResetableAtBeginDocumentList
。因此,您的示例代码将如下所示:
\AllowAtBeginDocumentToBeResetable%% ALL EXTERNAL PACKAGES INCLUDED BEFORE HERE
\AtBeginDocument{First\par}
\AtBeginDocument{Second\par}
\AtBeginDocument{Third\par}
\ClearResetableAtBeginDocumentList% I want to cancel the above at this point
\AtBeginDocument{New First\par}
\AtBeginDocument{New Second\par}
\AtBeginDocument{New Third\par}
生成结果:
笔记:
- 请注意,这要求全部外部包必须被包括在内前你的问题
\AllowAtBeginDocumentToBeResetable
。
代码:
\documentclass{memoir}
\makeatletter
\let\@OldAtBeginDocument\AtBeginDocument
\newcommand{\@ResetableBegindDoumentItems}{}%
\newcommand{\AllowAtBeginDocumentToBeResetable}{%
\ifdefined\@AtBeginDocumentIncludesResetableList\else
\gdef\@AtBeginDocumentIncludesResetableList{}% Don't execute this again
\AtBeginDocument{\@ResetableBegindDoumentItems}%
\fi
\renewcommand{\AtBeginDocument}[1]{%
\g@addto@macro\@ResetableBegindDoumentItems{{##1}}%
}%
}
\newcommand*{\ClearResetableAtBeginDocumentList}{%
\gdef\@ResetableBegindDoumentItems{}%
}
\makeatother
\AllowAtBeginDocumentToBeResetable%% ALL EXTERNAL PACKAGES INCLUDED BEFORE HERE
\AtBeginDocument{First\par}
\AtBeginDocument{Second\par}
\AtBeginDocument{Third\par}
\ClearResetableAtBeginDocumentList% I want to cancel the above at this point
\AtBeginDocument{New First\par}
\AtBeginDocument{New Second\par}
\AtBeginDocument{New Third\par}
\begin{document}
\end{document}
答案4
在较新的版本中:\@begindocumenthook
不再使用,而是使用了一些复杂的数据结构。文档位于lthooks.dtx
,或者可以在 中找到source2e.pdf
。
您可以使用\ShowHook{begindocument}
来显示钩子中的代码。
至于删除它们,有\RemoveFromHook{begindocument}[⟨optional label⟩]
。文档位于上面提到的地方。
因此,对于这种特殊的用例,如果您指定诸如的标签\AtBeginDocument[⟨your label⟩]{⟨your code⟩}
,则可以使用\RemoveFromHook{begindocument}[⟨your label⟩]
它是安全的并且不会影响任何其他代码。
公共 API 不支持更复杂的操作(例如从钩子中获取代码或修补等),但您可以摆弄内部数据结构(但您的代码显然随时可能中断)。请参阅源代码文档中的子节“钩子的数据结构”。