# Adding a list of bios to the book class

I am busy with a document where I need to add an Appendix with a list of names and short biographies (about a paragraph each).

I would be happier if I can do that as I describe the person in the relevant chapters save that to a macro and then add at the end. Similar to a Bibliography.

Is there a package that can do this or a way to build such macros?

-
Answers to this question might be of use. –  Seamus Apr 8 '11 at 15:57

I would take a slightly different approach than Seamus.

We first define a list to hold all the names. The list is to be delimited by commas:

\def\alist{}% {George, Martin, Seamus, Yiannis}


We then define helper macros to add a person to the list. At the same time we create a command on the fly to hold the Bio. For example typing \Mary will typeset the Bio for the person.

To print the Bios in the appendix we simply type,

\PrintBios


We also add a few helper functions to keep the list sorted, so that we can print them alphabetically. These are borrowed for the listings package (just a BubbleSort).

To loop through the list we use the @for from the LaTeX kernel.

Here is a minimal that includes all these. The Bios are just paragraphs from the lipsum package.

\documentclass[11pt]{book}
\usepackage{lstdoc,lipsum}
\begin{document}
\makeatletter
\def\alist{}

\let\sort\lst@BubbleSort
}

\long\expandafter\gdef\csname#1\endcsname{\textbf{#1}: #2}
\sort\alist
}

\def\PrintBios{%
\@for \i:=\alist\do{%
\csname\i\endcsname}
}
%example
% print the biographies
\PrintBios
\makeatother
\end{document}


I am not too sure how fast it will be for hundreds of Bios, but for about 100-200 the compiling time was imperceptible.

-
I'm late to the party, but I brought cake! :) Amazing answer, Yiannis! :) –  Paulo Cereda Mar 28 '13 at 1:12

Here's an example of using the newfile package to achieve this. It could obviously do with some tweaking. A lot of this is borrowed from answers to this question. Also thanks to Martin Scharrer for comments.

The idea is to write each author bio to a file and then read them all in at the end.

\documentclass{book}
\usepackage{newfile}
\usepackage{lipsum}
\newoutputstream{bios}
\openoutputfile{\jobname.bio}{bios}
\newcommand\styleauthor[1]{{\bfseries \begin{center}#1\end{center}}}
\newcommand\authorbio[2]{%
\unexpanded{%
\styleauthor{#1}%
\par
#2
\vspace{\baselineskip}}
}
}
\begin{document}
\chapter{Foo}
\authorbio{A. Author}{Here is a short bio on Albert Author

\lipsum[2]}

\chapter{Bar}

\authorbio{B. Buthor}{Here is a short bio on Brian Buthor

This allows newlines. Sweet.}

\appendix

\chapter{Author bios}
\closeoutputstream{bios}
\input{\jobname.bio}
\end{document}

-
This only works for single paragraphs... –  Seamus Apr 8 '11 at 16:14
@Seamus no it doesn't. You fixed it, remember? –  Seamus Apr 8 '11 at 16:25
@Seamus: Why shouldn't it work with more than one paragraph? It works fine in my tests. The only trouble I see if \par is redefined in a fragile way. Which can be fixed using: \newcommand\authorbio[2]{{\let\par\relax\addtostream{bios}{\noexpand\item[#1] #2}}} –  Martin Scharrer Apr 8 '11 at 16:27
@Martin Scharrer I hadn't actually thought it through. I was covering my back. It think the way the updated solution works should be even more robust and more easily customisable... –  Seamus Apr 8 '11 at 16:29
@Seamus: Also i would recommend using \protect instead of \noexpand. It's much saver in writes. Here it might be ok, but e.g. \addtocontents writes the stuff first into the .aux file and then into the target file like .toc. Therefore you need more than one \noexpand. The \protect is then \noexpand\protect\noexpand :-) –  Martin Scharrer Apr 8 '11 at 16:34

Just for fun, here's Yiannis' answer reimplemented in LaTeX3. The idea is exactly the same: the \AddBio command saves the author name and bio to macros, and uses the sort argument to name them. The sort is also what the authors are sorted by.

This makes use of egreg's solution to how to sort strings in an l3 way. (the code has the answer linked in a comment).

\documentclass{article}
\usepackage{xparse,expl3,kantlipsum,l3sort}

\ExplSyntaxOn
\seq_new:N \l_authorlist_seq

% Sort, Author Name, Bio
\tl_new:c {l_#1_name_tl}
\tl_gset:cn {l_#1_name_tl} {#2}
\tl_new:c {l_#1_bio_tl}
\tl_gset:cn {l_#1_bio_tl} {#3}
\seq_gput_right:Nn \l_authorlist_seq {#1}
}

\prg_new_conditional:Npnn \string_compare:nnn #1 #2 #3 {TF}
{
\if_int_compare:w \pdftex_strcmp:D {#1}{#3} #2 \c_zero
\prg_return_true:
\else:
\prg_return_false:
\fi
}

\NewDocumentCommand{\sortauthors}{ }{
\seq_sort:Nn \l_authorlist_seq {
\string_compare:nnnTF {##1} {>} {##2} {\sort_reversed:} {\sort_ordered:}
}
}

\NewDocumentCommand{\PrintBio}{m}{
\textbf{\tl_use:c {l_#1_name_tl}:~} \tl_use:c{l_#1_bio_tl}\par
}

\NewDocumentCommand{\PrintBios}{}{
\sortauthors
\seq_map_inline:Nn \l_authorlist_seq {\PrintBio{##1}}
}
\ExplSyntaxOff
\begin{document}


I should have actually used l3prop rather than rely on token lists. I did it properly here about line 93. –  Seamus May 18 '13 at 12:18