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.

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.

share|improve this question
    
Please provide a full minimal example. If I change the style of Audreys answer I get 0 Erros –  Marco Daniel Sep 5 '11 at 22:25
    
@Marco For context, refer to the comments here. I think the error is just omission of \makeatletter/makeatother. But on your end, you'll see a number of problems with the output. Also: apc is attempting to adapt the cite bib macro from authoryear-comp, which is different from the one in authoryear. –  Audrey Sep 5 '11 at 22:54
    
@Audrey: In my opinion it is very bad to ask such unclear questions or question with: see link_1...link_n. The possibility with makeatletter is more a guess ;-) (no MWE). –  Marco Daniel Sep 5 '11 at 23:09

2 Answers 2

up vote 7 down vote accepted

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.

share|improve this answer
    
+1 Clever! It doesn't seem to handle delimiters between compact labels and parentheses in \textcite correctly. (Try generating the sample document in my answer.) Can you fix this? –  Audrey Sep 5 '11 at 23:44
    
@Audray: Maybe tomorrow. I must sleep now ;-) (2:00am in Germany) –  Marco Daniel Sep 5 '11 at 23:52
    
Awesome. This works beautifully. Thanks! –  apc Sep 5 '11 at 23:54
    
@Marco I'm guessing the problem is \setunit. Your approach wraps the whole result in \printtext[bibhyperref], which prevents what would otherwise be adjacent \setunits (generated at the end of one cite/textcite and at the beginning of the next) from working their magic. –  Audrey Sep 6 '11 at 8:44
    
@Audrey: I compared the solution. I must think about it ;-) –  Marco Daniel Sep 6 '11 at 13:39

Both \cite and \textcite use \setunit inside the <loopcode> argument of \DeclareCiteCommand. Links will include punctuation if you simply wrap <loopcode> (or the cite and textcite bibliography macros) in \bibhyperref. Moreover printing of \setunit is deferred to the next \print* or \bibstring command. So it is difficult to ensure that this approach will create links that point to the correct item in the bibliography.

The following patches to cite will make a single link for labelname/label and labelyear+extrayear where appropriate. The patches to textcite will include the parentheses around labelyear+extrayear in the absence of prenote, postnote and citation lists. Otherwise separate links are applied, similar to the citation links obtained with natbib.

\documentclass{report}
\usepackage[style=authoryear-comp]{biblatex}
\usepackage{hyperref}
\usepackage{xpatch}

% Just for demo
\ExecuteBibliographyOptions{maxcitenames=1}

% Combine label and labelyear links
\xpatchbibmacro{cite}
  {\usebibmacro{cite:label}%
   \setunit{\addspace}%
   \usebibmacro{cite:labelyear+extrayear}}
  {\printtext[bibhyperref]{%
     \DeclareFieldAlias{bibhyperref}{default}%
     \usebibmacro{cite:label}%
     \setunit{\addspace}%
     \usebibmacro{cite:labelyear+extrayear}}}{}{}

% Include labelname in labelyear link
\xpatchbibmacro{cite}
  {\printnames{labelname}%
   \setunit{\nameyeardelim}%
   \usebibmacro{cite:labelyear+extrayear}}
  {\printtext[bibhyperref]{%
     \DeclareFieldAlias{bibhyperref}{default}%
     \printnames{labelname}%
     \setunit{\nameyeardelim}%
     \usebibmacro{cite:labelyear+extrayear}}}{}{}

% Access hyperref's citation link start/end commands
\makeatletter
\protected\def\blx@imc@biblinkstart{%
  \@ifnextchar[%]
    {\blx@biblinkstart}
    {\blx@biblinkstart[\abx@field@entrykey]}}
