4

I am using natbib for citations and often have to

  1. reference specific page numbers of sources, and
  2. reference sources in the possessive.

I am using hyperref for internal hyperlinks and I have not been able to find a way for hyperref to link either the possessive or the page numbers (in some cases - it seems to work with citet). MWE shown below, with a partial solution found on this site. Any suggestions?

\documentclass{article}
\usepackage{natbib}
  \def\citeaposay#1{\citeauthor{#1}'s (\citeyear{#1})}
\usepackage{etoolbox}

% This code is from 
%http://tex.stackexchange.com/questions/24136/natbib-and-hyperref-for-author-year-style-produces-two-links

\makeatletter

% Current citation \cite or \citet?
\newbool{NAT@bool@patch}

% Closing parenthesis already printed in hyperlink?
\newtoggle{NAT@tog@close}

% Flag \cite and \citet
\pretocmd{\citet}
  {\global\booltrue{NAT@bool@patch}}
  {}% Do nothing if patch works
  {}% Do nothing if patch fails

\pretocmd{\cite}
  {\global\booltrue{NAT@bool@patch}}
  {}% Do nothing if patch works
  {}% Do nothing if patch fails

% Don't print postnote if already printed in hyperlink
\newcommand\NAT@postnote[1]{%
  \iftoggle{NAT@tog@close}
    {}
    {#1}}

% Don't print closing bracket if already printed in hyperlink
% NB: We have to reset this so that all brackets are printed in multi-citations
\renewcommand\NAT@@close{%
  \ifbool{NAT@bool@patch}
    {\iftoggle{NAT@tog@close}
       {\global\togglefalse{NAT@tog@close}}
       {}}
    {\ifNAT@par\NAT@close\fi}}

% Patch main cite command to issue new postnote command
\patchcmd{\NAT@citex}
  {\else\NAT@cmt#2}
  {\else\NAT@postnote{\NAT@cmt#2}}
  {}% Do nothing if patch works
  {}% Do nothing if patch fails

% Patch main cite command to include postnote/closing bracket in hyperlink
\patchcmd{\NAT@citex}
  {\@citea\NAT@hyper@{%
     \NAT@nmfmt{\NAT@nm}%
     \hyper@natlinkbreak{\NAT@spacechar\NAT@@open\if*#1*\else#1\NAT@spacechar\fi}%
       {\@citeb\@extra@b@citeb}%
     \NAT@date}}
  {\@citea\NAT@hyper@{%
     \NAT@nmfmt{\NAT@nm}%
     \hyper@natlinkbreak{\NAT@spacechar\NAT@@open\if*#1*\else#1\NAT@spacechar\fi}%
       {\@citeb\@extra@b@citeb}%
     \ifbool{NAT@bool@patch}
       {\global\toggletrue{NAT@tog@close}%
        \NAT@date%
        \ifNAT@swa\else\if*#2*\else\NAT@cmt#2\fi\fi%
        \NAT@close}
       {\NAT@date}}}
  {}% Do nothing if patch works
  {}% Do nothing if patch fails

% Reset flags after citation is printed
\apptocmd{\NAT@citex}
  {\global\boolfalse{NAT@bool@patch}%
   \global\togglefalse{NAT@tog@close}}
  {}% Do nothing if patch works
  {}% Do nothing if patch fails

% Don't break hyperlinks between name and year
\renewcommand\hyper@natlinkbreak[2]{#1}

\makeatother

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

\begin{filecontents}{\jobname.bib}
@Book{adams,
  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}

\begin{document}
\bibpunct[]{(}{)}{;}{a}{,}{,}

\noindent
citet with page numbers: \citet[:23-25]{adams} is a good book. (here both parentheses should be hyperlinked) \\
citep with page numbers: As suggested by him \citep[:23-25]{adams}. (here :23-25 should be hyperlinked)\\
citeyear with page numbers: As suggested by him (\citeyear[:23-25]{adams}). (here :23-25 should be hyperlinked)\\
citeaposay with possessive: \citeaposay{adams} book suggests... (here 's should be hyperlinked)

\bibliographystyle{plainnat}
\bibliography{\jobname}

\end{document} 
David Carlisle
  • 757,742
Agnar
  • 73

1 Answers1

2

Including all postnotes in the hyperlink requires patches to both the \NAT@citex and \NAT@cite macros. A possessive suffix can be appended in the name format in the definition of a new citation command. The example below is adapted from \citet.

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

\makeatletter

\DeclareRobustCommand\citepos
  {\begingroup\def\NAT@nmfmt##1{{\NAT@up##1's}}%
   \NAT@swafalse\let\NAT@ctype\z@\NAT@partrue
   \@ifstar{\NAT@fulltrue\NAT@citetp}{\NAT@fullfalse\NAT@citetp}}

\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*}{}{}

\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{citepos}: \citepos[e.g.][100]{adams:life}; \citepos{adams:rest,companion} \\
\cmd{citet}: \citet[1--10]{companion,adams:rest,adams:life} \\
\cmd{cite}: \cite[e.g.][100]{adams:life}; \cite{adams:rest} \\
\cmd{citep}: \citep[e.g.][1--10]{adams:rest,adams:life} \\
\cmd{citetext}; \cmd{citealp}:
\citetext{see \citealp[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}

enter image description here

David Carlisle
  • 757,742
Audrey
  • 28,881