Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

natbib and hyperref create by default two links to the bibentry in the reference section|chapter of the document:

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

enter image description here

In order to avoid two links to the bibliography (one for the [author] and one for the year [year], respectively), I took Audrey's solution to an older question and added it to my preamble.

\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

enter image description here

Which gets me almost where I want to be, but leaves me with two issues I would like to be solved:

  • while \citet includes pre- and postnotes in the link, \citep doesn't. How can \citep be changed to include postnotes?
  • is there a way to color the brackets and commas that are typeset in black in the unmodified first example also in black in the modified second example without removing them from the link?
share|improve this question
    
And is biblatex not an option? –  Marco Daniel May 19 '13 at 9:00
    
No, unfortunately am I very much committed to natbib –  D.Roepo May 19 '13 at 9:10
1  
@MarcoDaniel This problem is much more difficult to solve with biblatex. –  Audrey Jul 25 '13 at 19:32
add comment

2 Answers

up vote 4 down vote accepted

Linking postnotes in \citep was already addressed in a previous question. To set punctuation in black text, you can patch natbib's internal punctuation commands. These patches can be deferred to the beginning of your document to account for the fact that the punctuation commands are redefine-able (with, say, \bibpunct) at any point in your document preamble.

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

enter image description here

share|improve this answer
add comment

Fiddling around with my problem, and using egreg's solution to an earlier post, I found a solution which works for my specific case:

I defined new commands \mycitet and \mycitep in this way

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

and for demonstration purposes I also changed the document to

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

to obtain exactly what I want:

enter image description here

However, while this may serve prefectly as a demonstration of what I want, I would prefer a general solution to this specific one as

  • this approach does not adapt the parentheses to \bibliographystyle automatically
  • it might mess up other commands if I \let\citep\mycitep and \let\citet\mycitet

PS: Can somebody explain how egreg's snippet knows that ',' is my delimiter?

share|improve this answer
    
This question answers your post scriptum. In short, \@for loops only work on comma-separated lists. –  mafp May 21 '13 at 9:26
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.