使用biblatex
,可以非常轻松地选择作者(或编辑)姓名及其列表在参考书目中的显示方式。您可以选择名字和姓氏(以及姓名的其他部分)的顺序,决定名字和中间名是否应缩写为首字母或完全省略,并设置最多显示人数,其余人员隐藏在“et al.”或其本地变体中。
我怎样才能biblatex
自动使用适合一行(或任意宽度)的最长形式?
我希望它尝试以下变体(其中n是名字的数量):
- 所有名字均完整。
- 所有姓名、首字母缩写我最右边的 (1 ≤我≤n)。
- 所有带首字母的名字,删除我最右边的 (1 ≤我≤n–1),请添加“et al.”。
示例代码:
\documentclass[12pt,a4paper]{minimal}
\usepackage[showframe]{geometry}
\newcommand*\yearandtitle{\hfill \quad 2012\\
\textit{A very interesting book. With subtitle}. \hfill Someplace / Otherplace: SUP Press\par\medskip}
\begin{document}
% full line
\noindent Agnes Ursula \textsc{Thor}, Charles-Oliver \textsc{Author}, William \textsc{Riter} and Claire \textsc{Ontributor}\yearandtitle
% add Sandra Uperv-Isor
\noindent Agnes Ursula \textsc{Thor}, Charles-Oliver \textsc{Author}, William \textsc{Riter}, Claire \textsc{Ontributor} and Sandra \textsc{Uperv-Isor}\yearandtitle
% shorten as much as necessary
\noindent Agnes Ursula \textsc{Thor}, C.-O. \textsc{Author}, W. \textsc{Riter}, C. \textsc{Ontributor} and S. \textsc{Uperv-Isor}\yearandtitle
% add Gina Raphics
\noindent A. U. \textsc{Thor}, C.-O. \textsc{Author}, W. \textsc{Riter}, C. \textsc{Ontributor}, S. \textsc{Uperv-Isor} and G. \textsc{Raphics} \yearandtitle
% shorten
\noindent A. U. \textsc{Thor}, C.-O. \textsc{Author}, W. \textsc{Riter}, C. \textsc{Ontributor}, S. \textsc{Uperv-Isor} et al. \yearandtitle
\end{document}
参考书目:
@book{foo, Author={Agnes Ursula Thor and Charles-Oliver Author and William Riter and Claire Ontributor and Sandra Uperv-Isor and Gina Raphics}, Year={2014}, Title={A very interesting book}, Subtitle={With subtitle}, Publisher={SUP Press}, Location={Someplace / Otherplace}}
算法(伪代码):
\newlength\availablewidth{\linewidth}% for instance
\ifthenelse % 1. try all full names
{\widthof{\printnames{author}} < \availablewidth}% condition
{\printnames{author}}% then
{% else
\ifthenelse % 2. try all initial names
{\widthof{\printnames[initials]{author}} < \availablewidth}% condition
{\printnames[initials][]{author}}% then (advanced: expand the left-most ones again)
{% else (automatically set `maxbibnames` locally)
\printnames[initials][etal]{author}% (advanced: automatically determine local `minbibnames` value)
}
答案1
尝试下面的代码,它很大程度上依赖于上面的伪代码。
我们使用 a\savebox
来评估长度。我们只需要设置\setlength{\availablewidth}{\linewidth}
。
我们定义一个新的bibmacro
varwidthname
。我们需要一些新的名称格式
\DeclareNameFormat{first-last-full}{%
\usebibmacro{name:first-last}{#1}{#3}{#5}{#7}}
\DeclareNameFormat{first-last-inits}{%
\usebibmacro{name:first-last}{#1}{#4}{#5}{#7}}
\DeclareNameFormat{first-last-inits-etal}{%
\usebibmacro{name:first-last}{#1}{#4}{#5}{#7}%
\usebibmacro{name:andothers}}
\newlength{\availablewidth}
\setlength{\availablewidth}{\linewidth}
%\setlength{\availablewidth}{50mm}
\newcounter{templabelnamea}
\newcounter{templabelnameb}
\newcommand*{\thisnamedelim}{\multinamedelim}
\newif\ifprintouthappened
\printouthappenedfalse
\newsavebox\mybox
\makeatletter
\newbibmacro*{varwidthname}{%
\printouthappenedfalse
\sbox{\mybox}{\printnames[first-last-full][-\c@labelname]{labelname}}% this is the full name list
\ifdim\wd\mybox>\availablewidth% if the full list is to long, start shortening it
\sbox{\mybox}{\printnames[first-last-inits][-\c@labelname]{labelname}}% all initials
\ifdim\wd\mybox<\availablewidth
\setcounter{templabelnamea}{\c@labelname}%
\setcounter{templabelnameb}{\c@labelname}%
\addtocounter{templabelnameb}{-1}%
\loop\ifnum\value{templabelnamea}>1%
\ifnum\value{templabelnamea}=\c@labelname
\renewcommand{\thisnamedelim}{\finalnamedelim}%
\else
\renewcommand{\thisnamedelim}{\multinamedelim}%
\fi
\sbox{\mybox}{\printnames[first-last-full][1-\value{templabelnameb}]{labelname}\thisnamedelim\printnames[first-last-inits][\value{templabelnamea}-\c@labelname]{labelname}}%
\ifnum\wd\mybox<\availablewidth
\printnames[first-last-full][1-\value{templabelnameb}]{labelname}\thisnamedelim\printnames[first-last-inits][\value{templabelnamea}-\c@labelname]{labelname}%
\printouthappenedtrue
\let\iterate\relax
\fi
\addtocounter{templabelnamea}{-1}%
\addtocounter{templabelnameb}{-1}%
\repeat
\ifprintouthappened
\else
\printnames[first-last-inits][-\c@labelname]{labelname}%
\printouthappenedtrue
\fi
\else
\sbox{\mybox}{\printnames[first-last-inits][-\c@labelname]{labelname}}%
\setcounter{templabelnamea}{\c@labelname}%
\loop\ifnum\value{templabelnamea}>0
\sbox{\mybox}{\printnames[first-last-inits-etal][-\value{templabelnamea}]{labelname}}%
\ifnum\wd\mybox<\availablewidth
\printnames[first-last-inits-etal][-\value{templabelnamea}]{labelname}%
\printouthappenedtrue
\let\iterate\relax
\fi
\addtocounter{templabelnamea}{-1}%
\repeat
\fi
\else% full list is fine
\printnames[first-last-full][-\c@labelname]{labelname}%
\printouthappenedtrue
\fi
\ifprintouthappened
\else
\printnames[first-last-inits-etal][1-1]{labelname}%
\fi}
\makeatother
如果可用宽度太小而无法容纳任何内容,此命令将不会打印任何内容。
如果空间太小而无法容纳任何内容,该命令将始终选择最短的形式(一个作者,带有姓名首字母,如果适用的话,还有“et al.”)。
我们可以定义一个新的 cite 命令:\varwidthciteauthor
。
\DeclareCiteCommand{\varwidthciteauthor}
{\usebibmacro{prenote}}
{\usebibmacro{citeindex}%
\usebibmacro{varwidthname}}
{\multicitedelim}
{\usebibmacro{postnote}}
平均能量损失
\documentclass[a4paper]{article}
\usepackage[maxnames=999]{biblatex}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@book{foo1, Author={Agnes Ursula Thor and Charles-Oliver Author and William Riter and Claire Ontributor and Sandra Uperv-Isor and Gina Raphics}, Year={2014}, Title={A very interesting book}, Subtitle={With subtitle}, Publisher={SUP Press}, Location={Someplace / Otherplace}}
@book{foo2, Author={Agnes Ursula Thor and Charles-Oliver Author and William Riter and Claire Ontributor and Sandra Uperv-Isor}, Year={2014}, Title={A very interesting book}, Subtitle={With subtitle}, Publisher={SUP Press}, Location={Someplace / Otherplace}}
@book{foo3, Author={Agnes Ursula Thor and Charles-Oliver Author and William Riter and Claire Ontributor}, Year={2014}, Title={A very interesting book}, Subtitle={With subtitle}, Publisher={SUP Press}, Location={Someplace / Otherplace}}
@book{foo4, Author={Agnes Ursula Thor and Charles-Oliver Author and William Riter}, Year={2014}, Title={A very interesting book}, Subtitle={With subtitle}, Publisher={SUP Press}, Location={Someplace / Otherplace}}
@book{foo5, Author={Agnes Ursula Thor and Charles-Oliver Author}, Year={2014}, Title={A very interesting book}, Subtitle={With subtitle}, Publisher={SUP Press}, Location={Someplace / Otherplace}}
@book{foo6, Author={Agnes Ursula Thor}, Year={2014}, Title={A very interesting book}, Subtitle={With subtitle}, Publisher={SUP Press}, Location={Someplace / Otherplace}}
\end{filecontents*}
\addbibresource{\jobname.bib}
\DeclareCiteCommand{\varwidthciteauthor}
{\usebibmacro{prenote}}
{\usebibmacro{citeindex}%
\usebibmacro{varwidthname}}
{\multicitedelim}
{\usebibmacro{postnote}}
\DeclareNameFormat{first-last-full}{%
\usebibmacro{name:first-last}{#1}{#3}{#5}{#7}}
\DeclareNameFormat{first-last-inits}{%
\usebibmacro{name:first-last}{#1}{#4}{#5}{#7}}
\DeclareNameFormat{first-last-inits-etal}{%
\usebibmacro{name:first-last}{#1}{#4}{#5}{#7}%
\usebibmacro{name:andothers}}
\newlength{\availablewidth}
\setlength{\availablewidth}{\linewidth}
%\setlength{\availablewidth}{50mm}
\newcounter{templabelnamea}
\newcounter{templabelnameb}
\newcommand*{\thisnamedelim}{\multinamedelim}
\newif\ifprintouthappened
\printouthappenedfalse
\newsavebox\mybox
\makeatletter
\newbibmacro*{varwidthname}{%
\printouthappenedfalse
\sbox{\mybox}{\printnames[first-last-full][-\c@labelname]{labelname}}% this is the full name list
\ifdim\wd\mybox>\availablewidth% if the full list is to long, start shortening it
\sbox{\mybox}{\printnames[first-last-inits][-\c@labelname]{labelname}}% all initials
\ifdim\wd\mybox<\availablewidth
\setcounter{templabelnamea}{\c@labelname}%
\setcounter{templabelnameb}{\c@labelname}%
\addtocounter{templabelnameb}{-1}%
\loop\ifnum\value{templabelnamea}>1%
\ifnum\value{templabelnamea}=\c@labelname
\renewcommand{\thisnamedelim}{\finalnamedelim}%
\else
\renewcommand{\thisnamedelim}{\multinamedelim}%
\fi
\sbox{\mybox}{\printnames[first-last-full][1-\value{templabelnameb}]{labelname}\thisnamedelim\printnames[first-last-inits][\value{templabelnamea}-\c@labelname]{labelname}}%
\ifnum\wd\mybox<\availablewidth
\printnames[first-last-full][1-\value{templabelnameb}]{labelname}\thisnamedelim\printnames[first-last-inits][\value{templabelnamea}-\c@labelname]{labelname}%
\printouthappenedtrue
\let\iterate\relax
\fi
\addtocounter{templabelnamea}{-1}%
\addtocounter{templabelnameb}{-1}%
\repeat
\ifprintouthappened
\else
\printnames[first-last-inits][-\c@labelname]{labelname}%
\printouthappenedtrue
\fi
\else
\sbox{\mybox}{\printnames[first-last-inits][-\c@labelname]{labelname}}%
\setcounter{templabelnamea}{\c@labelname}%
\loop\ifnum\value{templabelnamea}>0
\sbox{\mybox}{\printnames[first-last-inits-etal][-\value{templabelnamea}]{labelname}}%
\ifnum\wd\mybox<\availablewidth
\printnames[first-last-inits-etal][-\value{templabelnamea}]{labelname}%
\printouthappenedtrue
\let\iterate\relax
\fi
\addtocounter{templabelnamea}{-1}%
\repeat
\fi
\else% full list is fine
\printnames[first-last-full][-\c@labelname]{labelname}%
\printouthappenedtrue
\fi
\ifprintouthappened
\else
\printnames[first-last-inits-etal][1-1]{labelname}%
\fi}
\makeatother
\begin{document}
\noindent\varwidthciteauthor{foo1}
\noindent\varwidthciteauthor{foo2}
\noindent\varwidthciteauthor{foo3}
\noindent\varwidthciteauthor{foo4}
\noindent\varwidthciteauthor{foo5}
\noindent\varwidthciteauthor{foo6}
\end{document}
请注意,您真的不应该在实际文档中使用这种引用命令,因为要测试的适当长度将比仅仅确定更难\linewidth
。而且 - 这是更重要的一点 - 它看起来非常不一致(有时您打印 4 个名字,然后又只有 2 个,有时只有首字母,有时是全名,有时甚至是两者之间的某种混合),风格指南通常会鄙视不一致 - 尤其是这种比例的不一致 - 这是有充分理由的。