我正在开发一个自定义文档类,其中文档中可能有一个或多个作者。通常,只需指定\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{\\}\else\g@addto@macro\@author{}\@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}