问题陈述

问题陈述

问题陈述

在 biblatex v3.11 下,我定义了一个\DeclareCiteCommand,它包括a\printfield{source}和a\printnames命令(参见下面的 MWE)。

source字段本身包含一个引用(例如source = {\cite{Rossing1990}}),我意识到这可能是有问题的,但却是我想要实现的一个重要方面。

根据source字段中的引用是否包含后注,将不会生成或在和\DeclareCiteCommand之间生成分号。\printfield{source}\printnames

  • 我希望去掉分号在后一种情况下,这曾经是几个版本之前(大约 1-2 年,IIRC)biblatex 的默认行为。
  • 此外,解释如果能解释一下我所观察到的现象发生的原因(参考 biblatex 文档),我将不胜感激。

最小(非)工作示例(MWE)

main.tex文件

\documentclass{article}

\usepackage[style=authoryear-comp]{biblatex}
\addbibresource{test.bib}

\DeclareCiteCommand{\mycite}{}{%
  \printfield{source}  \printnames[first-last]{author}
}{}{}

\begin{document}

This citation includes a semicolon between \verb|\printfield| and \verb|\printnames| (which I am trying to get rid of):\\
\mycite{MyImg}\\

This citation doesn't (which is what I want):\\
\mycite{MyImg2}\\

\end{document}

test.bib文件

@image{MyImg,
    author = {{Addison-Wesley}},
    source = {\cite{Rossing1990}},
}

@image{MyImg2,
    author = {{Addison-Wesley}},
    source = {\cite[45]{Rossing1990}},
}

@book{Rossing1990,
    author = {Thomas D. Rossing},
    date = {1990},
}

汇编

注:本 MWE 的编译需要 biber运行。以下序列有效:

pdflatex main
biber main
pdflatex main
biber main
pdflatex main

答案1

下面我将使用note而不是source(因为source在默认数据模型中未知,所以它不会被传递给文件.bbl- 我假设您有一个自定义.dbx设置)。

使用\setunit{\addspace}文字空格代替

你只需要\setunit{\addspace}在两个\print...命令之间添加一个就可以了

%\RequirePackage{filecontents}
\begin{filecontents}{\jobname.bib}
@image{MyImg,
    author = {{Addison-Wesley}},
    note = {\cite{Rossing1990}},
}

@image{MyImg2,
    author = {{Addison-Wesley}},
    note = {\cite[45]{Rossing1990}},
}

@book{Rossing1990,
    author = {Thomas D. Rossing},
    date = {1990},
}
\end{filecontents}

\documentclass{article}

\usepackage[style=authoryear-comp]{biblatex}
\addbibresource{\jobname.bib}

\DeclareCiteCommand{\mycite}{}{%
  \printfield{note}%
  \setunit{\addspace}%
  \printnames[given-family]{author}%
}{}{}

\begin{document}

This citation includes a semicolon between \verb|\printfield| and \verb|\printnames| (which I am trying to get rid of):\\
\mycite{MyImg}\\

This citation doesn't (which is what I want):\\
\mycite{MyImg2}\\
\end{document}

在此处输入图片描述

为什么有\setunit帮助?

标点符号追踪器

biblatex对字段之间或一般命令中的标点符号采用特殊方法\print...。不应直接插入标点符号,而应将其存储在缓冲区中,并仅在需要时打印出来。这种对文本的标点符号采用异步方法可以轻松避免不必要的双重标点符号。

您可以在§4.11.7 中阅读有关标点符号跟踪器的全部内容使用标点符号追踪器手册biblatex,简短版本如下:

