我快写完一篇文章了,到目前为止,我对处理作者姓名的方式不太满意。我使用的解决方案来自第一次出现时在 biblatex 中引用作者的全名并用 引用作者姓名\citeauthor{key}
。
嗯,如果你总是要处理键,那么源代码中的阅读就会变得困难,尤其是当你有多个条目属于同一个作者时。所以我正在寻找一种让作者引用更方便的方法。
看看以下 MWE:
\documentclass{article}
\usepackage[style=verbose-ibid]{biblatex}
\usepackage{filecontents}
\begin{filecontents*}{mybib.bib}
@book{kpv,
author={Immanuel Kant},
title={Kritik der praktischen Vernunft}
}
@book{krv,
author={Immanuel Kant},
title={Kritik der reinen Vernunft}
}
@book{sz,
author={Martin Heidegger},
title={Sein und Zeit}
}
@book{sg,
author={Martin Heidegger},
title={Der Satz vom Grund}
}
\end{filecontents*}
\addbibresource{mybib.bib}
\makeatletter
\newcommand*{\cbx@seennames}{}
\newrobustcmd*{\cbx@nameseen}[1]{%
\listxadd{\cbx@seennames}{\detokenize{#1}}}
\newrobustcmd*{\cbx@ifnameseen}[1]{%
\xifinlist{\detokenize{#1}}{\cbx@seennames}}
\DeclareNameFormat{citeauthor}{%
\cbx@ifnameseen{#1#3#5#7}
{\ifcase\value{uniquename}%
\usebibmacro{name:last}{#1}{#3}{#5}{#7}%
\or
\ifuseprefix
{\usebibmacro{name:first-last}{#1}{#4}{#5}{#8}}
{\usebibmacro{name:first-last}{#1}{#4}{#6}{#8}}%
\fi}%
{\usebibmacro{name:first-last}{#1}{#3}{#5}{#7}%
\cbx@nameseen{#1#3#5#7}}%
\usebibmacro{name:andothers}}
\DeclareCiteCommand{\citeauthor}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\indexnames{labelname}%
\printnames[citeauthor]{labelname}}
{\multicitedelim}
{\usebibmacro{postnote}}
\makeatother
\begin{document}
\noindent{}\citeauthor{sz} has shown that\ldots, but \citeauthor{kpv} presumes that\ldots.
However, \citeauthor{krv} lived in the 18. century, \citeauthor{sg} in the 20.
\nocite{*}
\printbibliography
\end{document}
想法1:让 LaTeX 自动从 .bib 文件中生成类似\kant
和的命令\heidegger
。我不知道这是否可行,但那绝对是我最喜欢的。
想法2:让 biblatex 自动为每位作者生成虚拟条目(即 @book)。因此,在下面的示例中,它必须生成条目@book{kant,authorname={Immanuel Kant}}
和,@book{heidegger,authorname={Martin Heidegger}}
并且我至少可以使用\citeauthor{kant}
。
如果一条记录有多个作者,那么这一切可能会变得更加困难:\heideggeretal
答案1
您可能对以下方面感兴趣nameauth
用于一致名称格式的包。
以下是一些入门知识。你可以忽略第一部分,这只是我回答的副本首次引用名字略有改善第一次出现时在 biblatex 中引用作者的全名并使其与biblatex
>= 3.3 兼容。
从 开始的第二段代码为遇到的每个名称\DeclareCiteCommand{\specialciteauthor}
创建一个宏\<Lastname>
,并将其与 的内部版本相关联\citeauthor{<some entry key authored by name>}
。
\documentclass{article}
\usepackage[style=verbose-ibid]{biblatex}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@book{kpv,
author={Immanuel Kant},
title={Kritik der praktischen Vernunft}
}
@book{krv,
author={Immanuel Kant},
title={Kritik der reinen Vernunft}
}
@book{sz,
author={Martin Heidegger},
title={Sein und Zeit}
}
@book{sg,
author={Martin Heidegger},
title={Der Satz vom Grund}
}
@book{apphack,
author={Humprey Appleby and James Hacker},
title={On the Importance of the Civil Service}
}
\end{filecontents*}
\addbibresource{\jobname.bib}
\makeatletter
\newrobustcmd*{\cbx@nametracker@global}[1]{%
\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}
{}
{\listcsxadd{cbx@bseen@names@\the\c@refsection}{#1}}}
\newrobustcmd*{\cbx@nametracker@context}[1]{%
\iftoggle{blx@footnote}
{\xifinlistcs{#1}{cbx@fseen@names@\the\c@refsection}
{}
{\listcsxadd{cbx@fseen@names@\the\c@refsection}{#1}}}
{\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}
{}
{\listcsxadd{cbx@bseen@names@\the\c@refsection}{#1}}}}
\newrobustcmd*{\cbx@ifnameseen@global}[1]{%
\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}}
\newrobustcmd*{\cbx@ifnameseen@context}[1]{%
\iftoggle{blx@footnote}%
{\xifinlistcs{#1}{cbx@fseen@names@\the\c@refsection}}%
{\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}}}
\DeclareBibliographyOption[string]{nametracker}[true]{%
\ifcsdef{blx@opt@nametracker@#1}
{\csuse{blx@opt@nametracker@#1}}
{\blx@err@invopt{nametracker=#1}{}}}
\def\blx@opt@nametracker@global{%
\let\cbx@ifnameseen\cbx@ifnameseen@global
\let\cbx@nametracker\cbx@nametracker@global}
\let\blx@opt@nametracker@true\blx@opt@nametracker@global
\def\blx@opt@nametracker@false{%
\protected\long\def\cbx@ifnameseen##1##2##3{##3}%
\let\cbx@nametracker\relax}
\def\blx@opt@nametracker@context{%
\let\cbx@ifnameseen\cbx@ifnameseen@context
\let\cbx@nametracker\cbx@nametracker@context}
\appto\blx@secinit{%
\ifcsundef{cbx@bseen@names@\the\c@refsection}
{\global\cslet{cbx@bseen@names@\the\c@refsection}\@empty}
{}%
\ifcsundef{cbx@fseen@names@\the\c@refsection}
{\global\cslet{cbx@fseen@names@\the\c@refsection}\@empty}
{}}
\InitializeCitationStyle{%
\global\cslet{cbx@bseen@names@\the\c@refsection}\@empty
\global\cslet{cbx@fseen@names@\the\c@refsection}\@empty}
\ExecuteBibliographyOptions{nametracker=context}
\DeclareNameFormat{labelname}{%
\cbx@ifnameseen{\thefield{hash}}
{\ifcase\value{uniquename}%
\usebibmacro{name:family}
{\namepartfamily}
{\namepartgiven}
{\namepartprefix}
{\namepartsuffix}%
\or
\ifuseprefix
{\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiveni}
{\namepartprefix}
{\namepartsuffixi}}
{\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiveni}
{\namepartprefixi}
{\namepartsuffixi}}%
\or
\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiven}
{\namepartprefix}
{\namepartsuffix}%
\fi}
{\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiven}
{\namepartprefix}
{\namepartsuffix}%
\cbx@nametracker{\thefield{hash}}}%
\usebibmacro{name:andothers}}
\DeclareCiteCommand{\specialciteauthor}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}}
{\renewbibmacro*{name:andothers}{}%
\printnames[labelname][\thefield{postnote}-\thefield{postnote}]{author}}
{}
{}
\DeclareIndexNameFormat{createauthorcommands}{%
\ifcsundef{nbx@\thefield{hash}}
{\global\cslet{nbx@\thefield{hash}}\@empty
\csxdef{\namepartfamily}{%
\noexpand\specialciteauthor[\the\value{listcount}]
{\thefield{entrykey}}}%
\typeout{created author command '\namepartfamily' for
\namepartfamily\space to point to author
\the\value{listcount} of \thefield{entrykey}.}
}
{}}%
\AtDataInput{\indexnames[createauthorcommands][1-999]{author}}
\makeatother
\begin{document}
\Kant{} and \Appleby{} and \Hacker{}
\citeauthor{sz} has shown that\ldots, but \citeauthor{kpv} presumes that\ldots.
However, \citeauthor{krv} lived in the 18. century, \citeauthor{sg} in the 20.
\nocite{*}
\printbibliography
\end{document}
这种方法并不理想,并且有一些缺点
- 如果有两个人的姓氏相同,则命令将被覆盖。也许可以使用该
uniquename
功能来避免这种情况。 - 包含非 ASCII 字符的名称可能会导致问题,因为该名称被用作
\csname
。这可以通过清理名称来解决(理想情况下使用 Biber 的源映射 -> 删除非 ASCII 字符,甚至可能是小写)。 - 宏
\<Lastname>
仅在 Biber 运行后可用。因此,示例中\Kant
会产生未定义的控制序列错误。编译不能中止(因为这样 Biber 就无法运行),告诉 TeX 继续运行,然后运行 Biber,下次运行应该就可以正常工作了。这可以通过使用不同的接口(如始终可以定义的\mmname{Kant}
位置)来解决。\mmname
以下方法解决了问题 3,并用于uniquename
防止问题 1 中所述的名称冲突。
\documentclass{article}
\usepackage[style=verbose-ibid, uniquename, maxnames=999]{biblatex}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@book{kpv,
author={Immanuel Kant},
title={Kritik der praktischen Vernunft}
}
@book{krv,
author={Immanuel Kant},
title={Kritik der reinen Vernunft}
}
@book{sz,
author={Martin Heidegger},
title={Sein und Zeit}
}
@book{sg,
author={Martin Heidegger},
title={Der Satz vom Grund}
}
@book{apphack,
author={Humprey Appleby and James Hacker},
title={On the Importance of the Civil Service}
}
@book{elk,
author={Emma Elk and Anne Belk},
title={Brontos!}
}
@book{elk2,
author={Anne Elk and Anna Belk},
title={Brontos!}
}
\end{filecontents*}
\addbibresource{\jobname.bib}
\makeatletter
\newrobustcmd*{\cbx@nametracker@global}[1]{%
\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}
{}
{\listcsxadd{cbx@bseen@names@\the\c@refsection}{#1}}}
\newrobustcmd*{\cbx@nametracker@context}[1]{%
\iftoggle{blx@footnote}
{\xifinlistcs{#1}{cbx@fseen@names@\the\c@refsection}
{}
{\listcsxadd{cbx@fseen@names@\the\c@refsection}{#1}}}
{\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}
{}
{\listcsxadd{cbx@bseen@names@\the\c@refsection}{#1}}}}
\newrobustcmd*{\cbx@ifnameseen@global}[1]{%
\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}}
\newrobustcmd*{\cbx@ifnameseen@context}[1]{%
\iftoggle{blx@footnote}%
{\xifinlistcs{#1}{cbx@fseen@names@\the\c@refsection}}%
{\xifinlistcs{#1}{cbx@bseen@names@\the\c@refsection}}}
\DeclareBibliographyOption[string]{nametracker}[true]{%
\ifcsdef{blx@opt@nametracker@#1}
{\csuse{blx@opt@nametracker@#1}}
{\blx@err@invopt{nametracker=#1}{}}}
\def\blx@opt@nametracker@global{%
\let\cbx@ifnameseen\cbx@ifnameseen@global
\let\cbx@nametracker\cbx@nametracker@global}
\let\blx@opt@nametracker@true\blx@opt@nametracker@global
\def\blx@opt@nametracker@false{%
\protected\long\def\cbx@ifnameseen##1##2##3{##3}%
\let\cbx@nametracker\relax}
\def\blx@opt@nametracker@context{%
\let\cbx@ifnameseen\cbx@ifnameseen@context
\let\cbx@nametracker\cbx@nametracker@context}
\appto\blx@secinit{%
\ifcsundef{cbx@bseen@names@\the\c@refsection}
{\global\cslet{cbx@bseen@names@\the\c@refsection}\@empty}
{}%
\ifcsundef{cbx@fseen@names@\the\c@refsection}
{\global\cslet{cbx@fseen@names@\the\c@refsection}\@empty}
{}}
\InitializeCitationStyle{%
\global\cslet{cbx@bseen@names@\the\c@refsection}\@empty
\global\cslet{cbx@fseen@names@\the\c@refsection}\@empty}
\ExecuteBibliographyOptions{nametracker=context}
\DeclareNameFormat{labelname}{%
\cbx@ifnameseen{\thefield{hash}}
{\ifcase\value{uniquename}%
\usebibmacro{name:family}
{\namepartfamily}
{\namepartgiven}
{\namepartprefix}
{\namepartsuffix}%
\or
\ifuseprefix
{\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiveni}
{\namepartprefix}
{\namepartsuffixi}}
{\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiveni}
{\namepartprefixi}
{\namepartsuffixi}}%
\or
\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiven}
{\namepartprefix}
{\namepartsuffix}%
\fi}
{\usebibmacro{name:given-family}
{\namepartfamily}
{\namepartgiven}
{\namepartprefix}
{\namepartsuffix}%
\cbx@nametracker{\thefield{hash}}}%
\usebibmacro{name:andothers}}
\DeclareCiteCommand{\specialciteauthor}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}}
{\renewbibmacro*{name:andothers}{}%
\printnames[labelname][\thefield{postnote}-\thefield{postnote}]{author}}
{}
{}
\DeclareIndexNameFormat{createauthorcommands}{%
\ifcsundef{nbx@\thefield{hash}}
{\global\cslet{nbx@\thefield{hash}}\@empty
\typeout{\the\value{uniquename}}%
\ifcase\value{uniquename}
\def\nbx@macroname{\namepartfamily}%
\or
\def\nbx@macroname{\namepartfamily\namepartgiveni}%
\or
\def\nbx@macroname{\namepartfamily\namepartgiven}%
\fi
\csxdef{nbx@\nbx@macroname}{%
\noexpand\specialciteauthor[\the\value{listcount}]
{\thefield{entrykey}}}%
\typeout{created author command '\nbx@macroname'
to point to author \the\value{listcount} of
\thefield{entrykey}.}}
{}}%
\AtDataInput{\indexnames[createauthorcommands][1-999]{author}}
\newcommand*{\mmname}[1]{%
\ifcsundef{nbx@#1}
{\textbf{#1}%
\@latex@warning{Name #1 not found.\MessageBreak
Either you need to re-run Biber and then LaTeX,\MessageBreak
or the name is misspelled.}}
{\csuse{nbx@#1}}}
\makeatother
\begin{document}
\mmname{Kant} and \mmname{Appleby} and \mmname{Hacker}
\citeauthor{sz} has shown that\ldots, but \citeauthor{kpv} presumes that\ldots.
However, \citeauthor{krv} lived in the 18. century, \citeauthor{sg} in the 20.
\nocite{*}
\printbibliography
\end{document}