0

I use natbib in author-year format, along with a custom .bst file. It formats bibliographies as I want. But in the text of my documents, I have many citations like \citet[12-30]{lamport94}. They produce the expected output: "Lamport (1994, 12-30)."

I want to change the formatting of the argument in brackets so that it displays with an en dash instead of a hyphen. That is, I want the output to be "Lamport (1994, 12–30)." But I don't want to modify all of my citations "by hand." Instead, I want to add a command or modify my .bst file so that I can automatically convert the hyphens to en dashes. How may I do this?

I already have, in my .bst file, a command that replaces hyphens with en dashes in a given string. But I can't see how to change my .bst file to modify the text that lies within the optional brackets of a \citet or \citep command. For example, I don't see how to use my .bst file to format the "xxx" in citet[xxx]{lamport94}, or how to use my .bst file to modify the page range in \citet[12-30]{lamport94}.

  • 1
    Future visitors may be interested to know that this 'page range normalisation' has been a feature in biblatex since version 3.11, see github.com/plk/biblatex/issues/293. – moewe Jul 23 at 6:15
2

It is possible to modify the citet command to perform a string substitution from - to -- in the optional command, using \StrSubstitute from the xstring package.

In natbib the citing commands are structured as a branching sequence of commands that are called. Some of those commands are short and can be redefined entirely without needing much code in your source file. In the MWE below I have selected \NAT@@citetp as a command to modify, which is the third command in the sequence (after \citet itself and \NAT@citetp). This command is only one line and it exposes the optional command, therefore the string substitution can be performed.

Code:

\documentclass[12pt]{article}
\usepackage[round]{natbib}
\usepackage{xstring}
\makeatletter
\def\NAT@@citetp[#1]{%
\StrSubstitute{#1}{-}{--}[\newdash]%
% original code: \@ifnextchar[{\@citex[#1]}{\@citex[][#1]}
\@ifnextchar[{\@citex[\newdash]}{\@citex[][\newdash]}}
\makeatother
\begin{document}

\noindent Changing\\
Lamport (1994, 12-30) into\\
\citet[12-30]{lamport94}

\begin{thebibliography}{1}
\providecommand{\natexlab}[1]{#1}
\providecommand{\url}[1]{\texttt{#1}}
\expandafter\ifx\csname urlstyle\endcsname\relax
  \providecommand{\doi}[1]{doi: #1}\else
  \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi

\bibitem[Lamport(1994)]{lamport94}
Leslie Lamport,
\emph{\LaTeX: A Document Preparation System}.
Addison Wesley, Massachusetts,
2nd Edition,
1994.
\end{thebibliography}
\end{document}

Result:

enter image description here

For postnotes it is possible to redefine the \NAT@cite command (using \renewcommand because this command does not have a \def version):

\documentclass[12pt]{article}
\usepackage[round]{natbib}
\usepackage{xstring}
\makeatletter
\def\NAT@@citetp[#1]{%
\StrSubstitute{#1}{-}{--}[\newdash]%
\@ifnextchar[{\@citex[\newdash]}{\@citex[][\newdash]}}
\renewcommand\NAT@cite[3]{%
\ifNAT@swa\NAT@@open\if*#2*\else #2\NAT@spacechar\fi
#1\if*#3*\else\NAT@cmt\StrSubstitute{#3}{-}{--}\fi\NAT@@close\else #1\fi\endgroup}
\makeatother
\begin{document}

\noindent Changing\\
Lamport (1994, 12-30) into\\
\citet[12-30]{lamport94}

\noindent postnote: \citep[see, e.g.,][12-30]{lamport94}

\begin{thebibliography}{1}
\providecommand{\natexlab}[1]{#1}
\providecommand{\url}[1]{\texttt{#1}}
\expandafter\ifx\csname urlstyle\endcsname\relax
  \providecommand{\doi}[1]{doi: #1}\else
  \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi

\bibitem[Lamport(1994)]{lamport94}
Leslie Lamport,
\emph{\LaTeX: A Document Preparation System}.
Addison Wesley, Massachusetts,
2nd Edition,
1994.
\end{thebibliography}
\end{document}

Result:

enter image description here

  • 1
    This solution works for \citet[12-30]{lamport94} but not for, say, \citep[see, e.g.,][12-30]{lamport94}. Can you think of a way to modify your code so that it operates on the second of two optional arguments of \citet and \citep? – Mico Jul 22 at 18:05
  • 1
    @Mico that can be done by redefining \NAT@cite, see edit. – Marijn Jul 22 at 21:52
  • +1. :-) Really neat solution! – Mico Jul 22 at 21:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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