每当需要标点符号时,标点符号不会直接插入,而是被包裹在里面\setunit(通常使用的\newunit相当于 ,\setunit{\newunitpunct}默认\newunitpunct\addperiod\space)。一个典型的片段是(来自volume+number+eidstandard.bbx

\printfield{volume}%
\setunit*{\adddot}%
\printfield{number}%
\setunit{\addcomma\space}%
\printfield{eid}

\setunit遇到 时(我们\setunit*稍后会介绍带星号的版本),biblatex将其参数存储在标点缓冲区中,命令本身不打印任何内容。标点缓冲区可以被后续的\setunits 覆盖,因此\setunit{X}\setunit{Y}只留Y在缓冲区中。缓冲区被打印并在下一个\print...实际打印任何内容的命令时清空。

假设在上面的例子中,条目有一个volume和一个eid字段,但没有number字段。处理代码片段时volume,将打印\setunit*插入\adddot标点符号缓冲区。没有number,所以\printfield{number}什么也不做。\setunit{\addcomma\space}发送\addcomma\space到缓冲区并替换其先前的值\adddot。然后\printfield{eid}打印eid,但在此之前,标点符号缓冲区被打印并清空。这导致

<volume><eid>

如果number存在,我们最终会得到

<volume><number><eid>

带星号的版本\setunit*检查\print...紧接在它之前的命令是否打印了某些内容。如果是,它的行为就像,如果不是,它会丢弃它的参数并且不执行任何操作。因此,在示例中,如果有但没有 ,\setunit则可以看到差异。假设上面的代码片段之前已插入标点符号缓冲区。使用 ,我们将得到numbervolume\printtext{Blah}\setunit{\addcomma\space}\addcomma\spacevolume

废话,<volume><number><eid>

但如果没有音量并且\setunit被使用,\adddot则会覆盖\addcomma\space以给出

废话<number><eid>

如果缺少\setunit*标点符号缓冲区,则不会发生任何事情,因此我们得到volume

废话<number>,,<eid>

因为即使在那之后什么也没做,它\addcomma\space仍然留在缓冲区中。\printfield{volume}\setunit*{\adddot}

authoryear-comp's中的标点符号\cite

引用宏authoryear-comp可以简化为以下方案(请查看\DeclareCiteCommand{\cite}\newbibmacro{cite}authoryear-comp.cbx

循环代码

<Lots of `\print...` commands>
\setunit{\multicitedelim}

邮政编码

\iffieldundef{postnote}
  {}
  {\setunit{\postnotedelim}%
   \printfield{postnote}}

对于您引用的每个条目,循环代码都会执行一次(因此\cite{sigfridsson,nussbaum}将先执行一次循环代码 for sigfridsson,然后再执行 for nussbaum),邮政编码在循环结束后执行。

如果您\cite执行没有后注的命令,即使完成后,该\cite命令也会在标点符号缓冲区中留下一个。这是因为循环代码的最后一行是,如果是空的,则邮政编码实际上会被跳过。通常这不是问题,因为通常在标点符号跟踪器不控制其\multicitedelim\setunit{\multicitedelim}postnote\cite周围环境以及 - 通常\cite后面没有\print...命令 - 因此缓冲区保持设置状态,但不会被打印。下一个\cite(或任何高级biblatex命令)会在执行其工作之前清除缓冲区,因此在完成后将缓冲区保持非空状态没有任何坏处。但是,在您的应用程序中,and\printfield之后有一个\cite,它\printfield会看到非空的标点符号缓冲区并在打印其内容之前将其插入。

如果有postnote,那么在循环代码完成其工作并留\multicitedelim在标点符号缓冲区中后,我们进入循环代码,采取第二个分支并遇到\setunit{\postnotedelim}。因此,\multicitedelim缓冲区中的 被 替换为\postnotedelim,然后\printfield{postnote}打印并清空标点符号缓冲区,最后打印postnote。请注意,在这一连串事件之后,标点符号缓冲区为空。\printfield之后的\cite没有标点符号可插入,只是打印其文本。

请注意,这种情况是由于 的authoryear-comp引用宏的实现细节而发生的。使用authoryear的引用命令时不会发生这种情况。authoryear它的循环代码不是以 结束的\setunit{\multicitedelim},而是\multicitedelim使用 sepcode 参数插入\DeclareCiteCommand。 无法做到这一点,因此必须在循环代码的末尾使用authoryear-comp(通常)风格有问题的。\setunit{\multictedelim}

结论

标点符号和空格应始终由标点符号跟踪器处理\setunit。切勿在命令之间直接插入空格或标点符号\print...

我应该补充一点,如果可能的话,\cite应该尽量避免在.bib条目和参考书目中使用。对于某些应用程序来说,该related功能可能更合适,但我认为在其他情况下,解决方法并不简单,需要一些思考。

您在这里所做的实际上是嵌套引用命令。通常biblatex会积极阻止嵌套引用命令(任何尝试过的人\cite[\cite{nussbaum}]{sigfridsson}都知道这一点),因为它们可能会导致 的biblatex许多跟踪功能混淆(\cite[\cite{nussbaum}]{sigfridsson}“ibid.”应该指什么? - 即使我们认为这意味着这是合理的,也sigfridsson很难执行,因为nussbaum实际上是最后处理的,并且biblatex的跟踪器必须是全局的,所以无论多少分组都无法帮助我们)。对于这种仅在受控环境中使用的高度专业化的引用命令来说,这可能不是什么大问题,但它肯定会导致正常引用命令中的混淆和意外行为。

相关内容