使用 LaTeX 时偶尔会遇到的一个问题是软件包之间的不兼容。软件包作者处理软件包冲突的最佳实践是什么?
例如:
- 处理包选项冲突的最佳方法是什么?
- 应如何记录软件包冲突?(在软件包文档中是否有统一/推荐的方式来呈现此内容?我认为没有。)
- 有
\PassOptionsToPackage
。 - 如果某个包已经加载,有没有办法抛出错误?
- 是否有一种标准的方式可以告诉用户(通过警告或错误)更改包加载顺序?
- 包在加载时如何检测不正确的包加载顺序(如果包的作者知道相应的依赖关系)?
- 是否有推荐的方式/接口供软件包进行通信以指示或检查某个命令是否/如何已被修补/修改?
- 是否有一种推荐的方法可以让软件包记录或警告其他软件包不要对它们正在执行的现有命令进行何种修补?
(我怀疑这些问题中的一些的“最佳”答案是“等待 LaTeX3”,但这并不意味着人们不能或不应该在此期间记录解决方法。事实上,我问这些问题部分是为了提供文档记录。)
有关 TeX.SE 的一些问题构成部分答案或要求提供相关信息:
答案1
选项处理(摘自 source2e 文档)
在处理选项的时候,分为两种类型:当地的和全球的:
- 对于类来说,命令中的选项
\documentclass
是本地的。 - 对于包来说,命令中的选项
\usepackage
是局部的,命令中的选项\documentclass
是全局的。
\documentclass
和的选项\usepackage
按下列方式处理:
\DeclareOption
首先处理已声明的本地和全局选项。- 对于
\ProcessOptions
,它们将按照在类或包中声明的顺序进行处理。 - 对于
\ProcessOptions*
,它们将按照选项列表中出现的顺序进行处理。首先是全局选项,然后是局部选项。
- 对于
任何剩余的本地选项都使用默认选项(使用 声明)处理
\DeclareOption*
。对于文档类,这通常不执行任何操作,但会将选项记录在未使用选项列表中。对于包,这通常会产生错误。
从实际角度来说,这意味着当需要相同的选项时,最好将其设为全局选项,例如多个包所需的语言选项
\documentclass[english]{article}
\usepackage{babel}%------ Uses global english
\usepackage{varioref}%--- Uses global english
\usepackage{refstyle}%--- Uses global english
另一个例子是amsmath
,它被许多包加载。有时设置选项的唯一方法是将它们设为全局选项。对于包编写者来说,通过指定全局选项是一种避免冲突的方法。
包加载顺序
如果您的包必须在另一个包之前加载,那么可以使用内部命令进行测试并使用机制来引发错误或警告:
\@ifpackageloaded{<package>}{<true>}{<false>}
:查看某个包是否已经被加载\@ifpackagewith{<package>}{<options>}{<true>}{<false>}
:查看某个包是否已经加载了至少以下选项<options>
例如在包声明中:
\ProvidesPackage{MYpackage}
\@ifpackageloaded{ABCpackage}%
{\PackageError{MYpackage}{You must load MYpackage before ABCpackage}{}}%
{}
请注意,强制加载顺序并不是一个好习惯。作为包编写者,你可以在 98% 的情况下通过使用 \AtBeginDocument{}
测试或设置某些内容来避免冲突
\AtBeginDocument{%
\@ifpackageloaded{graphicx}%
{}%
{\PackageError{MYpackage}{You must load the graphicx package}{}}}
检查补丁
有一个 Latex 命令\CheckCommand
可以测试命令是否被更改。将其放入\AtBeginDocument{}
进行测试和更改命令中也是不错的选择。有许多问题,例如这次讨论
如果你正在修补某个命令,最好通过将其写入日志文件来通知用户:
\PackageInfo{MYpackage}{The command ... was redefined}
但请不要重新定义内部 Latex 命令!