为什么在下面的代码中找不到 \endcsname

为什么在下面的代码中找不到 \endcsname

这是我真正问题的前兆。但无论出于什么原因,当我尝试减少代码以在此处发布某些内容时,我遇到了更多错误。特别是,以下代码在\endcsname循环中给出了错误\foreach。虽然循环没有做任何我想要的事情,但在我的原始代码中它实际上已经编译。现在在这个代码片段中我收到一条关于缺少的错误消息\endcsname。有人能指出我明显忽略了什么吗?

\documentclass{article}

\usepackage{pgffor}
\usepackage{etoolbox}

\makeatletter

\def\ae@set@main#1:#2\@nil{%%
  \expandafter\def\csname ae@slogan@#1/main\endcsname{#2}}
\def\slogan{\@ifstar{\set@slogan}{\get@slogan}}

\def\set@slogan#1#2{\ae@set@#1.0.0.0:#2\@nil}
\def\ae@set@#1.#2.#3.#4:#5\@nil{%%
  \expandafter\def\csname ae@slogan@#1@max\endcsname{#2}%%'0
  \expandafter\def\csname ae@slogan@#1.#2\endcsname{#5}}

\newif\if@iterate@through@subslogans
\def\get@slogan#1{%%
  \@ae@sep#1.0.0\@nil
  \ifnum\ae@second>0\relax
    \expandafter\ae@get@\[email protected]\@nil
    :\hspace{0.5em}%%'
  \else
    \xdef\aemax{\csname ae@slogan@\ae@first @max\endcsname}%%
    \typeout{====> MAX=\aemax}%%'
    \ifnum\aemax>0\relax
      \@iterate@through@subsloganstrue
    \fi
  \fi
  \ae@get@#1.0.0.0\@nil
  \if@iterate@through@subslogans
    \expandafter\@iterate@subslogans
  \fi
  \@iterate@through@subslogansfalse
}
\def\ae@get@#1.#2.#3.#4\@nil{%%
  \csname ae@slogan@#1.#2\endcsname}

\def\@iterate@subslogans{%%
    \edef\ae@list{}
      \foreach \myx in {1,2,...,\aemax}
      {\typeout{==> (\myx|\ae@first) \csname ae@slogan@\ae@first.\myx \endcsname}%%' :\ae@list   
       }
    \begin{enumerate}\item
      \ae@list
    \end{enumerate}
}

\def\aeitem{\item}
\def\@ae@sep#1.#2.#3\@nil{%%
  \def\ae@first{#1}%%
  \def\ae@second{#2}}

%% define slogans
\slogan*{1}{First of all train in the preliminaries}
\slogan*{1.1}{Arithmetic\rule{1em}{2pt}}
\slogan*{1.2}{Algebra}
\slogan*{1.3}{Geometry}

\makeatother
\pagestyle{empty}
\begin{document}

  \slogan{1}

  \slogan{1.2}

\end{document}

错误消息

====> MAX=3
! Missing \endcsname inserted.
<to be read again> 
                   \def 
l.65   \slogan{1}

答案1

\rule是一个脆弱的命令,因此您不能在\write没有的情况下使用它\protect

\slogan*{1.1}{Arithmetic \protect\rule{1em}{2pt}}

答案2

我根本不知道您的代码应该做什么,但是,前面的代码\tracingmacros=1显示\slogan{1}了以下内容:

\ae@set@ #1.#2.#3.#4:#5\@nil ->\expandafter \def \csname ae@slogan@#1@max\endcs
name {#2}\expandafter \def \csname ae@slogan@#1.#2\endcsname {#5}
#1<-\def 
#2<-0
#3<-0
#4<-0
#5<-\reserved@b 
! Missing \endcsname inserted.
<to be read again> 
                   \def 
l.65   \slogan{1}

由于#1\def不可扩展的,因此不能在 内部使用\csname...\endcsname

答案3

\typeout我实际上需要 @davidcarlisle 答案的替代方案,因为我不能依赖传递给具有适当编辑的脆弱命令的内容\protect。这是一个也可以通过调用来工作的解决方案\detokenize

而不是打电话

  \foreach \myx in {1,2,...,\aemax}
  {\typeout{==> (\myx|\ae@first) \csname ae@slogan@\ae@first.\myx \endcsname}%%' :\ae@list   
   }

我可以改用

  \foreach \myx in {1,2,...,\aemax}
  {\typeout{==> (\myx|\ae@first) \detokenize\expandafter\expandafter\expandafter{\csname ae@slogan@\ae@first.\myx \endcsname}%%' :\ae@list   
   }}

尽管如此,还是非常感谢大卫,因为我之前还没有考虑过相关问题\typeout{...}

相关内容