Biblatex 的 bibmacros、参考书目驱动程序、格式 - 修补或重新定义?

Biblatex 的 bibmacros、参考书目驱动程序、格式 - 修补或重新定义?

xpatch提供了一系列专门用于支持修补biblatexbibmacros、参考书目驱动程序和字段/名称/列表格式的修补命令(据我所知,不是引用命令)。

在 TeX.SX 中,我有时会在 biblatex 相关答案中看到这些可能性的使用。但更常见的是(我的印象),我们发现了对各个 bibmacros、驱动程序和格式的完整重新定义。

在某些情况下,是否有明确的理由使用其中一种方法或另一种方法?一般来说,这两种方法的优缺点是什么?提出这个问题的另一种方式是什么时候最好使用一种方法还是另一种方法?

虽然我想从一般角度考虑这个问题,但我特别感兴趣的是修补的与完全重新定义的 bibmacros/drivers/formats 对 biblatex 中的更改/更新的恢复能力。

注意:这个问题可能源于我对修补代码的一般不熟悉。如果这个问题太模糊而无法“照原样”回答,我将避免提出这个问题。但我认为这个问题可能很有用。我真的很想了解更有经验的用户在选择修补还是重新定义 biblatex 时所采用的标准。

答案1

这是一个有趣的问题。我认为这个问题也可以应用于更一般的场景,但由于我主要关注的是biblatex书目领域,所以我将坚持讨论。

通常,重新定义的性质是,只有 才\xpatchbibmacro相关,\xapptobibmacro\xpretobibmacro,它们的语法稍微简单一些,通常不适用。\xpatchbibmacro的语法是。该命令将中\xpatchbibmacro{<bibmacro>}{<search>}{<replace>}{<success>}{<failure>}的第一个实例替换为。<search><bibmacro><replace>

一般来说,我更喜欢直接重新定义 bibmacros,而不是通过xpatch

这种方法的优点是

  • xpatch无需加载,从而减少开销。xpatch基于 LaTeX3 宏并加载expl3。开销可能微不足道,但确实存在。编辑事实上,xpatch需求expl3不再相关,因为expl3现在是 LaTeX 内核的一部分。)我还假设修补比简单地重新定义宏更昂贵,但我无法在这里给你确切的数字 - 差异可能可以忽略不计。

  • 语法稍微简单一些:\renewbibmacro{foo}{<new definition>}vs \xpatchbibmacro{foo}{<search>}{<replace>}{<success>}{<failure>}

    • 通常,更改仅涉及几行,因此很容易复制原始\newbibmacro{foo}定义,放入并修改宏代码。将要更改的代码复制到参数中,将修改后的代码添加到并添加代码(通常只是空组,但不要忘记它们)re可能会有点麻烦。\xpatchbibmacro{foo}<search><replace><success><failure>
    • 对于需要进行大量更改的短宏,\renewbibmacro其实际上可能更短。
  • \renewbibmacro对读者来说可能更有启发,因为他们可以看到整个相关的宏

      \renewbibmacro*{issue+date}{%
        \printtext[parens]{%
          \printfield{issue}%
          \setunit*{\addcomma\space}%<- change here
          \usebibmacro{date}}%
        \newunit}
    

    更清楚地显示了新代码的作用

      \xpatchbibmacro{issue+date}
        {\setunit*{\addspace}}
        {\setunit*{\addcomma\space}}
        {}{}
    

    读者不必查阅原始定义即可了解宏的新行为。不过,他们必须查阅原始定义才能准确比较更改的内容。

    这也意味着更容易扩展或采用变化。

缺点是

  • 灵活性较低。xpatch您不必知道要修补的宏的确切定义。只有代码<search>是相关的。因此,xpatch如果修改应该独立于使用的样式,则在某种程度上是有用的。

  • 代码长度。为了改变一个标点符号而复制数十行代码可能被视为过分。

