\{ 和 \} 不能与 \xdef 一起使用

\{ 和 \} 不能与 \xdef 一起使用

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

相关内容