用户友好的数组定义宏

用户友好的数组定义宏

我正在开发一个自定义文档类,其中文档中可能有一个或多个作者。通常,只需指定\author{}并调用一些额外的宏来设置一些特殊值,例如\email{}(类代码中定义的命令)。

然后,在\maketitle类中定义的宏中,我只需执行

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

这很好,但现在我想通过让用户指定多个作者和多个电子邮件(当然,它们的数量应该相同)来扩展该类的功能。这是一个概念:

\documentclass{myclass}

\title{Glorious ducks}
\authors{{John Smith}{Jane Smith}{George Hastings}}
\emails{{[email protected]}{[email protected]}{[email protected]}}

然后,\maketitle将包含类似这样的内容(伪代码):

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

我不需要像例子中那样的语法,它只是为了展示概念。


我发现一个可能的解决方案是使用arrayjobx包。我可以在类中提供这样的宏:

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

然后用户可以做

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

并且\maketitle可以以某种方式迭代这个数组……但我没有找到arrayjobx获取数组长度的方法,这使得这个解决方案几乎毫无用处。作为用户,我不想指定数组及其长度。

您将如何解决这个问题?我并不坚持使用arrayjobx,如果可能的话,更“优雅”的 (La)TeX 解决方案是最受欢迎的。谢谢。

把它们加起来:

  • 用户可以指定\author\email获取具有单个作者的文档
  • \authors\emails获取在表格环境中列出的具有多个作者的文档

答案1

老实说,我不会使用这样的语法。我更喜欢类似的东西,\author{xxx \and xxx \and xxx}但添加电子邮件也并非易事。按照你想要的语法,电子邮件列表必须按照与作者列表相同的顺序给出,我觉得这太复杂了。

你可以研究不同的类,看看它们如何处理事情。这可能是一个起点:

\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{[email protected]}
\email{[email protected]}

\author{Someone Else}
\email{[email protected]}

\author{Yet Another}
\email{[email protected]}
\email{[email protected]}

\author{Last One}
\email{[email protected]}

\begin{document}

\maketitle

\end{document}

在此处输入图片描述


或者类似的东西,不需要创建新的,\if而是重新定义\@emailsep\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{[email protected]}
\email{[email protected]}

\author{Someone Else}
\email{[email protected]}

\author{Yet Another}
\email{[email protected]}
\email{[email protected]}

\author{Last One}
\email{[email protected]}

\begin{document}

\maketitle

\end{document}

在此处输入图片描述

答案2

将信息收集与排版分开:

\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{[email protected]}

\author{Jane Smith}
\email{[email protected]}

\author{George Hastings}
\email{[email protected]}

\printauthors

\end{document}

作者的姓名和电子邮件按顺序收集起来,然后用来制作tabular;但您可以用其他几种方式重复使用这些项目。

当然,这只是一个框架,有很多变化,并且可能容纳隶属关系,甚至多个电子邮件地址。

这是另一种可能性,即处理好从属关系。

\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{[email protected]}
\affiliation{University of Somewhere}

\author{Jane Smith}
\email{[email protected]}
\affiliation{University of Elsewhere}

\author{George Hastings}
\email{[email protected]}
\affiliation{University of Duckistan, Department of Duckology, and 
University of Another Place, Department of Long Names with No Meaning}

\printauthors

\end{document}

在此处输入图片描述

答案3

哦,这和 campa 刚刚发布的差不多一样 :-)

\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{[email protected]}
\email{[email protected]}
\author{Jane Smith}
\email{[email protected]}
\begin{document}

\maketitle

\section{Intro}
\vdots
\end{document}

相关内容