这就是为什么我有时会使用xpatch。人们真的很喜欢短代码。在一定程度上biblatex, 倾向于划分并使用许多嵌套的短 bibmacros,这允许在许多情况下进行微小的更改而无需太多代码。但有些 bibmacros 很长,bibdrivers 也是如此。

以我的回答为例如何自定义 \textcite 命令?。 本来\renewbibmacro大约有 50 行,而\xpatchbibmacro只需要 5 行。所有这一切都是为了将​​一个更改\printnames{labelname}\printnames[first-last]{labelname}

尤其是当需要直接更改 bibdrivers 时,我更喜欢xpatch使用\DeclareBibliographyDriver。您的平均标准 bibdriver 长度为 30 到 40 行。如果需要更改多个驱动程序,则小的更改可能会积累数百行代码。示例可以在Biblatex/Biber:将系列、卷数和编号放在末尾如何将字段注释移至参考文献末尾

这两种方法在更改 bibmacros 和驱动程序时都存在问题。大多数普通用户想要更改的 bibmacros 和驱动程序多年来一直非常稳定。这并不是说不会偶尔更改更频繁更改的宏,但这种情况通常很少见。

的明显优势在于xpatch,如果相关<search>代码及其上下文没有改变,那么即使在更新宏后,修补也很可能继续正确执行。但是,如果代码<search>被修改,修补将失败。如果在宏中添加了类似于的新代码<search>,则将修补宏的错误部分。所有这些都成立,前提是命令和宏使用<replace>没有发生重大变化。

另一方面,用 重新定义的宏\renewbibmacro将始终应用相同的更改。它们当然容易受到应用于其<new definition>参数中使用的命令和宏的所有更改的影响。使用 ,\renewbibmacro您更有可能错过新功能或错误修复,因为您覆盖了整个定义,而不仅仅是部分定义。但只要 中使用的宏和命令<new definition>没有重命名或更改为执行与其先前行为相反的操作,您的重新定义将继续执行其编写的操作。

https://github.com/plk/biblatex/commit/04c939eed70ed2264a2753a811a2364e7f70d4ef作为第一个例子。如果您根据更改前的代码重新定义了editorbibmacro ,则除非您修改,否则\renewcommand将无法正常使用。但是,您的代码将继续像以前一样工作。如果您曾经更改与该更改无关的宏部分,则一切将继续按预期工作,并且您可以使用新的。如果您修补了与更改相关的某些内容,即显式的,则您的修补程序将失败。editortypedelimrenewcommand\xpatchbibmacroeditoreditortypedelim\setunit{\addcomma\space}

第二个例子是https://github.com/plk/biblatex/commit/189d90db9dbe94dd08f47261e79df09e2a37c66ahttps://github.com/plk/biblatex/commit/320f114d493ca7fa310c559c3a48b5912282fa22。如果您想要更改已重命名的宏之一,例如\usebibmacro{date+extrayear},这两种方法都不会产生良好的结果。如果您更改了调用已重命名的宏之一的宏,例如bbx:editor来自的bibmacro authoryear.bbx,则又有两种情况。如果代码不涉及,则该xpatch方法完全没有问题。如果涉及,则会失败。另一方面,如果您重新定义和引用,如果不是在提交中采取向后兼容性措施,事情就会出错。<search>\usebibmacro{date+extrayear}<search>\usebibmacro{date+extrayear}xpatchbibmacrobbx:editor<new definition>\usebibmacro{date+extrayear}

CTAN 上的样式比我预期的要多xpatch

其中一些用途是避免一遍又一遍地从同一个包中复制整个定义。在这些情况下,xpatch这是一种避免代码重复的简短而优雅的方法。这相当安全,因为修补的宏通常在同一个包中定义,并且不太可能在补丁作者没有注意到的情况下发生变化。其他用途涉及修补 bibdrivers。由于驱动程序很长,因此复制整个驱动程序只是为了修补一行很麻烦。一些包过去xpatch独立于底层样式工作。

相关内容