使用 biblatex \newunit 进行跳转

使用 biblatex \newunit 进行跳转

编写新的 BibLaTeX 书目样式时,我注意到,我不太明白 biblatex 的标点符号算法是如何工作的,如果在第一个打印字段之前有一个。在 BibLaTeX 文档(4.7、4.11.7\newunit\setunit{}\printXXX{}\newunit这个问题) 我只发现了当参考书目驱动程序中间的字段为空时如何使用的解释。

如果\newunit在第一个打印字符串之前,它不会在那里打印一个点(这是我所期望的),但它会在接下来两个字符串之间打印一个点,\printXXX{}即使那里不应该有标点符号。点是跳跃从开始到下一个可能的位置。

查看我的 MWE 和结果:

\begin{filecontents}[force]{\jobname.bib}
@article{WithTitle,
  title = {Testtext},
}

@article{WithoutTitle,
  title = {},
}
\end{filecontents}

\begin{filecontents}[force]{\jobname.bbx}
\RequireBibliographyStyle{numeric}

\DeclareBibliographyDriver{article}{
  \printfield{title}%
  \newunit%
  \printtext{word}%
  \printtext{string}%
  \usebibmacro{finentry}%
}
\end{filecontents}

\documentclass{article}
\usepackage[backend=biber,bibstyle=\jobname,citestyle=numeric]{biblatex}

\addbibresource{\jobname}

\begin{document}
\printbibliography

\cite{WithTitle}\cite{WithoutTitle}
\end{document}

MWE的结果

出现这种行为的原因是什么?我该如何设置\newunit不跳跃的?

答案1

标点符号缓冲区的原理及其工作原理实际上相当简单。要理解为什么会得到这样的结果,以下内容就足够了(更多细节和示例可以在已经链接的\setunit 和 \newunit 起什么作用?biblatex:\DeclareCiteCommand 在 \printfield 和 \printnames 之间添加分号,但只是有时

\setunit{<punctuation>}(就所有意图和目的而言,\newunit只是\setunit{\newunitpunct})放入<punctuation>标点符号缓冲区。如果缓冲区已包含一个值,则该值将被覆盖(除非先前的值是使用 添加到缓冲区的\printunit,否则该值\printunit将保留在缓冲区中并且无法被覆盖)。

\printfield每当( \printlist, \printnames, \printtext) 打印某些内容时,如果已经打印了任何内容,则标点符号缓冲区会被打印出来并清空(因为biblatex标点符号位于两个元素之间,因此在打印任何内容之前打印标点符号是没有意义的)。

当前值保留在缓冲区中,直到被覆盖或在两个命令\setunit之间打印出来。\print...


所以现在

\printfield{title}%
\newunit%
\printtext{word}%
\printtext{string}%
\usebibmacro{finentry}%

如果title不为空,则一切都会按预期进行。

  • \printtext{title}打印标题并告诉标点符号缓冲区已打印一些内容。
  • \newunit放入\newunitpunct标点符号缓冲区。
  • \printtext{word}打印标点符号(并清空缓冲区),然后打印“单词”。
  • \printtext{string}打印“字符串”。

因为之后标点符号缓冲区为空\printtext{word},“单词”与“字符串”之间没有标点符号。

如果title为空,则会发生以下情况。

  • 没有打印任何内容\printtext{title}
  • \newunit放入\newunitpunct标点符号缓冲区。
  • \printtext{word}打印“word”,但不打印任何标点符号,因为之前没有打印任何内容。缓冲区仍包含\newunitpunct
  • \printtext{string}打印标点符号,清空缓冲区,然后打印“字符串”。

在本例中,有几种方法可以解决该问题,但根据您的实际使用情况,其中一些选项可能比其他选项更可取。

  1. 一个简单的解决方案就是将\printtext{word}和移动\printtext{string}到同一个\printtext{wordstring}
  2. 您可以按照以下建议自行使用\setunit{}between\printtext{word}和清空标点符号缓冲区\printtext{strgin}乌尔丽克·菲舍尔 在评论中
  3. 您可以在 后面使用星号\setunit*代替\setunit/ ,这样只会在前一个命令打印了任何内容时向缓冲区添加标点符号。(请参阅\newunit\printfield{title}\setunit*{<punct>} 和 \setunit{\add<punct>} 之间有什么区别\setunit进行关于vs的讨论\setunit*

以下 MWE 展示了这三个想法。

\documentclass{article}
\usepackage[backend=biber]{biblatex}

\DeclareBibliographyDriver{article}{%
  \printfield{title}%
  \newunit
  \printtext{wordstring}%
  \usebibmacro{finentry}%
}

\DeclareBibliographyDriver{book}{%
  \printfield{title}%
  \newunit
  \printtext{word}%
  \setunit{}%
  \printtext{string}%
  \usebibmacro{finentry}%
}

\DeclareBibliographyDriver{incollection}{%
  \printfield{title}%
  \setunit*{\newunitpunct}%
  \printtext{word}%
  \printtext{string}%
  \usebibmacro{finentry}%
}

\begin{filecontents}{\jobname.bib}
@article{art:WithTitle,
  title   = {Testtext},
  presort = {a},
}
@article{art:WithoutTitle,
  title   = {},
  presort = {b},
}
@book{book:WithTitle,
  title   = {Testtext},
  presort = {c},
}
@book{book:WithoutTitle,
  title   = {},
  presort = {d},
}
@incollection{incoll:WithTitle,
  title   = {Testtext},
  presort = {e},
}
@incollection{incoll:WithoutTitle,
  title   = {},
  presort = {f},
}
\end{filecontents}
\addbibresource{\jobname.bib}

\begin{document}
\nocite{*}

\printbibliography
\end{document}

[1] “测试文本”。字符串。[2] 字符串。[3] 测试文本。字符串。[4] 字符串。[5] “测试文本”。字符串。[6] 字符串。

相关内容