我如何重置当前的 \AtBeginDocument?

我如何重置当前的 \AtBeginDocument?

下面实际上是一个大型作业的简化版本。

\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}

生成结果:

enter image description here

笔记:

  • 请注意,这要求全部外部包必须被包括在内你的问题\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 不支持更复杂的操作(例如从钩子中获取代码或修补等),但您可以摆弄内部数据结构(但您的代码显然随时可能中断)。请参阅源代码文档中的子节“钩子的数据结构”。

相关内容