\setunit*{ 之间有什么区别吗?} 和 \setunit{\add}

\setunit*{ 之间有什么区别吗?} 和 \setunit{\add}

例如,我想知道以下两者之间的区别:

  • \setunit*{\space}(有*但没有add

  • \setunit{\addspace}(没有*,但有add)。

我有时会在 biblatex文件中看到这样的表达\setunit*{\addspace}(同时包含*和) 。这是否有点多余,因为我认为add.bbx*add前缀具有相同的功能,即避免双重标点符号?

我之所以问这个问题,是因为我刚刚重新定义了 @book 驱动程序,以便反转editionbyeditor+other宏的顺序。然后,为了删除逗号,我用 替换了\newunit\newblock\setunit{\addspace}这得到了 :

\printfield{edition}%
\setunit{\addspace}%
\usebibmacro{byeditor+others}%

这时,我开始问自己是否应该添加*,因为我有时会在那些.bbx文件中看到。

答案1

\setunit和之间以及和\setunit*之间的差异是完全正交的。\addspace\space

在深入了解biblatex标点符号缓冲区的细节之前,最好先了解一下基础知识。§4.11.7 中有非常好的例子使用标点符号追踪器biblatex文档我已经在本网站的各种答案中写过它,例如\setunit 和 \newunit 起什么作用?biblatex:\DeclareCiteCommand 在 \printfield 和 \printnames 之间添加分号,但只是有时biblatex 中 @inbook 条目的 in:, \intitlepunct 正确使用。主要思想是,biblatex当在命令中遇到标点符号时,不会直接打印标点符号\setunit。相反,标点符号会被保存,然后由下一个打印任何内容的\printtex\printfield\printlist\printnames\printdate命令打印。后面的\setunits 会覆盖先前调用的标点符号\setunit。标点符号缓冲区意味着可以避免重复标点符号。这还意味着,在确保标点符号正确时,biblatex通常可以避免过多的调用。\iffieldundef{...}

\setunit对比\setunit*

biblatex看到 时,\setunit它会将其参数保存在标点缓冲区中(覆盖其先前的内容)。下次biblatex遇到\print(text|field|list|names|date)打印某些内容的命令时,会打印缓冲区。

\DeclareBibliographyDriver{book}{%
  \printnames{author}%
  \setunit{ \textbf{A} }%
  \printfield{title}%
  \setunit{ \textbf{B} }%
  \printfield{edition}%
  \setunit{ \textbf{C} }%
  \printdate}

biblatex看到时,\setunit{ \textbf{B} }它会将其添加\textbf{B}到缓冲区。然后它会看到\printfield{edition}。如果版本字段不为空,biblatex将打印缓冲区的内容,然后打印版本字段的内容。如果字段为空,则不会发生任何事情。然后biblatex看到\setunit{ \textbf{C} }并将它添加 \textbf{C}到缓冲区。然后\printdate打印缓冲区和日期(如果日期不为空),否则不执行任何操作。

特别是我们将看到

阿普尔比,汉弗莱A 论公务员制度的重要性 第 4 版C1980

如果authortitleedition存在date,但我们得到

布普比,汉弗莱A 论公务员制度的重要性 C1981

如果没有edition字段,因为\setunit会覆盖缓冲区(因此“最后的\setunit胜利”)。

\setunit*工作方式略有不同:如果前一个命令打印了某些内容,它才会将其参数添加到标点符号缓冲区\print(text|field|list|names|date)

\DeclareBibliographyDriver{book}{%
  \printnames{author}%
  \setunit{ \textbf{A} }%
  \printfield{title}%
  \setunit{ \textbf{B} }%
  \printfield{edition}%
  \setunit*{ \textbf{C} }%
  \printdate}

上面的相同示例条目将产生

阿普尔比,汉弗莱A 论公务员制度的重要性 第 4 版C1980

布普比,汉弗莱A 论公务员制度的重要性 1981

也就是说,在 Bppleby 条目中,edition我们得到了一个而不是C就像这个\setunit案例一样。

这是因为这里\setunit*{ \textbf{B} }检查是否\printfield{edition}打印了某些内容,并且只添加\texbf{B}到缓冲区如果是这样的话。第二个条目没有edition字段,因此\setunit*后续操作\printfield{edition}不执行任何操作。

一个常见的用途\setunit*是在字段之间通常\setunit同时出现,但在特殊情况下第一个字段可能会缺失(如果第二个字段缺失,那么我们是否使用或并不重要,\setunit*因为后面的字段\setunit无论如何都会覆盖它)。

standard.bbx例如

\newbibmacro*{series+number}{%
  \printfield{series}%
  \setunit*{\addspace}%
  \printfield{number}%
  \newunit}

这意味着如果 和 都series存在number,则它们之间只有一个空格。但如果series缺少 ,则标点符号跟踪器前面不会有空格number,而是前面的内容。

\setunit和之间的另一个区别的例子\setunit*在 biblatex-chicago 中使用句点分隔期刊卷和发行号时,修复仅包含发行号的期刊的格式

\addspace对比\space

\addspace定义biblatex.sty

\newrobustcmd*{\addspace}{%
  \unspace\blx@postpunct
  \space\blx@imc@resetpunctfont}

本质上这意味着它\addspace\space做一些额外的管理工作。

特别是\unspace\addspace在插入自己的 之前尝试抑制任何先前的空格\space。这应该有助于防止出现虚假空格。比较(坏例子)

\printnames{author}
\setunit{\space}%
\printfield{title}%

\printnames{author}
\setunit{\addspace}%
\printfield{title}%

这里第一行应该是

\printnames{author}%

而不是\printnames{author}。但仍然可以防止产生\addspace不必要的双倍空格。\space

\blx@postpunct是一个内部命令,可帮助正确使用美式引号。在美式引号风格中,引号可能会越过后面的标点符号,即使严格来说它不属于引文本身。(见https://en.wikipedia.org/wiki/Quotation_marks_in_English#US_practice

\blx@imc@resetpunctfontbiblatex是该功能代码的一部分punctfont,它以与以前的文本相同的样式排版标点符号。

\add...其他标点符号命令的定义也类似biblatex\addcomma产生逗号,尽量避免虚假空格和不必要的双标点,并进行一些常规处理。

基本上,您总是希望使用\addspace而不是\space\addcomma而不是,\addperiod而不是.等等),但并不总是容易发现差异(特别是如果您使用%以避免虚假空格,不要使用美国引号约定并且不要激活punctfont)。

只有一种情况通常优先使用biblatexwhere而不是 ,即当空格直接跟在同一个宏中已经使用 的不同标点符号命令之后时。通常的习惯用法是\space\addspace\add...

\setunit{\addcomma\space}%

而不是,\setunit{\addcomma\addspace}%因为\addcomma已经完成了所有必要的整理工作,因此空间无需再做任何事。当然,\addcolon\space\addperiod\space也是如此。

结束语

\setunit*{\space}在标准样式中,我找不到 的一个实例biblatex,但我可以找到几个\setunit*{\addspace}。即使您看不出 和 之间的区别\setunit*{\space},但\setunit*{\addspace}我认为\addspace在几乎所有情况下您都应该使用 。

是否应该在问题中引用的代码中使用\setunit或取决于如果缺少则您期望的行为。\setunit*edition

用于测试的 MWE

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}

\usepackage[style=authoryear, backend=biber]{biblatex}

\DeclareBibliographyDriver{book}{%
  \printnames{author} 
  \setunit{\addspace}%
  \printfield{title}%
  \setunit{ \textbf{B} }%
  \printfield{edition}%
  \setunit{ \textbf{C} }%
  \printdate
  \setunit{\par}%
  \printnames{author} 
  \setunit{\addspace}%
  \printfield{title}%
  \setunit{ \textbf{B} }%
  \printfield{edition}%
  \setunit*{ \textbf{C} }%
  \printdate}

\begin{filecontents}{\jobname.bib}
@book{appleby,
  author  = {Humphrey Appleby},
  title   = {On the Importance of the Civil Service},
  date    = {1980},
  edition = {4},
}
@book{bppleby,
  author  = {Humphrey Bppleby},
  title   = {On the Importance of the Civil Service},
  date    = {1981},
}
\end{filecontents}
\addbibresource{\jobname.bib}

\begin{document}
\cite{appleby,bppleby}
\printbibliography
\end{document}

相关内容