在 MWE 中,当我尝试使用时,\{ ... \}
出现以下错误! TeX capacity exceeded, sorry [input stack size=5000]
。但是,如果我使用\ensuremath{\lbrace} ... \ensuremath{\rbrace}
它,它就可以工作。
所以我的问题是:为什么它在一种情况下有效,而在另一种情况下无效?
\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}
\newcommand{\AuthorA}{nameA surnameA}
\newcommand{\AuthorMailA}{[email protected]}
\newcommand{\AuthorB}{nameB surnameB}
\newcommand{\AuthorMailB}{[email protected]}
\newcommand{\AuthorC}{nameC surnameC}
\newcommand{\AuthorMailC}{[email protected]}
\newcounter{Idxi}
\newcommand{\sortauthors}{%
\setcounter{Idxi}{0}
\foreach \Idx in \PaperAuthorsList{%
\ifcsname Author\Idx \endcsname
\stepcounter{Idxi}
\expandafter\xdef\csname PaperAuthorMail\Alph{Idxi}\endcsname{\csname AuthorMail\Idx\endcsname}
\fi
}
\xdef\PaperAuthorsTotalNum{\theIdxi}
}
\newcommand{\textlbrace}{\ensuremath{\lbrace}}
\newcommand{\textrbrace}{\ensuremath{\rbrace}}
\newcommand{\printauthorsmail}{%
\def\temp{Emails:\space}%
\foreach \Idx in {1,...,\PaperAuthorsTotalNum}{%
\setcounter{Idxi}{\Idx}%
%
\ifnum\PaperAuthorsTotalNum=1%
\xdef\temp{Email:\space\csname PaperAuthorMail\Alph{Idxi}\endcsname}%
\fi%
%
\ifnum\PaperAuthorsTotalNum>1%
\StrBefore{\csname PaperAuthorMail\Alph{Idxi}\endcsname}{@}[\PaperAuthorMailPrefix]%
\StrBehind{\csname PaperAuthorMail\Alph{Idxi}\endcsname}{@}[\PaperAuthorMailSuffix]%
\ifnum\Idx=1%
\xdef\temp{\temp \{\PaperAuthorMailPrefix,\space}% <- \textlbrace instead of \{ works
\else%
\ifnum\Idx=\PaperAuthorsTotalNum%
\xdef\temp{\temp \PaperAuthorMailPrefix\}@\PaperAuthorMailSuffix}% <- \textrbrace instead of \} works
\else%
\xdef\temp{\temp \PaperAuthorMailPrefix,\space}%
\fi%
\fi%
\fi%
}%
\temp%
}
\begin{document}
\newcommand\PaperAuthorsList{A}
\sortauthors
\printauthorsmail
\renewcommand\PaperAuthorsList{A,B}
\sortauthors
\printauthorsmail
\end{document}
答案1
它之所以有效是\ensuremath{\lbrace}
因为当 TeX 执行\xdef
以下不是在数学模式下,因此您得到的本质上是$\delimiter "4266308$
,这在的上下文中是合法的\xdef
。
使用\protected@xdef
而不是\xdef
。
然而,你可以做得更好。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\Author}{mmm}
{% #1 = key, #2 = author's name, #3 = author's email
\prop_gput:Nnn \g_cacamailg_authors_prop
{ name #1 }{ #2 }
\prop_gput:Nnn \g_cacamailg_authors_prop
{ email #1 } { #3 }
}
\NewDocumentCommand{\printauthors}{m}
{% #1 = list of keys
\seq_clear:N \l__cacamailg_authors_temp_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__cacamailg_authors_temp_seq
{ \prop_item:Nn \g_cacamailg_authors_prop { name ##1 } }
}
\seq_use:Nnnn \l__cacamailg_authors_temp_seq
{ ~and~ } % between two
{ ,~ } % between more than two
{ ,~and~ }% between last two
}
\NewDocumentCommand{\printemails}{m}
{% #1 = list of keys (emails share domain)
\int_compare:nNnTF { \clist_count:n { #1 } } = { 1 }
{ \__cacamailg_authors_email_single:n { #1 } }
{ \__cacamailg_authors_email_compress:n { #1 } }
}
\prop_new:N \g_cacamailg_authors_prop
\tl_new:N \l__cacamailg_authors_email_domain_tl
\seq_new:N \l__cacamailg_authors_temp_seq
\seq_new:N \l__cacamailg_authors_email_names_seq
\cs_new_protected:Nn \__cacamailg_authors_email_single:n
{
\prop_item:Nn \g_cacamailg_authors_prop { email #1 }
}
\cs_new_protected:Nn \__cacamailg_authors_email_compress:n
{
\tl_clear:N \l__cacamailg_authors_email_domain_tl
\seq_clear:N \l__cacamailg_authors_email_names_seq
\clist_map_function:nN { #1 } \__cacamailg_authors_email_split:n
% print the addresses
\{ \seq_use:Nn \l__cacamailg_authors_email_names_seq { ,~ } \}
@\tl_use:N \l__cacamailg_authors_email_domain_tl
}
\cs_new_protected:Nn \__cacamailg_authors_email_split:n
{
\__cacamailg_authors_email_split_aux:x
{ \prop_item:Nn \g_cacamailg_authors_prop { email #1 } }
}
\cs_new_protected:Nn \__cacamailg_authors_email_split_aux:n
{
\__cacamailg_authors_email_split:w #1 \q_stop
}
\cs_generate_variant:Nn \__cacamailg_authors_email_split_aux:n { x }
\cs_new_protected:Npn \__cacamailg_authors_email_split:w #1 @ #2 \q_stop
{
\tl_if_empty:NT \l__cacamailg_authors_email_domain_tl
{
\tl_set:Nn \l__cacamailg_authors_email_domain_tl { #2 }
}
\seq_put_right:Nn \l__cacamailg_authors_email_names_seq { #1 }
}
\ExplSyntaxOff
\begin{document}
\Author{A}{nameA surnameA}{[email protected]}
\Author{B}{nameB surnameB}{[email protected]}
\Author{C}{nameC surnameC}{[email protected]}
\printauthors{A,B,C}
Emails: \printemails{A,C}, \printemails{B}
\end{document}
答案2
因为目标是打印结果,所以你不需要构造宏。只需一次打印一点即可。
\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}
\newcommand{\AuthorA}{nameA surnameA}
\newcommand{\AuthorMailA}{[email protected]}
\newcommand{\AuthorB}{nameB surnameB}
\newcommand{\AuthorMailB}{[email protected]}
\newcommand{\AuthorC}{nameC surnameC}
\newcommand{\AuthorMailC}{[email protected]}
\newcounter{Idxi}
\newcommand{\sortauthors}{%
\setcounter{Idxi}{0}
\foreach \Idx in \PaperAuthorsList{%
\ifcsname Author\Idx \endcsname
\stepcounter{Idxi}
\expandafter\xdef\csname PaperAuthorMail\Alph{Idxi}\endcsname{\csname AuthorMail\Idx\endcsname}
\fi
}
\xdef\PaperAuthorsTotalNum{\theIdxi}
}
\newcommand{\textlbrace}{\ensuremath{\lbrace}}
\newcommand{\textrbrace}{\ensuremath{\rbrace}}
\newcommand{\printauthorsmail}{%
Emails:\space%
\foreach \Idx in {1,...,\PaperAuthorsTotalNum}{%
\setcounter{Idxi}{\Idx}%
%
\ifnum\PaperAuthorsTotalNum=1%
\textit{\csname PaperAuthorMail\Alph{Idxi}\endcsname}%
\else
\StrBefore{\csname PaperAuthorMail\Alph{Idxi}\endcsname}{@}[\PaperAuthorMailPrefix]%
\StrBehind{\csname PaperAuthorMail\Alph{Idxi}\endcsname}{@}[\PaperAuthorMailSuffix]%
\ifnum\Idx=\PaperAuthorsTotalNum%
\textit{\PaperAuthorMailPrefix@\PaperAuthorMailSuffix}% <- \textrbrace instead of \} works
\else%
\textit{\PaperAuthorMailPrefix,\space}%
\fi%
\fi%
}
}
\begin{document}
\newcommand\PaperAuthorsList{A}
\sortauthors
\printauthorsmail
\renewcommand\PaperAuthorsList{A,B}
\sortauthors
\printauthorsmail
\end{document}