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.

What is the right way to define a macro with an optional argument that can be called within the <postnote> optional argument to biblatex \cite?

The last two \cite below don't work.

(Unless they are enclosed in braces as the third and fourth \cite)

enter image description here

\documentclass{article}
\usepackage{xparse}
\usepackage[backend=biber, style=authortitle]{biblatex}
\usepackage{ifthen}
\usepackage{filecontents}

\DeclareFieldFormat{postnote}{#1}
\bibliography{mybib.bib}

\begin{filecontents}{mybib.bib}
@Book{mykey, author={Author}, title={Title}, journal={Journal}, year={1950}}
\end{filecontents}

\newcommand         \x [2][] {\ifthenelse{\equal{#1}{}}{}{(#1)}#2}
\NewDocumentCommand \y {mo}  {#1\IfValueT{#2}{(#2)}}

\begin{document}

\cite [\x{100}]      {mykey}

\cite [\y{100}]      {mykey}

\cite [{\x[a]{100}}] {mykey}

\cite [{\y{100}[a]}] {mykey}

\cite [\x[a]{100}]   {mykey}

\cite [\y{100}[a]]   {mykey}

\end{document}
share|improve this question
3  
Adding the braces is the right thing to do. {} matching is built in to the TeX parser (that is matching characters of catcode 1 and 2) LaTeX [] options are parsed with a delimited macro so they end at the first ] without counting nested []. So you need the {} to hide the inner square bracket. –  David Carlisle Jan 23 '13 at 23:31
    
@DavidCarlisle That's true for commands defined using the standard LaTeX method (which is what biblatex does), but not those using xparse, which does deal correctly with the nesting here. –  Joseph Wright Jan 24 '13 at 15:25
add comment

1 Answer

up vote 7 down vote accepted

The postnote formatting directive already acts on the contents of the postnote field. Its default definition can be found in biblatex.def:

\DeclareFieldFormat{postnote}{\mkpageprefix[pagination]{#1}}

Passing macros like \x{100} to the postnote argument prevents biblatex from recognizing page references. So you should modify the directive instead. The example below takes this approach. Postnotes can be specified in the form:

\cite[<prenote>][(<postnote prefix>)(<postnote suffix>)<postnote stem>]{<key>}

where the postnote prefix and suffix arguments are optional. When only one is given it is assumed to be a suffix. New directives are used to format each of the three postnote parts.

\documentclass{article}
\usepackage{biblatex}
\usepackage[colorlinks]{hyperref}

% just for demonstration
\ExecuteBibliographyOptions{parentracker=false}
\renewcommand*{\multicitedelim}{\addsemicolon\space}

\DeclareFieldFormat{postnote:stem}{%
  \addcolon\space\mkcomprange[{\mkpageprefix[pagination]}]{#1}}
\DeclareFieldFormat{postnote:prefix}{#1}
\DeclareFieldFormat{postnote:suffix}{\addcomma\space#1}
\DeclareFieldFormat{postnote}{\mkpostnote{#1}}

\makeatletter

\newrobustcmd*{\mkpostnote}[1]{\mkpostnote@i#1&}

\def\mkpostnote@i{%
  \@ifnextchar(%)
    {\mkpostnote@ii}
    {\mkpostnote@ii()}}

\def\mkpostnote@ii(#1){%
  \@ifnextchar(%)
    {\mkpostnote@iii(#1)}
    {\mkpostnote@iii()(#1)}}

\def\mkpostnote@iii(#1)(#2)#3&{%
  \ifblank{#1}{}{%
    \blx@getformat\cbx@postnote@prefix@fmt{ffd}{}{postnote:prefix}%
    \cbx@postnote@prefix@fmt{#1}}%
  \ifblank{#3}{}{%
    \blx@getformat\cbx@postnote@stem@fmt{ffd}{}{postnote:stem}%
    \cbx@postnote@stem@fmt{#3}}%
  \ifblank{#2}{}{%
    \blx@getformat\cbx@postnote@suffix@fmt{ffd}{}{postnote:suffix}%
    \cbx@postnote@suffix@fmt{#2}}}
\def\cbx@postnote@stem@fmt{}
\def\cbx@postnote@prefix@fmt{}
\def\cbx@postnote@suffix@fmt{}

\makeatother

\addbibresource{biblatex-examples.bib}
\begin{document}
\subsection*{Without postnote affixes}
\cite[See][]{companion}
\cite[See][10]{companion}
\cite[See][11--19]{companion}
\cite[See][11--19 and the last section]{companion}
\cites[10]{companion}[e.g.][]{ctan}[11--19]{markey}[10]{knuth:ct}
\cites(See)()[11--19]{companion}{ctan,markey,knuth:ct}
\subsection*{With postnote affixes}
\cite[See][(post)]{companion}
\cite[See][(post)10]{companion}
\cite[See][(pre)()11--19]{companion}
\cite[See][(pre)(post)11--19 and the last section]{companion}
\cites[10]{companion}[e.g.][()(post)]{ctan}[11--19]{markey}[(pre)()10]{knuth:ct}
\cites(See)()[(pre)(post)11--19]{companion}{ctan,markey,knuth:ct}
\printbibliography
\end{document}

enter image description here

share|improve this answer
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.