使用 natbib 和 hyperref 的(作者,年份)引用样式的单一链接

使用 natbib 和 hyperref 的(作者,年份)引用样式的单一链接

natbibhyperref默认创建两个指向文档参考部分|章节中的 bibentry 的链接:

\begin{filecontents}{\jobname.bib}
@book{author08,
title = {{A Title}},
publisher = {Alpha},
year = {2008},
author = {Author, A},
address = {London}
}
@book{buthor90,
title = {{B Title}},
publisher = {Bravo},
year = {1990},
editor = {Buthor, B},
address = {New York}
}
\end{filecontents}

\documentclass{article}

\usepackage{natbib}
\usepackage{hyperref}
\hypersetup{colorlinks,citecolor=red}

\begin{document}

\noindent
citet: \citet{author08}, \citet[see][p. 20]{author08} \\
citep: \citep{author08}, \citep[see][p. 20]{author08}

\bibliographystyle{plainnat}
\bibliography{\jobname}

\end{document}

在此处输入图片描述

为了避免出现两个参考书目链接(一个链接指向[作者],一个链接指向[年份]),我采用了奥黛丽的解决方案回答一个老问题并将其添加到我的序言中。

\usepackage{etoolbox}
\makeatletter

\pretocmd{\NAT@citex}{%
  \let\NAT@hyper@\NAT@hyper@citex
  \def\NAT@postnote{#2}%
  \setcounter{NAT@total@cites}{0}%
  \setcounter{NAT@count@cites}{0}%
  \forcsvlist{\stepcounter{NAT@total@cites}\@gobble}{#3}}{}{}
\newcounter{NAT@total@cites}
\newcounter{NAT@count@cites}
\def\NAT@postnote{}

% include postnote and \citet closing bracket in hyperlink
\def\NAT@hyper@citex#1{%
  \stepcounter{NAT@count@cites}%
  \hyper@natlinkstart{\@citeb\@extra@b@citeb}#1%
  \ifnumequal{\value{NAT@count@cites}}{\value{NAT@total@cites}}
    {\ifNAT@swa\else\if*\NAT@postnote*\else%
     \NAT@cmt\NAT@postnote\global\def\NAT@postnote{}\fi\fi}{}%
  \ifNAT@swa\else\if\relax\NAT@date\relax
  \else\NAT@@close\global\let\NAT@nm\@empty\fi\fi% avoid compact citations
  \hyper@natlinkend}
\renewcommand\hyper@natlinkbreak[2]{#1}

% avoid extraneous postnotes, closing brackets
\patchcmd{\NAT@citex}
  {\ifNAT@swa\else\if*#2*\else\NAT@cmt#2\fi
   \if\relax\NAT@date\relax\else\NAT@@close\fi\fi}{}{}{}
\patchcmd{\NAT@citex}
  {\if\relax\NAT@date\relax\NAT@def@citea\else\NAT@def@citea@close\fi}
  {\if\relax\NAT@date\relax\NAT@def@citea\else\NAT@def@citea@space\fi}{}{}

\makeatother

在此处输入图片描述

这几乎让我达到了我想要的目标,但仍有两个问题需要解决:

  • 虽然\citet链接中包含前注和后注,但\citep不包括。如何才能\citep更改为包含后注?
  • 有没有办法将未修改的第一个例子中用黑色排版的括号和逗号在修改后的第二个例子中也变成黑色,而无需将它们从链接中删除?

答案1

链接后记\citep已在上一个问题。要设置黑色文本中的标点符号,您可以修补 natbib 的内部标点符号命令。这些修补程序可以推迟到文档的开头,以说明标点符号命令可以\bibpunct在文档前言的任何位置重新定义(例如,)。

\documentclass{article}
\usepackage{natbib}
\usepackage[colorlinks]{hyperref}
\usepackage{etoolbox}

\makeatletter

% count citations
\pretocmd{\NAT@citex}{%
  \let\NAT@hyper@\NAT@hyper@citex
  \def\NAT@postnote{#2}%
  \setcounter{NAT@total@cites}{0}%
  \setcounter{NAT@count@cites}{0}%
  \forcsvlist{\stepcounter{NAT@total@cites}\@gobble}{#3}}{}{}
\newcounter{NAT@total@cites}
\newcounter{NAT@count@cites}
\def\NAT@postnote{}

% include postnote and \citet closing bracket in hyperlink
\def\NAT@hyper@citex#1{%
  \stepcounter{NAT@count@cites}%
  \hyper@natlinkstart{\@citeb\@extra@b@citeb}#1%
  \ifnumequal{\value{NAT@count@cites}}{\value{NAT@total@cites}}
    {\if*\NAT@postnote*\else\NAT@cmt\NAT@postnote\global\def\NAT@postnote{}\fi}{}%
  \ifNAT@swa\else\if\relax\NAT@date\relax
  \else\NAT@@close\global\let\NAT@nm\@empty\fi\fi% avoid compact citations
  \hyper@natlinkend}
\renewcommand\hyper@natlinkbreak[2]{#1}

% avoid extraneous postnotes, closing brackets
\patchcmd{\NAT@citex}
  {\ifNAT@swa\else\if*#2*\else\NAT@cmt#2\fi
   \if\relax\NAT@date\relax\else\NAT@@close\fi\fi}{}{}{}
\patchcmd{\NAT@citex}
  {\if\relax\NAT@date\relax\NAT@def@citea\else\NAT@def@citea@close\fi}
  {\if\relax\NAT@date\relax\NAT@def@citea\else\NAT@def@citea@space\fi}{}{}
\patchcmd{\NAT@cite}{\if*#3*}{\if*\NAT@postnote*}{}{}

% all punctuation black
\AtBeginDocument{%
  \preto\NAT@sep{\textcolor{black}\bgroup}%
  \appto\NAT@sep{\egroup}%
  \preto\NAT@aysep{\textcolor{black}\bgroup}%
  \appto\NAT@aysep{\egroup}%
  \preto\NAT@yrsep{\textcolor{black}\bgroup}%
  \appto\NAT@yrsep{\egroup}%
  \preto\NAT@cmt{\textcolor{black}\bgroup}%
  \appto\NAT@cmt{\egroup}%
  \preto\NAT@open{\textcolor{black}\bgroup}%
  \appto\NAT@open{\egroup}%
  \preto\NAT@close{\textcolor{black}\bgroup}%
  \appto\NAT@close{\egroup}}

\makeatother

\begin{filecontents}{\jobname.bib}
@book{companion,
  author = {Goossens, Michel and Mittelbach, Frank and Samarin, Alexander},
  title = {The LaTeX Companion},
  edition = {1},
  publisher = {Addison-Wesley},
  location = {Reading, Mass.},
  year = {1994}}
@book{adams:life,
  title = {Life, the Universe and Everything},
  author = {Adams, Douglas},
  series = {The Hitchhiker's Guide to the Galaxy},
  publisher = {Pan Macmillan},
  year = {1980}}
@book{adams:rest,
  title = {The Restaurant at the End of the Universe},
  author = {Douglas Adams},
  series = {The Hitchhiker's Guide to the Galaxy},
  publisher = {Pan Macmillan},
  year = {1980}}
\end{filecontents}

\newcommand{\cmd}[1]{\textbackslash\texttt{#1}}
\begin{document}
\noindent
\cmd{citet}: \citet[e.g.][pp.~1--10]{companion} \\
\cmd{citet}: \citet[pp.~1--10]{companion,adams:rest,adams:life} \\
\cmd{cite}: \cite[e.g.][p.~100]{adams:life}; \cite{adams:rest} \\
\cmd{citep}: \citep[e.g.][p.~1--10]{adams:rest,adams:life} \\
\cmd{citetext}; \cmd{citealp}:
\citetext{see \citealp[pp.~10]{adams:rest}; or even better \citealp{adams:life}} \\
\cmd{citeauthor}: \citeauthor{adams:life}; \citeauthor{companion} \\
\cmd{citeyear}: \citeyear{adams:life}; \citeyear{adams:rest} \\
\bibliographystyle{plainnat}
\bibliography{\jobname}
\end{document}

在此处输入图片描述

答案2

摆弄我的问题,并使用egreg 对之前帖子的解决方案,我找到了一个适合我的具体情况的解决方案:

我定义了新的命令\mycitet,并\mycitep以这种方式

\usepackage{twoopt}
\usepackage{ifthen}

\newcommand\black[1]{\textcolor[rgb]{0,0,0}{#1}}

\newcommandtwoopt{\mycitet}[3][aa][bb]{%
    \ifthenelse{\equal{#1}{aa}}                                                                         % if nargin == 1
      {\hyperlink{cite.#3}{\citeauthor{#3} \black{(}\citeyear{#3}\black{)}}}                            %     \citet{key}
      {\ifthenelse{\equal{#2}{bb}}                                                                      % elseif nargin == 2
        {\hyperlink{cite.#3}{\citeauthor{#3} \black{(}\citeyear{#3}\black{,}~#1\black{)}}}              %     \citet[pg]{key}
        {\ifthenelse{\equal{#1}{}}                                                                      % elseif #1 = []
          {\hyperlink{cite.#3}{\citeauthor{#3} \black{(}\citeyear{#3}\black{,}~#2\black{)}}}            %     \citet[][pg]{key}
          {\ifthenelse{\equal{#2}{}}                                                                    % elseif #2 == []
            {\hyperlink{cite.#3}{\citeauthor{#3} \black{(#1~}\citeyear{#3}\black{)}}}                   %     \citet[eg][]{key}
            %                                                                                           % else
            {\hyperlink{cite.#3}{\citeauthor{#3} \black{(#1~}\citeyear{#3}\black{,}~#2\black{)}}}       %     \citet[eg][pg]{key}}
          }
        }
      }
}

\makeatletter 
\newcommand{\multicite}[1]{% taken from egreg, see link
  \@tempswafalse
  \@for\next:=#1\do
    {\if@tempswa;~\else\@tempswatrue\fi
    \hyperlink{cite.\next}{\citeauthor{\next}\black{,~}\citeyear{\next}}%
    }%
}
\makeatother

\newcommandtwoopt{\mycitep}[3][aa][bb]{%        
    \ifthenelse{\equal{#1}{aa}}                                                                  % if nargin == 1
      {(\multicite{#3})}                                                                         %    \citep{key(s)}
      {\ifthenelse{\equal{#2}{bb}}                                                               % elseif nargin == 2
          {(\hyperlink{cite.#3}{\citeauthor{#3}\black{,~}\citeyear{#3}\black{,~}#1})}            %    \citep[pg]{key}
          {\ifthenelse{\equal{#1}{}}                                                             % elseif #1 = []
              {(\hyperlink{cite.#3}{\citeauthor{#3}\black{,~}\citeyear{#3}\black{,~}#2})}        %    \citep[][pg]{key}
              {\ifthenelse{\equal{#2}{}}                                                         % elseif #2 == []
                  {(#1~\multicite{#3})}                                                          %    \citep[eg][]{key(s)}
                  %                                                                              % else
                  {(#1~\hyperlink{cite.#3}{\citeauthor{#3}\black{,~}\citeyear{#3}\black{,~}#2})} %    \citep[eg][pg]{key}}
              }
           }
      }
}

为了演示目的,我还将文档更改为

\begin{document}

\begin{tabular}{lll}
                           & Audrey                             & me, myself and I                    \\
\hline\hline
citet\{key\}               & \citet{author08}                   & \mycitet{author08}                  \\
citet[pg]\{key\}           & \citet[pg.7]{author08}             & \mycitet[pg.7]{author08}            \\
citet[ ][pg]\{key\}        & \citet[][pg.7]{author08}           & \mycitet[][pg.7]{author08}          \\
citet[eg][ ]\{key\}        & \citet[e.g.][]{author08}           & \mycitet[e.g.][]{author08}          \\
citet[eg][pg]\{key\}       & \citet[e.g.][pg.7]{author08}       & \mycitet[e.g.][pg.7]{author08}      \\
\hline
citep\{key\}               & \citep{author08}                   & \mycitep{author08}                  \\
citep[pg]\{key\}           & \citep[pg.7]{author08}             & \mycitep[pg.7]{author08}            \\
citep[ ][pg]\{key\}        & \citep[][pg.7]{author08}           & \mycitep[][pg.7]{author08}          \\
citep[eg][ ]\{key\}        & \citep[e.g.][]{author08}           & \mycitep[e.g.][]{author08}          \\
citep[eg][pg]\{key\}       & \citep[e.g.][pg.7]{author08}       & \mycitep[e.g.][pg.7]{author08}      \\
\hline
citep\{key1,key2\}         & \citep{author08,buthor90}          & \mycitep{author08,buthor90}         \\
citep[eg][ ]\{key1,key2\}  & \citep[e.g.][]{author08,buthor90}  & \mycitep[e.g.][]{author08,buthor90} \\
\end{tabular}

\bibliographystyle{plainnat}
\bibliography{\jobname}

\end{document}

得到我想要的东西:

在此处输入图片描述

然而,虽然这可以完美地展示我想要的东西,但我更希望对这个具体问题有一个通用的解决方案,因为

  • 这种方法不会自动将括号适配到 \bibliographystyle
  • \let\citep\mycitep如果我和它可能会弄乱其他命令\let\citet\mycitet

PS:有人可以解释一下 egreg 的代码片段如何知道“,”是我的分隔符吗?

相关内容