biblatex. 方便的作者引用

biblatex. 方便的作者引用

我快写完一篇文章了,到目前为止,我对处理作者姓名的方式不太满意。我使用的解决方案来自第一次出现时在 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}

这种方法并不理想,并且有一些缺点

  1. 如果有两个人的姓氏相同,则命令将被覆盖。也许可以使用该uniquename功能来避免这种情况。
  2. 包含非 ASCII 字符的名称可能会导致问题,因为该名称被用作\csname。这可以通过清理名称来解决(理想情况下使用 Biber 的源映射 -> 删除非 ASCII 字符,甚至可能是小写)。
  3. \<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}

相关内容