[Tex/LaTex] Code fails with Emergency stop, when using \expandafter\csname and such in listings

listingsprogramming

I am further working on my code for LaTeX Examples. I want to use the package showexpl for the simultaneus printing of code and results. Unfortunately I get an '! Emergency stop.'

\documentclass{scrbook}
\makeatletter
\providecommand{\packagename}{templatedemo}
\RequirePackage{etoolbox}
\RequirePackage{showexpl}

\providecommand\AddDemo[3][]{%
  \expandafter\providecommand\csname demo@content@#2\endcsname{#3}%
  \expandafter\providecommand\csname demo@options@#2\endcsname{#1}%
}

\providecommand\demo@printhis{}
\providecommand\PrintDemo[1]{%
  \ifcsdef{demo@content@#1}%
  { % print 
    \renewcommand{\demo@printhis}{\expandafter\csname demo@content@#1\endcsname}
    \begin{LTXexample} 
      \demo@printhis
    \end{LTXexample} 
  }%
  {}
}

\AddDemo{text}{Sample Text}% end: \AddDemo

\makeatother
\listfiles

\begin{document}
  \PrintDemo{text}
\end{document}

If this would work, the next problem would be that the listings shall only show the expanded version. So If I wrote:

\begin{document}
    \begin{LTXexample} 
      \PrintDemo{text}
    \end{LTXexample} 
\end{document}

the listings package would output '\PrintDemo{text}' instead of its contents.

Best Answer

There are many problems in your code. The main one is that LTXexample is an environment much like verbatim and cannot be used in the argument of a command.

It's possible to circumvent this problem in some cases, via \scantokens. However your way to proceed won't respect line breaks in the input; at least not without heavy surgery with category codes that will break in any case because the code would be read many times; once a character token enters TeX its category code is fixed. With \scantokens it can be reread and category code reassigned, but once it's passed to LTXexample the problem will reappear.

Just to show a possibility, here is an attempt:

\newcommand\AddDemo[3][]{%
  \expandafter\newcommand\csname demo@content@#2\endcsname{#3}%
  \expandafter\newcommand\csname demo@options@#2\endcsname{#1}%
}

\newcommand\PrintDemo[1]{%
  \ifcsdef{demo@content@#1}%
  { % print 
    \letcs\next{demo@content@#1}%
    \toks@=\expandafter{\next}%
    \edef\next{\unexpanded{\begin{LTXexample}}^^J%
      \the\toks@^^J%
      \unexpanded{\end{LTXexample}}}%
    \scantokens{\next}%
  }%
  {}
}

\makeatother

\AddDemo{text}{Sample Text}% end: \AddDemo

You can try it and verify it seems to work as intended. But

\AddDemo{text}{Sample
   Text}

will print exactly in the same way (which is usually not intended in code samples). The major problem, however, is that

\AddDemo{text}{Sample Text \today}

will break listings (that is used by LTXexample). Try it.

Some comments

Your use of \providecommand is wrong; \providecommand\AddDemo will be silently ignored if \AddDemo is already defined. Say that some package defines it: you'll be very puzzled about the result.

It's wrong also inside the definition of \AddDemo; say that

\AddDemo{text}{demo1}
...
\AddDemo{text}{demo2}

is, by mistake, used: \PrintDemo{text} would always use demo1 and you'll not be notified about the double definition.

Also \expandafter\csname demo@content@#1\endcsname is questionable: the \expandafter will try to expand d (which of course is not expandable); the effect is exactly the same as \csname demo@content@#1\endcsname. In other situations a misplaced \expandafter can produce disasters.

I can understand that you'd like to have the code samples all in one place, but typesetting TeX code requires subtleties that make this goal quite difficult (if not impossible) to attain.

Related Question