为各种类和包构建补丁集合

为各种类和包构建补丁集合

我开发了一个包,其主要部分包括对其他文档类和包的修复和补丁。当然,我只希望在相关类或包已加载时应用补丁。此外,可以有适用于多个类/包的补丁,也可以有适用于一个类/包的补丁仅有的如果其他类/包尚未加载(例如,hyperref修改了标准类中的许多内容,如果我也要修改它们,我将不得不使用两个版本,具体取决于是否hyperref已加载)。由于我不想强制任何特定的加载顺序,因此我还想运行包检测/修补部分 AtBeginDocument。

我想到的一件事是扩展\@ifclassloadedand\@ifpackageloaded命令以使用 接受逗号分隔的名称列表\@for。然后我会说

\PatchClassIfLoaded{article,report,book}{<commands>}

等等。但这样<commands>就必须在参数内部,并且会被“读取”两次(请原谅我没有足够的 TeX 知识来更好地描述它),我不喜欢这样。虽然这对于包补丁来说是必要的,因为\AtBeginDocument,但对于类来说这不是必需的。

我更喜欢这样的构造

\IfClassLoaded{article,report,book}
  <commands>
\fi

我知道如果我降低一级就可以编程\@ifclassloaded。但这更像是一种不应依赖的黑客行为。

以上只是我想要实现的一个例子。问题本身更广泛:这个问题有不同的解决方案吗?是否有实现类似功能的包?包喜欢hyperrefcaption使用什么方法来适应各种各样的类和包?

答案1

软件包caption版本 <= 3.0 修补了现有宏,即新代码在旧的现有宏代码之上运行。由于周围有太多文档类和软件包提供或修补与标题相关的代码(例如某些babel软件包),因此这种方法并不令人满意。总是存在我无法处理的不兼容性。

因此,对于 3.1 版本,我进行了以下更改:我不再修补与标题相关的宏,而是通常替换它们\AtBeginDocument。显然,这有一些优点和缺点。

我先说说缺点:

  • 我必须将其他软件包的内容集成到我的代码中,以使我的软件包与其他软件包兼容。如果其他软件包的内部发生变化,我的软件包将不再起作用,因此我也必须采用我的代码。
  • 我的包仅与已集成(与标题相关的)代码的文档类或包兼容。对于所有其他包,它不再兼容。
  • 只有当我是唯一一个以这种方式修补标题相关宏的人时它才有效。

优点:

  • 我现在完全兼容我支持的文档类和包。(它们在caption包中列出。)
  • caption软件包消除了我支持的软件包之间的不兼容性。例如,软件包fltpage与软件包不兼容hyperref。但是,当caption另外加载软件包时,两个软件包的标题相关代码将完全替换为我的代码,因此这种组合现在可以正常工作。(该caption软件包甚至能够提供有关fltpage和组合的一些额外设置hyperref。)

最后,我对这一变化感到非常高兴。但新方法之所以成功,是因为 LaTeX 和我支持的大多数软件包都“死了”;它们多年来一直没有改变,希望永远不会改变。我必须照顾的唯一“活着”的软件包是 KOMA-Script 和 hyperref。(当然,我与这些软件包的作者保持联系。)

关于如何检测文档类或包的问题:这在caption包代码中有所不同,即我并不总是使用相同的策略。有时我会检查已加载的包,有时我会检查特定宏是否存在。我知道这可以改进,但除非我因此收到错误报告,否则我不会更改它 ;-)

附录:造成这种不一致的原因很简单,因为我从未对此形成任何概念。当我在 1994 年开始编写该软件包时,我从未计划修补如此多的文档类和软件包。

关于我该如何处理hyperref等:我已经将功能封装到宏中,如果包未加载,则hyperref宏不执行任何操作:hyperref


\newcommand*\caption@makecurrent[2]{}
\let\caption@makeanchor\@firstofone
\let\caption@start\relax
\let\caption@@start\relax
\let\caption@freezeHref\relax
\let\caption@defrostHref\relax

这些宏将由我的标题代码使用。如果hyperref检测到包,主标题代码将不会更改,但上面的辅助宏将会更改。(我也对其他包使用相同的机制,例如包float。)

答案2

我想说:尽量避免编写这样的包。您只需阅读 hyperref 文档中有关兼容性和问题的部分,就会发现使用和管理一个必须与许多其他包保持兼容性的包已经很不容易了。再添加一堆“修复和补丁”将导致拥挤的\AtBeginDocument钩子、关于谁稍后插入其代码的鸡和蛋的竞赛,以及使用您未考虑的包组合的用户的困惑问题。

相关内容