Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

My google-fu has finally failed me... I'm trying to write a package that will allow you say \addauthor{name, email} several times and have the title page properly formatted. Here is a minimal example of my troubles:

% FILE: sd.sty
\ProvidesPackage{sd}
\newcounter{authors}
\newcommand{\@authors}{\@empty}
\newcommand{\@authorsnoemail}{\@empty}
\def\addauthor#1{\@addauthor#1\@nil}
\def\@addauthor#1,#2\@nil{%
  \expandafter\def\expandafter\@authorsnoemail\expandafter{%
    \@authorsnoemail%
    \ifnum\value{authors}>0, \fi%
    #1}
  \expandafter\def\expandafter\@authors\expandafter{\@authors%
    \ifnum\value{authors}=0 \else ; \fi%
    #1 - #2}
  \stepcounter{authors}}
\newcommand{\ane}{\@authorsnoemail}
\newcommand{\auth}{\@authors}

and then I try

% FILE: main.tex
\documentclass{article}
\usepackage{sd}

\addauthor{1, 1@1}
\addauthor{2, 2@2}
\addauthor{3, 3@3}

\begin{document}
\begin{tabular}{ll}
Expected: & 1, 2, 3 \\
Got: &  \ane\\
Expected: & 1 - 1@1; 2 - 2@2; 3 - 3@3 \\
Got: & \auth \\
\end{tabular}
\end{document}

And the output is

Expected: 1, 2, 3
Got:      , 1, 2, 3
Expected: 1 - 1@1; 2 - 2@2; 3 - 3@3
Got:      ; 1 - 1@1; 2 - 2@2; 3 - 3@3

My question is "How can I do the counter comparison properly, so that the divider will only be inserted at the second author and above?"

(I included both lists since for some reason removing one makes it work... I suspect I'm doing something wrong with the \expandafters)

share|improve this question

3 Answers 3

up vote 10 down vote accepted

enter image description here

It's probably easier just to deal with the initial case first. I also added an extra #3 to lose any white space after the comma.

% FILE: sd.sty
\ProvidesPackage{sd}
\newcounter{authors}
\let\@authors\@empty
\let\@authorsnoemail\@empty
\def\addauthor#1{\@addauthor#1\@empty\@nil}
\def\@addauthor#1,#2#3\@nil{%
  \ifx\@authors\@empty
     \def\@authorsnoemail{#1}%
     \def\@authors{#1 - #2#3}%
  \else
  \expandafter\def\expandafter\@authorsnoemail\expandafter{%
    \@authorsnoemail, #1}%
  \expandafter\def\expandafter\@authors\expandafter{%
    \@authors; #1 - #2#3}%
   \fi
  \stepcounter{authors}}
\newcommand{\ane}{\@authorsnoemail}
\newcommand{\auth}{\@authors}
share|improve this answer
    
Perfect -- thanks! @egreg 's answer below explains why this works (problem was with the expansion of \ifnum). I still haven't gotten around to LaTeX3, so I like this solution. I'm also getting rid of the counter, since it served no other purpose. –  Felipe Dec 15 '12 at 6:24

You're not expanding the conditional, which is put inside \@authors as is: if you do \makeatletter\show\@authors\makeatother after the \addauthor lines, you get

> \@authors=macro:
->\@empty \ifnum \value {authors}=0 \else ; \fi 1 -  1@1\ifnum \value {authors}
=0 \else ; \fi 2 -  2@2\ifnum \value {authors}=0 \else ; \fi 3 -  3@3.

which is obviously not what you want.

Here's a way out; just to be more modern than David, I present it in LaTeX3 form:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\addauthor}{ >{ \SplitArgument { 1 } { , } } m }
 {
  \sd_addauthor:nn #1
 }

\NewDocumentCommand{\betteraddauthor}{ m m }
 {
  \sd_addauthor:nn { #1 } { #2 }
 }

\NewDocumentCommand{\ane}{ }
 {
  \seq_use:Nnnn \g_sd_authors_noemail_seq { ,~ } { ,~ } { ,~ }
 }
\NewDocumentCommand{\auth}{ }
 {
  \seq_use:Nnnn \g_sd_authors_seq { ;~ } { ;~ } { ;~ }
 }

\cs_new_protected:Npn \sd_addauthor:nn #1 #2
 {
  \seq_gput_right:Nn \g_sd_authors_seq { #1 ~ - ~ #2 }
  \seq_gput_right:Nn \g_sd_authors_noemail_seq { #1 }
 }
\seq_new:N \g_sd_authors_seq
\seq_new:N \g_sd_authors_noemail_seq

\ExplSyntaxOff


\addauthor{1, 1@1}
\addauthor{2, 2@2}
\betteraddauthor{3}{3@3}

\begin{document}
\begin{tabular}{ll}
Expected: & 1, 2, 3 \\
Got: &  \ane\\
Expected: & 1 - 1@1; 2 - 2@2; 3 - 3@3 \\
Got: & \auth \\
\end{tabular}
\end{document}

Here's the output:

enter image description here

I don't think that the syntax

\addauthor{A. Name, a.name@x.y.z}

is so good and I'd prefer

\addauthor{A. Name}{a.name@x.y.z}

so I've provided the definition of \betteraddauthor for the second syntax. Notice that the "internal" macro used is just the same.

share|improve this answer

The following just uses fewer characters and uses the inserted space without zapping it. This only works because of your suggested output, which requires the space.

enter image description here

\documentclass{article}
\makeatletter
\newcounter{authors}
\newcommand{\@authors}{}
\newcommand{\@authorsnoemail}{}
\def\addauthor#1{\@addauthor#1\@nil}
\def\@addauthor#1,#2\@nil{%
  \protected@edef\@authorsnoemail{\@authorsnoemail%
    \ifnum\value{authors}>0, \fi%
    #1}%
  \protected@edef\@authors{\@authors%
    \ifnum\value{authors}>0; \fi%
    #1 -#2}%
  \stepcounter{authors}}
\newcommand{\ane}{\@authorsnoemail}
\newcommand{\auth}{\@authors}
\makeatother
\addauthor{1, 1@1}
\addauthor{2, 2@2}
\addauthor{3, 3@3}

\begin{document}
\begin{tabular}{ll}
Expected: & 1, 2, 3 \\
Got: &  \ane\\
Expected: & 1 - 1@1; 2 - 2@2; 3 - 3@3 \\
Got: & \auth \\
\end{tabular}
\end{document}
share|improve this answer
    
\xdef will cause troubles if an input like \addauthor{\textbf{1}, 1@1} is given (I don't know if it is to be expected, though) –  cgnieder Dec 14 '12 at 23:44
    
@cgnieder: True. –  Werner Dec 14 '12 at 23:54
    
Use \protected@edef, not \xdef: if an author's name has accents you'll be in big troubles. Also, but it is in the original code, why \@authors and \@authorsnoemail are not initialized as empty? The set with the empty set as element is not empty. ;-) –  egreg Dec 14 '12 at 23:59
    
@egreg: Agreed. I thought it may have been, originally, to test in an \ifx. I've removed it. –  Werner Dec 15 '12 at 0:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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