软件包不兼容:etoolbox、hyperref 和 bm,独立吗?

软件包不兼容:etoolbox、hyperref 和 bm,独立吗?

我正在尝试过渡到使用etoolbox包,但似乎遇到了一些困难,它们似乎与hyperrefbm包有关,而在我看来,它们完全不相关。MWE 示例自定义以来就进行了编译,并表明在使用 \RemoveEToolbox之前没有明显的问题。etoolbox

注释掉该\def\RemoveEToolbox{}行会产生两个问题:

  1. 使用\renewcommandusepackage{hyperref}注释,结果为“失控的争论?段落在 \bm@test@token 完成之前就结束了”

  2. 包括usepackage{hyperref}(带\renewcommand注释的)结果“未定义控制序列。\Call@AtVeryEndDocument ...cumentHook \@undefined”

但是如果取消注释该\renewcommand{\bm}{#1}行(实际上没有任何\bm),那么这似乎可以编译。

我已经使用这个有一段时间了,一切似乎都运行良好,但现在我尝试使用时etoolbox似乎遇到了问题。

\documentclass{standalone}
\def\RemoveEToolbox{}% Shows that this works fine without {etoolbox}

\usepackage{amsmath}
\usepackage{xcolor}
\usepackage{bm}

\ifdefined\RemoveEToolbox
    \newcommand*{\iftoggle}[3]{#2}% Default to true value of "if"
\else
    \usepackage{etoolbox}
    \newtoggle{paper}
    \toggletrue{paper}

    %\renewcommand{\bm}[1]{#1}% Why can't I have a normal \bm with {etoolbox}?
\fi

% \usepackage{hyperref}

\begin{document}

This document is intended for 
\iftoggle{paper}{paper}{electronic}
distribution.

\bm{\textcolor{blue}{Solve $x^2-1=0$}}

\begin{align*}
    a &= b\\
    \iftoggle{paper}{
        c &= d\\
    }{}
    e &= f\\
\end{align*}
\end{document}

答案1

问题是standalone类和etoolbox包都重新定义了document环境。这会导致冲突。您可以通过etoolbox使用在类之前加载来避免这种情况\RequirePackage。我会尝试支持此包的正常功能,但要过一段时间才能有时间发布新版本的standalone

解决方法:

\def\RemoveEToolbox{}% Shows that this works fine without {etoolbox}

\ifdefined\RemoveEToolbox
    \newcommand*{\iftoggle}[3]{#2}% Default to true value of "if"
\else
    \RequirePackage{etoolbox}
    \newtoggle{paper}
    \toggletrue{paper}

    %\renewcommand{\bm}[1]{#1}% Why can't I have a normal \bm with {etoolbox}?
\fi

\documentclass{standalone}

\usepackage{amsmath}
\usepackage{xcolor}
\usepackage{bm}

% \usepackage{hyperref}

\begin{document}

This document is intended for 
\iftoggle{paper}{paper}{electronic}
distribution.

\bm{\textcolor{blue}{Solve $x^2-1=0$}}

\begin{align*}
    a &= b\\
    \iftoggle{paper}{
        c &= d\\
    }{}
    e &= f\\
\end{align*}
\end{document}

更新 2011/12/21

由于更改了修补环境的方式,因此的新版本 1.0standalone与 配合良好。但是,新的默认设置会忽略段落分隔符,因此在使用 时会出现问题。您可以使用class 选项轻松修复此问题。etoolboxdocumentalign*varwidth

答案2

(Martin 已经发布了答案,但还有更多内容!)问题是由于 的定义存在问题而产生的\@@end。这是 LaTeX 内核存储 TeX\end原语的地方(以便\end可以重复用于环境)。该bm包对依赖于它是原语的各种测试进行了测试\@@end。发生的事情etoolbox

\patchcmd\enddocument
  {\deadcycles}
  {\let\AfterEndDocument\@firstofone
   \@afterenddocumenthook
   \deadcycles}
  {}
  {\let\etb@@end\@@end
   \def\@@end{%
     \let\AfterEndDocument\@firstofone
     \@afterenddocumenthook
     \etb@@end}}

它试图修补\enddocument,如果不能,则改变 的定义\@@end。在标准类中,补丁有效(它寻找\deadcycles),所以一切都很好。另一方面,这失败了,因为standalone它重新定义\enddocument

\def\sa@@enddocument{%
  %\let\document\sa@orig@document
  \let\enddocument\sa@orig@enddocument
  \endinput
}

因此在这种情况下,etoolbox它是否会进行“后备”修补,然后测试会bm失败。

如果你不需要结束文档钩子,那么修复很容易

\makeatletter
\let\@@end\etb@end
\makeatother

我现在已经承担了维护etoolbox已对代码进行了修复。现在采取的方法是\@@end使用钩子尽可能延迟重新定义\AtEndDocument

相关内容