Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

This is a precursor to my real question. But for whatever reason, when I tried reducing my code for something to post here, I got more errors. In particular, the following code gives me an error with the \endcsname in the \foreach loop. While the loop doesn't do anything like what I want it to, in my original code it actually compiled. Now in this snippet I get an error message about a missing \endcsname. Could someone please point out what I'm obviously overlooking?

\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@\ae@first.0.0.0\@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}

The error message

====> MAX=3
! Missing \endcsname inserted.
<to be read again> 
                   \def 
l.65   \slogan{1}
share|improve this question
    
\usepackage{fixltx2e} will robustify a number of fragile LaTeX commands, including \rule. It, too, will fix your code, for the reasons that David cites in his answer. –  Steven B. Segletes Feb 3 at 0:14

3 Answers 3

up vote 11 down vote accepted

\rule is a fragile command so you can not use it in a \write without \protect.

\slogan*{1.1}{Arithmetic \protect\rule{1em}{2pt}}
share|improve this answer
    
Argh. I knew I was overlooking something. Stay tuned for my real question because it's this same issue, I think, popping up all over again, but I can't seem to get it to work. –  A.Ellett Feb 2 at 22:09

I'm unable to get even the slightest idea what your code is supposed to do, however, putting \tracingmacros=1 before \slogan{1} shows the following:

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

Since #1 is \def which is not expandable, it can't be used inside \csname...\endcsname.

share|improve this answer
    
That's where I was getting stuck. There's no \def there to complain about. –  A.Ellett Feb 2 at 22:07
    
@A.Ellett the \def is random fallout from inappropriate expansion of the \@ifnextchar in the optional argument handling for \rule which doesn't work in a \write –  David Carlisle Feb 2 at 22:10
    
My code is supposed to define a series of slogans when called as \slogan*{<number>}{<content>}. The code should then present the slogan when called as \slogan{<number>}. Some slogans have subslogans affiliated with them. When calling the master slogan, I was thinking it would be nice to print a list of the subslogans too. It seems, via @DavidCarlisle 's comments and answer, that it isn't in how I'm defining the slogans but in the combination of \typeouts that expansion issues are getting confounded. –  A.Ellett Feb 2 at 22:41

I actually need an alternative to @davidcarlisle 's answer because I cannot rely upon the content passed to \typeout having fragile commands appropriately \protected. Here's a solution which also works by making a call to \detokenize:

Instead of calling

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

I could instead call

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

Nevertheless, many thanks to David because I hadn't been thinking about issues with \typeout{...}.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.