8

I am working on a custom documentclass where there may be one or multiple authors in a document. Normally, one would simply specify \author{} and call some additional macros to set some special values, for example \email{} (a command defined in the class code).

Then, in the \maketitle macro defined in the class, I just do

{\Large\@author \texttt{<\@email>}}

This works well, but now I would like to extend the class’s functionality by letting users specify multiple authors and multiple emails (of course, their number should be the same). Here is a concept:

\documentclass{myclass}

\title{Glorious ducks}
\authors{{John Smith}{Jane Smith}{George Hastings}}
\emails{{john.smith@domain.tld}{jane.smith@domain.tld}{george.hastings@something.net}}

Then, \maketitle would contain something like this (pseudocode):

\begin{tabular}{ll}
\for \i in \len\@authors {
    \@authors{i} & \@emails{i} \\
}

I do not need the syntax to be like in the example, it was just to show the concept.


One possible solution I found was using the arrayjobx package. I can supply a macro such as this in the class:

\newcommand\authors[1]{\newarray\@Authors\readarray{@Authors}{#1}}

then the user can do

\authors{John Smith & Jane Smith & George Hastings}

and \maketitle could somehow iterate over this array… but I don’t see a way in arrayjobx to get the length of the array, which renders this solution pretty much useless. I do not want to specify an array as well as it’s length as a user.

How would you solve this problem? I do not insist on using arrayjobx, a more ‘elegant’ (La)TeX solution is most welcome, if possible. Thank you.

To sum it up:

  • users may either specify \author and \email to get a document with a single author
  • or \authors and \emails to get a document with multiple authors that are listed in a tabular environment
4
  • 3
    why separate \authors command rather than just allow more than one \author ? also I think it is easier for the author if you specify each email with each auther rather than two separate lists which need to match up. Mar 30 at 7:41
  • @DavidCarlisle good point, I thought about using \author multiple times. Your argument about including the emails with the author names is also valid, but do you mean simply like \author{John Smith <john.smith@domain.tld>}? I would like the email addresses in monospace, so this way an author would have to add that formatting themselves: \author{John Smith \texttt<john.smith@domain.tld>}
    – bp99
    Mar 30 at 7:49
  • 1
    no I just meant specify it with the author either \auther then \email as I just posted or as an optional argument \author[email]{name} Note you almost never need an indexed array syntax or an explicit loop in these things you just build up a list and execute it. Mar 30 at 7:58
  • Ah, how silly of me. Fair enough, that syntax is much better!
    – bp99
    Mar 30 at 13:30
4

Honestly I wouldn't use such a syntax. I would prefer something like \author{xxx \and xxx \and xxx} but adding also emails would be non trivial. With your desired syntax the email list must be given in the same order as the author's list, which I find too complicated.

You can look into different classes to see how they handle things. This could be a starting point:

\documentclass{article}

\makeatletter

\newif\if@email
\@emailfalse
\def\@author{}
\def\@@author{\gdef\@@author{\\[1ex]}}
\def\author#1{\@emailfalse\g@addto@macro\@author{\@@author#1}}
\def\email#1{\if@email\g@addto@macro\@author{\\&#1}\else\g@addto@macro\@author{&#1}\@emailtrue\fi}

\def\maketitle{\begin{tabular}{ll}\@author\end{tabular}}

\makeatother

\author{Me Myself}
\email{me@myself.com}
\email{me.again@myself.com}

\author{Someone Else}
\email{someone@elses.mail}

\author{Yet Another}
\email{yet.another@service1.com}
\email{y.another@service2.com}

\author{Last One}
\email{last@one.mail}

\begin{document}

\maketitle

\end{document}

enter image description here


Or something similar without creating a new \if but redefining an \@emailsep at every call of \author

\begin{filecontents*}{myclass.cls}
\LoadClass{article}
\def\@author{}
\def\@authorsep{\gdef\@authorsep{\\[1ex]}}

\def\author#1{%
   \g@addto@macro\@author{%
      \@authorsep#1%
      \gdef\@emailsep{&\gdef\@emailsep{\\&}}%
   }%
}
\def\email#1{\g@addto@macro\@author{\@emailsep\texttt{#1}}}

\def\maketitle{%
   \begin{center}
   \large\bfseries\@title
   \end{center}
   \noindent
   \begin{tabular}{@{}ll}
   \@author
   \end{tabular}%
}
\end{filecontents*}


\documentclass{myclass}

\title{Great Work}

\author{Me Myself}
\email{me@myself.com}
\email{me.again@myself.com}

\author{Someone Else}
\email{someone@elses.mail}

\author{Yet Another}
\email{yet.another@service1.com}
\email{y.another@service2.com}

\author{Last One}
\email{last@one.mail}

\begin{document}

\maketitle

\end{document}

enter image description here

2
  • This looks fantastic, thank you! I agree that this syntax is a lot cleaner. I just thought it would be very hard to handle multiple \authors. I will see if I can decipher what this code does :-)
    – bp99
    Mar 30 at 7:55
  • +1 you just beat me to it, I nearly didn't post mine once I saw this but as i'd done it and the OP might like a couple of examples, I left it :-) Mar 30 at 8:02
4

Separate gathering information from typesetting:

\documentclass{article}

\ExplSyntaxOn

\seq_new:N \g_bpclass_author_seq
\seq_new:N \g_bpclass_email_seq

