[Tex/LaTex] Automatically indexing references by author and year

biberbiblatexcitingindexing

I'm writing a literature review, and would like to add indices for both authors and publication year (i.e., two separate indices). Now, I could manually enter the appropriate \index{} commands, but it seems like this is something that could be automatically handled by biblatex. It would certainly make maintenance a lot easier, an important consideration since I intend to keep the review up-to-date over the next couple of years as I progress through my research.

I have been playing with the indexing option that is built into biblatex but cannot see how to make it work with multiple indices (or even index by year alone for that matter). Similarly, I have been looking at questions such as this one on writing custom \cite commands, but am struggling to see how they work as well.

A manually indexed minimal working example (using biblatex and multind) which shows the sort of final result I'm after:

\documentclass{report}

\usepackage{filecontents}
\begin{filecontents*}{testing.bib}
@article{Author2010,
    author="Author, A and Writer, B",
    journal="Slackers Monthly",
    title="An overly long treatise on procrastination",
    year=2010,
    month=jun,
}
@article{Writer2011,
    author="Writer, B and Scribe, C",
    journal="Fake Online Journal",
    title="Waste of time or time of waste: procrastination in a modern society",
    year=2011,
    month=oct,
}
@book{Writer2003,
    author="Writer, B",
    title="Procrastination for dummies",
    year=2003,
    publisher="Procrastination House",
    address="Auckland",
}
\end{filecontents*}

\usepackage[style=authoryear]{biblatex}
\addbibresource{testing}

\usepackage{multind}
\makeindex{authors}
\makeindex{years}

\begin{document}

\chapter{Introductory works}

\section{An overly long treatise on procrastination}

\fullcite{Author2010}
\index{authors}{Author, A!An overly long treatise on procrastination (2010)}
\index{authors}{Writer, B!An overly long treatise on procrastination (2010)}
\index{years}{2010!An overly long treatise on procrastination}

This paper was really useful in telling me how to waste more time rather 
than doing real work.

\section{Waste of time or time of waste: procrastination in a modern society}

\fullcite{Writer2011}
\index{authors}{Writer, B!Waste of time or time of waste: procrastination in a modern society (2011)}
\index{authors}{Scribe, C!Waste of time or time of waste: procrastination in a modern society (2011)}
\index{years}{2011!Waste of time or time of waste: procrastination in a modern society}

Applies post-modern philosophical theory to procrastination.

\section{Procrastination for dummies}

\fullcite{Writer2003}
\index{authors}{Writer, B!Procrastination for dummies (2003)}
\index{years}{2003!Procrastination for dummies}

A classic reference book for anybody starting a research position.

\printbibliography
\printindex{authors}{Author index}
\printindex{years}{Year index}

\end{document}

And a Makefile to compile it:

default:
    xelatex mwe
    bibtex mwe
    xelatex mwe
    xindy -M texindy -M page-ranges -L english -C utf8 authors.idx
    xindy -M texindy -M page-ranges -L english -C utf8 years.idx
    xelatex mwe

So is this possible to achieve with a custom cite command (or a built-in one for that matter)? Or would I be better off writing a script to parse the BibTeX/biber output to generate the input to xindy?

Best Answer

This answer has been updated in the light, particularly, of Audrey's perceptive comments.

Yes. There are a number of ways to do this.

