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}
{}
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.biblatex
does), but not those usingxparse
, which does deal correctly with the nesting here.