2

I want to allow using the \author command like this:

\author{John Doe <john.doe@example.com>, Someone Else <someone@example.com>}

And later parse the value to something like this:

\textsf{\textbf{John Doe}, \href{john.doe@example.com}{Email: john.doe@example.com}\\}
\textsf{\textbf{Someone Else}, \href{someone@example.com>}{Email: someone@example.com>}\\}

I already tried to do something like that using the xparse package:

\NewDocumentCommand{\printauthors}{ >{\SplitList{,}} m }{%
  \ProcessList{#1}{\printauthor}%
}

\NewDocumentCommand{\printauthor}{m}{ >{\SplitList{<}} m }{%
  \textsf{\textbf{#1}, \href{#2}{Email: #2}\\}
}

\printauthors{\theauthor}

Minimal document:

\documentclass{article}
\usepackage{titling}
\usepackage{xparse}

\title{mwe}
\author{John Doe <john.doe@example.com>, Someone Else <someone@example.com>}

\NewDocumentCommand{\printauthors}{ >{\SplitList{,}} m }{%
  \ProcessList{#1}{\printauthor}%
}

\NewDocumentCommand{\printauthor}{ >{\SplitList{<}} m }{%
  \textsf{\textbf{#1}, \href{#2}{Email: #2}\\}
}

\begin{document}
\thetitle

\printauthors{\theauthor}
\end{document}

But it doesn't seem to work like that. What am I doing wrong here? Is there a better way to do this?

  • What is \theauthors supposed to do? Which documentclass are you using? – user31729 Feb 11 '18 at 18:55
  • This is using the titling package (ctan.org/pkg/titling) and the article documentclass. – Johann Bauer Feb 11 '18 at 19:05
  • Please add the minimal document that has your issue. – user31729 Feb 11 '18 at 19:07
  • @Christian Done. – Johann Bauer Feb 11 '18 at 20:42
2

You can split at commas and then parse for the email; with regexes it's (almost) easy.

\documentclass{article}
\usepackage{titling}
\usepackage{xparse}
\usepackage{hyperref}

\ExplSyntaxOn
\NewDocumentCommand{\printauthors}{}
 {
  \seq_gset_from_clist:NV \g_bauer_authors_seq \theauthor
  \seq_clear:N \l__bauer_authors_out_seq
  \seq_map_inline:Nn \g_bauer_authors_seq
   {
    \bauer_authors_parseemail:n { ##1 }
   }
  \seq_use:Nn \l__bauer_authors_out_seq { \\ }
 }
\cs_generate_variant:Nn \seq_gset_from_clist:Nn { NV }
\seq_new:N \g_bauer_authors_seq
\seq_new:N \l__bauer_authors_out_seq
\cs_new_protected:Nn \bauer_authors_parseemail:n
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \regex_replace_once:nnN
   { ([^<]*) } % anything up to <
   { \c{bauer_authors_format_author:n}\cB\{\1\cE\} }
   \l_tmpa_tl
  \regex_replace_once:nnN
   { \<(.*)\> } % anything between < >
   { ,\ \c{bauer_authors_format_email:n}\cB\{\1\cE\} }
   \l_tmpa_tl
  \seq_put_right:NV \l__bauer_authors_out_seq \l_tmpa_tl
 }
\cs_new_protected:Nn \bauer_authors_format_author:n
 {
  \textsf { \textbf {\tl_trim_spaces:n { #1 } } }
 }
\cs_new_protected:Nn \bauer_authors_format_email:n
 {
  \href{mailto:#1}{Email:~\texttt{#1}}
 }
\ExplSyntaxOff

\title{mwe}

\author{
  John Doe <john.doe@example.com>,
  Someone Else <someone@example.com>,
  No Mail
}

\begin{document}

\begin{flushleft}
{\LARGE\thetitle\\}

\bigskip

\printauthors
\end{flushleft}

\end{document}

enter image description here

The idea is that each segment is transformed into

\bauer_authors_format_author:n { <name> }, \bauer_authors_format_email:n { <email> }

and then \printauthors will separate all segments with \\.

A different approach, with key-value arguments, that can be extended to accept other attributes.

\documentclass{article}
\usepackage{titling}
\usepackage{xparse}
\usepackage{hyperref}

\ExplSyntaxOn
\NewDocumentCommand{\authorlist}{m}
 {% a sequence of key-value items
  \keys_set:nn { bauer/authors } { #1 }
 }
\NewDocumentCommand{\printauthors}{}
 {
  \seq_map_function:NN \g_bauer_authors_seq \__bauer_authors_print:n
 }

\seq_new:N \g_bauer_authors_seq
\tl_new:N \l__bauer_authors_temp_tl

\keys_define:nn { bauer/authors }
 {
  author .code:n = \__bauer_authors_setup:n { #1 },
  email  .code:n = \__bauer_authors_email:n { #1 },
 }

\cs_new_protected:Nn \__bauer_authors_setup:n
 {
  \tl_gset:Nx \l__bauer_authors_temp_tl { \tl_to_str:n { #1 } }
  \seq_gput_right:NV \g_bauer_authors_seq \l__bauer_authors_temp_tl
  \prop_new:c { g_bauer_authors_ \l__bauer_authors_temp_tl _prop }
  \prop_gput:cnn
   { g_bauer_authors_ \l__bauer_authors_temp_tl _prop }
   { author }
   { #1 }
 }
\cs_new_protected:Nn \__bauer_authors_email:n
 {
  \prop_gput:cnn
   { g_bauer_authors_ \l__bauer_authors_temp_tl _prop }
   { email }
   { #1 }
 }

\cs_new_protected:Nn \__bauer_authors_print:n
 {
  \bauer_authors_format_author:n
   {
    \prop_item:cn { g_bauer_authors_#1_prop } { author }
   }
  \prop_if_in:cnT { g_bauer_authors_#1_prop } { email }
   {
    ,~ % separation
    \bauer_authors_format_email:n
     {
      \prop_item:cn { g_bauer_authors_#1_prop } { email }
     }
   }
  \\ % new line
 }
\cs_new_protected:Nn \bauer_authors_format_author:n
 {
  \textsf { \textbf {\tl_trim_spaces:n { #1 } } }
 }
\cs_new_protected:Nn \bauer_authors_format_email:n
 {
  \href{mailto:#1}{Email:~\texttt{#1}}
 }
\ExplSyntaxOff

\title{mwe}

\authorlist{
  author = John Doe,
  email  = john.doe@example.com,
  author = Someone Else,
  email  = someone@example.com,
  author = No Mail
}

\begin{document}

\begin{flushleft}
{\LARGE\thetitle\\}

\bigskip

\printauthors
\end{flushleft}

\end{document}

For each author a property list is allocated; a sequence works for indexing the authors.

|improve this answer|||||

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.