[Tex/LaTex] Biblatex, authoryear-comp, and hyperlinks

biblatexhyperref

In answer to this question, Audrey offered an answer that works great with the authoryear option.

(Context: I'm trying to get the hyperlink in citations to include the name of the author, and not just the year. Audrey provided a solution that works with authoryear, and I'm trying to adapt it to work with authoryear-comp.)

I'm trying to adapt the answer to make it work with authoryear-comp. Here is what I tried (it doesn't work—I get an error message: Latex Error: ./biblatex.tex:96 Argument of \@secondoftwo has an extra }. Runaway argument?):

\renewbibmacro*{cite}{%
\printtext[bibhyperref]{% Enclose cite macro output in hyperlink
    \global\togglefalse{cbx:hyperref}% Prevent nested hyperlinks
  \iffieldundef{shorthand}
    {\ifthenelse{\ifnameundef{labelname}\OR\iffieldundef{labelyear}}
       {\usebibmacro{cite:label}%
    \setunit{\addspace}%
    \usebibmacro{cite:labelyear+extrayear}%
        \usebibmacro{cite:reinit}}
       {\iffieldequals{namehash}{\cbx@lasthash}
          {\ifthenelse{\iffieldequals{labelyear}{\cbx@lastyear}\AND
                       \(\value{multicitecount}=0\OR\iffieldundef{postnote}\)}
             {\setunit{\addcomma}%
              \usebibmacro{cite:extrayear}}
             {\setunit{\compcitedelim}%
              \usebibmacro{cite:labelyear+extrayear}%
              \savefield{labelyear}{\cbx@lastyear}}}
          {\printnames{labelname}%
       \setunit{\nameyeardelim}%
           \usebibmacro{cite:labelyear+extrayear}%
           \savefield{namehash}{\cbx@lasthash}%
           \savefield{labelyear}{\cbx@lastyear}}}}
    {\usebibmacro{cite:shorthand}%
     \usebibmacro{cite:reinit}}%
\global\toggletrue{cbx:hyperref}}
  \setunit{\multicitedelim}}

I don't fully understand how \cite works under authoryear-comp, so maybe someone who does can see a way to do this? (I'm assuming it's possible, since this is how hyperlinks are implemented in BibTeX.)

EDIT (in re: to Marco's comment): Here's a minimal example:

\documentclass{article} 
\usepackage[utf8]{inputenc} 
\usepackage[style=authoryear-comp]{biblatex} 
\usepackage[colorlinks]{hyperref} 
\bibliography{biblatex-examples} 


\newtoggle{cbx:hyperref}
\toggletrue{cbx:hyperref}

\DeclareFieldFormat{bibhyperref}{% Adapted from bibhyperref format in biblatex.def
\iftoggle{cbx:hyperref}
{\bibhyperref{#1}}
{#1}}


\renewbibmacro*{cite}{%
\printtext[bibhyperref]{% Enclose cite macro output in hyperlink
    \global\togglefalse{cbx:hyperref}% Prevent nested hyperlinks
  \iffieldundef{shorthand}
    {\ifthenelse{\ifnameundef{labelname}\OR\iffieldundef{labelyear}}
       {\usebibmacro{cite:label}%
    \setunit{\addspace}%
    \usebibmacro{cite:labelyear+extrayear}%
        \usebibmacro{cite:reinit}}
       {\iffieldequals{namehash}{\cbx@lasthash}
          {\ifthenelse{\iffieldequals{labelyear}{\cbx@lastyear}\AND
                       \(\value{multicitecount}=0\OR\iffieldundef{postnote}\)}
             {\setunit{\addcomma}%
              \usebibmacro{cite:extrayear}}
             {\setunit{\compcitedelim}%
              \usebibmacro{cite:labelyear+extrayear}%
              \savefield{labelyear}{\cbx@lastyear}}}
          {\printnames{labelname}%
       \setunit{\nameyeardelim}%
           \usebibmacro{cite:labelyear+extrayear}%
           \savefield{namehash}{\cbx@lasthash}%
           \savefield{labelyear}{\cbx@lastyear}}}}
    {\usebibmacro{cite:shorthand}%
     \usebibmacro{cite:reinit}}%
\global\toggletrue{cbx:hyperref}}
  \setunit{\multicitedelim}}

\DeclareCiteCommand{\textcite}% Adapted from \textcite command in authoryear.cbx
  {\boolfalse{cbx:parens}}
  {\usebibmacro{citeindex}%
  \printtext[bibhyperref]{% Enclose textcite macro output in hyperlink
    \global\togglefalse{cbx:hyperref}% Prevent nested hyperlinks
    \usebibmacro{textcite}%
    \iffieldundef{postnote}% Include closing parenthesis if no postnote
      {\ifbool{cbx:parens}
         {\bibcloseparen\global\boolfalse{cbx:parens}}
      {}}
   {}}%
 \global\toggletrue{cbx:hyperref}}
 {\ifbool{cbx:parens}
 {\bibcloseparen\global\boolfalse{cbx:parens}}
 {}%
  \multicitedelim}
 {\iffieldundef{postnote}
  {}
 {\usebibmacro{textcite:postnote}}}

\begin{document} 
A reference to \parencite{kastenholz,sigfridsson} and~\cite{sigfridsson}. 
\printbibliography 
\end{document}

I'm using references from the biblatex-example database. The error I get is this: Paragraph ended before \@secondoftwo was complete.

Best Answer

I would prefer another solution:

\makeatletter
%Works without the last bracket ;-)
\let\abx@macro@citeOrig\abx@macro@cite
\renewbibmacro{cite}{%
   \bibhyperref{%
   \let\bibhyperref\relax\relax%
   \abx@macro@citeOrig%
   }%
}
\let\abx@macro@textciteOrig\abx@macro@textcite
\renewbibmacro{textcite}{%
   \bibhyperref{%
   \let\bibhyperref\relax\relax%
   \abx@macro@textciteOrig%
   }%
}%
\makeatother

You can use it for every cite-command.

\documentclass{article} 
\usepackage[utf8]{inputenc} 
\usepackage[style=authoryear-comp,backend=biber,hyperref]{biblatex} 
\usepackage[colorlinks]{hyperref} 
\bibliography{biblatex-examples} 

\makeatletter
%Works without the last bracket ;-)
\let\abx@macro@citeOrig\abx@macro@cite
\renewbibmacro{cite}{%
   \bibhyperref{%
   \let\bibhyperref\relax\relax%
   \abx@macro@citeOrig%
   }%
}
\let\abx@macro@textciteOrig\abx@macro@textcite
\renewbibmacro{textcite}{%
   \bibhyperref{%
   \let\bibhyperref\relax\relax%
   \abx@macro@textciteOrig%
   }%
}%
\makeatother


\begin{document} 
A reference to \parencite{kastenholz,sigfridsson} and~\cite{sigfridsson}. 
\printbibliography 
\end{document}

EDIT:

I change the code of the example above.

\makeatletter
   \patchcmd{\blx@citeprint}%
           {\blx@loopcode}%
           {\blx@imc@bibhyperlink{#1}‌​‌​{\blx@loopcode}}%
           {}{}
\makeatother

The problem: The last bracket isn't part of the link.

Related Question