\RenewDocumentCommand{\author}{m}
 {
  \seq_gput_right:Nn \g_bpclass_author_seq { #1 }
 }
\NewDocumentCommand{\email}{m}
 {
  \seq_gput_right:Nn \g_bpclass_email_seq { #1 }
 }

\NewDocumentCommand{\printauthors}{}
 {
  \par\noindent
  \begin{tabular}{@{} l l @{}}
  \seq_mapthread_function:NNN
    \g_bpclass_author_seq
    \g_bpclass_email_seq
    \bpclass_print_author:nn
  \end{tabular}
 }

\cs_new_protected:Nn \bpclass_print_author:nn
 {
  #1 % author name 
  &
  \ttfamily #2 % email
  \\[2ex]
 }

\ExplSyntaxOff

\begin{document}

\author{John Smith}
\email{john.smith@domain.tld}

\author{Jane Smith}
\email{jane.smith@domain.tld}

\author{George Hastings}
\email{george.hastings@something.net}

\printauthors

\end{document}

The authors' names and emails are gathered in sequences and then used to make a tabular; but you can reuse the items in several other ways.

Of course this is only a skeleton, there are so many variations and there's possibly to accommodate affiliations and maybe multiple email addresses.

Here's another possibility, taking care of the affiliation.

\documentclass{article}

\ExplSyntaxOn

\seq_new:N \g_bpclass_author_seq
\seq_new:N \g_bpclass_affiliation_seq
\seq_new:N \g_bpclass_email_seq

\RenewDocumentCommand{\author}{m}
 {
  \seq_gput_right:Nn \g_bpclass_author_seq { #1 }
 }
\NewDocumentCommand{\affiliation}{m}
 {
  \seq_gput_right:Nn \g_bpclass_affiliation_seq { #1 }
 }
\NewDocumentCommand{\email}{m}
 {
  \seq_gput_right:Nn \g_bpclass_email_seq { #1 }
 }

\NewDocumentCommand{\printauthors}{}
 {
  \noindent
  \begin{minipage}{\textwidth}
  \seq_map_indexed_function:NN \g_bpclass_author_seq \bpclass_print_author:nn
  \end{minipage}
 }

\cs_new_protected:Nn \bpclass_print_author:nn
 {
  \raggedright
  #2 % author name 
  \\[0.5ex]
  {
   \small\itshape
   \seq_item:Nn \g_bpclass_affiliation_seq { #1 } % affiliation
   \\
  }
  {
   \ttfamily\small
   \seq_item:Nn \g_bpclass_email_seq { #1 } % email
   \\
  }
  \bigskip
 }

\ExplSyntaxOff

\begin{document}

\author{John Smith}
\email{john.smith@domain.tld}
\affiliation{University of Somewhere}

\author{Jane Smith}
\email{jane.smith@domain.tld}
\affiliation{University of Elsewhere}

\author{George Hastings}
\email{george.hastings@something.net}
\affiliation{University of Duckistan, Department of Duckology, and 
University of Another Place, Department of Long Names with No Meaning}

\printauthors

\end{document}

enter image description here

4
  • Thanks for the LaTeX3 solution :-) I always find such code with these new macros incredibly difficult to read, but of course that’s largely due to my inexperience.
    – bp99
    Mar 30 at 13:33
  • I have two more questions about this: (A) I actually have three pieces of information for each author, I just wanted to simplify the example. But with \seq_mapthread_function I can only map two sequences. Is there an elegant way to do map/thread several seqs? (B) If I were to use this expl3 code in my class would I be recommended to replace all ‘classic’ macros (such as \newcommand) with expl3 ones?
    – bp99
    Mar 30 at 14:10
  • @bp99 I feared that: the institution is obviously a necessary identification item. As I said, this is a skeleton, but without enough information on the intended usage, that's as much as I can do. You can map as many sequences as you want by taking one for indexing; check for \seq_map_indexed_function:NN
    – egreg
    Mar 30 at 14:16
  • Thank you for your update. It’s hard to decide between the ‘new’ expl3 based solution and the classic approach provided by others :-) By the way—not that it matters—, the third field I needed was a student ID, not affiliation. Mr. Hastings’s line made me chuckle though, thanks for that!
    – bp99
    Mar 30 at 18:11
3

Oh this is more or less the same as campa just posted:-)

\documentclass{article}

\makeatletter
\def\@author{\@gobble}
\def\author#1{\g@addto@macro\@author{\\#1&}}
\def\email#1{\g@addto@macro\@author{ \texttt{<#1>}}}
\def\maketitle{{%
\par
\Large\noindent\textbf{\@title}\par
\smallskip
\large
\noindent\begin{tabular}{@{}ll@{}}% allow  more than one email
\@author{}%
\end{tabular}
\par
\bigskip}}
\makeatother

\title{Example}
\author{John Smith}
\email{js@example.com}
\email{j.smith999@example.org}
\author{Jane Smith}
\email{jane@example.com}
\begin{document}

\maketitle

\section{Intro}
\vdots
\end{document}
2
  • Oooh, the \def\@author{\@gobble} trick is also interesting.
    – campa
    Mar 30 at 8:00
  • @campa but you reminded me to put a {} guard in so it doesn't gobble the \end of \end{tabular} in the no-author case... Mar 30 at 8:11

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.