编写新的 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}
出现这种行为的原因是什么?我该如何设置\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}
打印标点符号,清空缓冲区,然后打印“字符串”。
在本例中,有几种方法可以解决该问题,但根据您的实际使用情况,其中一些选项可能比其他选项更可取。
- 一个简单的解决方案就是将
\printtext{word}
和移动\printtext{string}
到同一个\printtext{wordstring}
。 - 您可以按照以下建议自行使用
\setunit{}
between\printtext{word}
和清空标点符号缓冲区\printtext{strgin}
乌尔丽克·菲舍尔 在评论中。 - 您可以在 后面使用星号
\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}