\def\blx@biblinkstart[#1]{%
  \blx@sfsave\hyper@natlinkstart{\the\c@refsection @#1}\blx@sfrest}
\protected\def\blx@imc@biblinkend{%
  \blx@sfsave\hyper@natlinkend\blx@sfrest}
\blx@regimcs{\biblinkstart \biblinkend}
\makeatother

\newbool{cbx:link}

% Include parentheses around labelyear in \textcite only in
% single citations without pre- and postnotes
\def\iflinkparens{%
  \ifboolexpr{ test {\ifnumequal{\value{multicitetotal}}{0}} and
               test {\ifnumequal{\value{citetotal}}{1}} and
               test {\iffieldundef{prenote}} and
               test {\iffieldundef{postnote}} }}

\xpatchbibmacro{textcite}
  {\printnames{labelname}}
  {\iflinkparens
     {\DeclareFieldAlias{bibhyperref}{default}%
      \global\booltrue{cbx:link}\biblinkstart%
      \printnames{labelname}}
     {\printtext[bibhyperref]{\printnames{labelname}}}}{}{}

\xpatchbibmacro{textcite}
  {\usebibmacro{cite:label}}
  {\iflinkparens
     {\DeclareFieldAlias{bibhyperref}{default}%
      \global\booltrue{cbx:link}\biblinkstart%
      \usebibmacro{cite:label}}
     {\usebibmacro{cite:label}}}{}{}

\xpretobibmacro{textcite:postnote}
  {\ifbool{cbx:link}% patch 2.7+
     {\ifbool{cbx:parens}
        {\bibcloseparen\global\boolfalse{cbx:parens}}
        {}%
         \biblinkend\global\boolfalse{cbx:link}}
        {}}
  {}
  {\xpatchbibmacro{textcite}% patch earlier releases
     {\setunit{%
        \ifbool{cbx:parens}
          {\bibcloseparen\global\boolfalse{cbx:parens}}
          {}%
        \multicitedelim}}
     {\ifbool{cbx:link}
        {\ifbool{cbx:parens}
           {\bibcloseparen\global\boolfalse{cbx:parens}}
           {}%
         \biblinkend\global\boolfalse{cbx:link}}
        {}%
      \setunit{%
        \ifbool{cbx:parens}
          {\bibcloseparen\global\boolfalse{cbx:parens}}
          {}%
        \multicitedelim}}
     {}{}}

\renewcommand{\baselinestretch}{1.2}
\setlength{\parskip}{\smallskipamount}
\setlength{\parindent}{0pt}
\addbibresource{biblatex-examples.bib}
\begin{document}
\null\vfill
\textbf{Single citations}

Filler text \parencite{aristotle:poetics}.
Filler text \parencite{kant:ku}. Filler text \parencite{cms}. \\
Filler text \parencite[See][23]{aristotle:poetics}.
Filler text \parencite[1--10]{kant:ku}. \\
\textcite{knuth:ct} and \textcite{knuth:ct:a}.
\textcite{knuth:ct:b} and \textcite{knuth:ct:c}. \\
\textcite{aristotle:poetics} and \textcite{kant:ku} and \textcite{cms}. \\
\textcite[e.g.][]{aristotle:poetics} and \textcite[10]{kant:ku}. \\
Filler text.\footcite[23]{aristotle:poetics} Filler text.\footcite[1--10]{aristotle:rhetoric}
Filler text.\footnote{\smartcite[10--15]{companion}}

\textbf{Unqualified citation lists}

\textcite{knuth:ct,knuth:ct:a,knuth:ct:b,knuth:ct:c} showed that... \\
\textcite[e.g.][10--15]{aristotle:poetics,aristotle:rhetoric,cms} showed that...\\
Filler text \parencite[See][for example]{aristotle:poetics,aristotle:rhetoric,cms}. \\
Filler text \parencite[etc.]{knuth:ct,knuth:ct:a,knuth:ct:b,knuth:ct:c}.

\textbf{Qualified citation lists}

\textcites{aristotle:poetics}{aristotle:rhetoric} showed that...
\textcites(See)(){aristotle:poetics}[cf.][]{aristotle:rhetoric}. \\
\textcites(See)()[e.g.][15]{aristotle:poetics}[cf.][10]{aristotle:rhetoric} \\
\parencites(See)()[10--15]{aristotle:poetics}[cf.][10]{aristotle:rhetoric} \\
\parencites{knuth:ct,knuth:ct:a}[10--11]{knuth:ct:b,knuth:ct:c}

\textbf{Mix of qualified and unqualified citation lists}

\textcites(See)()[e.g.][]{aristotle:poetics}[10]{bertram,companion} \\
\textcites[e.g.][]{aristotle:poetics,aristotle:rhetoric}[10]{companion} \\
\textcites[10]{aristotle:poetics}{aristotle:rhetoric}[cf.][]{bertram} \\
\textcites[15]{aristotle:poetics}[cf.][10]{bertram,companion}

\printbibliography
\chapter*{Appendix}
\end{document}

Here is the output you should get with biblatex 2.6 or earlier. The patches also work with later releases, where \textcite and friends incorporate the and string into the final citation delimiter.

enter image description here

share|improve this answer
    
Oh, I see. That makes sense. Thanks for clearing this up. –  apc Sep 6 '11 at 0:01

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.