Como analisar um formato \author personalizado usando xparse?

Como analisar um formato \author personalizado usando xparse?

Quero permitir o uso do comando \author assim:

\author{John Doe <[email protected]>, Someone Else <[email protected]>}

E depois analise o valor para algo assim:

\textsf{\textbf{John Doe}, \href{[email protected]}{Email: [email protected]}\\}
\textsf{\textbf{Someone Else}, \href{[email protected]>}{Email: [email protected]>}\\}

Já tentei fazer algo assim usando o xparsepacote:

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

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

\printauthors{\theauthor}

Documento mínimo:

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

\title{mwe}
\author{John Doe <[email protected]>, Someone Else <[email protected]>}

\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}

Mas não parece funcionar assim. O que estou fazendo de errado aqui? Existe uma maneira melhor de fazer isso?

Responder1

Você pode dividir entre vírgulas e depois analisar o e-mail; com regexes é (quase) fácil.

\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 <[email protected]>,
  Someone Else <[email protected]>,
  No Mail
}

\begin{document}

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

\bigskip

\printauthors
\end{flushleft}

\end{document}

insira a descrição da imagem aqui

A ideia é que cada segmento seja transformado em

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

e então \printauthorsseparará todos os segmentos com \\.

Uma abordagem diferente, com argumentos de valor-chave, que pode ser estendida para aceitar outros atributos.

\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  = [email protected],
  author = Someone Else,
  email  = [email protected],
  author = No Mail
}

\begin{document}

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

\bigskip

\printauthors
\end{flushleft}

\end{document}

Para cada autor é alocada uma lista de propriedades; uma sequência serve para indexar os autores.

informação relacionada