The code below is a revision of my original suggestion, which (I hope) corrects various deficiencies in its general use. Specifically:

  • My original code didn't deal gracefully with empty years: this does.

  • My original code "hardwired" multind's syntax and your chosen index names: in this version the index names are in macros which means they can be changed.

  • My original code didn't make use of the indexsorttitle and indextitle fields: this does, as it should.

  • My original code could cause problems with certain macros (e.g. \TeX used in indextitles, as Audrey properly pointed out. This handles those properly, I hope.

On the example you gave, none of this changes anything -- but I've added two further example entries which the original version would have handled wrongly or stupidly, and this handles directly.

Oddly, \fullcite doesn't seem to call the indexing macros, which is why I've used \cite; I daresay there's an explanation for that, but I don't have time to dig into it.

\documentclass{report}

\usepackage{filecontents}
\begin{filecontents*}{testing.bib}
@article{Author2010,
    author="Author, A and Writer, B",
    journal="Slackers Monthly",
    title="An overly long treatise on procrastination",
    year=2010,
    month=jun,
}
@article{Writer2011,
    author="Writer, B and Scribe, C",
    journal="Fake Online Journal",
    title="Waste of time or time of waste: procrastination in a modern society",
    year=2011,
    month=oct,
}
@book{Writer2003,
    author="Writer, B",
    title="Procrastination for dummies",
    year=2003,
    publisher="Procrastination House",
    address="Auckland",
}
@book{knuth:ct:b,
  hyphenation = {american},
  sortyear = {1986-1},
  sorttitle = {Computers & Typesetting B},
  indexsorttitle = {TeX: The Program},
  author = {Knuth, Donald E.},
  title = {\TeX: The Program},
  shorttitle = {\TeX},
  maintitle = {Computers \& Typesetting},
  volume = {B},
  publisher = {Addison-Wesley},
  location = {Reading, Mass.},
  date = {1986},
  annotation = {The second volume of a five-volume book. Note the
    \texttt{sorttitle} and \texttt{sortyear} fields. Also note the
    \texttt{indexsorttitle} field}
}
@book{yearless,
  author = {Lazy B. Ugger},
  title  = {I Can't Be Bothered with Years},
  publisher = {Equally Lazee},
}
\end{filecontents*}

\usepackage[style=authoryear,indexing=cite]{biblatex}
\addbibresource{testing.bib}
\makeatletter
% For the "years" index, we redefine the ordinary bibmacro
% which indexes titles, so that it indexes into the years
% index instead
\renewbibmacro*{index:title}[2]{%
  \iffieldundef{year}
     {\usebibmacro{index:years}%
      {\index}%
      {\undated}%
      {\thefield{indexsorttitle}}%
      {\thefield{entrykey}}}
    {\usebibmacro{index:years}%
      {\index}%
      {\thefield{year}}%
      {\thefield{indexsorttitle}}%
      {\thefield{entrykey}}}}

\newbibmacro*{index:years}[4]{%
    \begingroup
     \protected@edef\theindexentry{%
      \unexpanded{#1}\yearsindex{#2!#3\actualoperator\unexpanded{\citefield}{#4}{indextitle}}}%
     \theindexentry
     \endgroup}

% For authors we just redefine the field format (so that it
% includes title and year information
\DeclareIndexNameFormat{default}{%
  \iffieldundef{year}
    {\usebibmacro{index:name}%
      {\index}%
      {#1}%
      {#3}%
      {#5}%
      {#7}%
      {\thefield{indexsorttitle}}%
      {\thefield{entrykey}}%
      {}}
   {\usebibmacro{index:name}%
      {\index}%
      {#1}%
      {#3}%
      {#5}%
      {#7}%
      {\thefield{indexsorttitle}}%
      {\thefield{entrykey}}%
      { (\thefield{year})}}}
% ... and modify the relevant bibmacro to add the extra information
\renewbibmacro*{index:name}[8]{%
  \begingroup
  \ifuseprefix
    {\protected@edef\theindexentry{%
       \unexpanded{#1}\authorsindex{%
         \ifblank{#4}{}{#4 }%
         \@firstofone #2% remove spurious braces
         \ifblank{#5}{}{ #5}%
         \ifblank{#3}{}{, #3}%
         \actualoperator
         \ifblank{#4}{}{\MakeCapital{#4} }%
         #2%
         \ifblank{#5}{}{ #5}%
         \ifblank{#3}{}{, #3}!#6
            \actualoperator\unexpanded{\citefield}{indextitle}#8}}}%
    {\protected@edef\theindexentry{%
       \unexpanded{#1}\authorsindex{%
         \@firstofone #2% remove spurious braces
         \ifblank{#5}{}{ #5}%
         \ifblank{#3#4}{}{,}%
         \ifblank{#3}{}{ #3}%
         \ifblank{#4}{}{ #4}!#6\actualoperator
            \unexpanded{\citefield}{#7}{indextitle}#8}}}%
  \theindexentry
  \endgroup}
\makeatother
% redefine this if the index for years is differently named, or if using
% index or imakeidx
\newcommand{\yearsindex}{{years}}

% redefine this if the index for authors is differently named, or if
% using index or imakeidx
\newcommand{\authorsindex}{{authors}}

% undated entries
\newcommand{\undated}{n.d.}

\usepackage{multind}
\makeindex{authors}
\makeindex{years}

\begin{document}

\chapter{Introductory works}

\section{An overly long treatise on procrastination}

\fullcite{Author2010}

This paper was really useful in telling me how to waste more time rather 
than doing real work.

\section{Waste of time or time of waste: procrastination in a modern society}

\cite{Writer2011}

Applies post-modern philosophical theory to procrastination.

\section{Procrastination for dummies}

\cite{Writer2003}

A classic reference book for anybody starting a research position.

\section{The Awkward Squad}

\cite{knuth:ct:b}

An author who uses a title that indexing programs find hard to cope
with, but certainly no procrastinator.

\cite{yearless}

An author so lazy that he cannot be bothered to put a year of publication.


\printbibliography
\printindex{authors}{Author index}
\printindex{years}{Year index}

\end{document}

(If you need to, you can coax biblatex to do very complex indexing: I've just completed the first version of a style which can produce many, many, indexes (more than 33!), and which indexes based not just on title fields, but uses postnotes to set sub-items. It's not thrilling to set up, but it's absolutely do-able as biblatex stands.)

Related Question