# Why can lstlisting not be saved in a command?

This code fails with Emergency stop:

\documentclass{scrbook}
\usepackage{listings}
\newcommand{\demo}{%
\begin{lstlisting}
foobar
\end{lstlisting}
}

\begin{document}
\demo
\end{document}


Why?

-
Because lstlisting has to play with category codes and putting it into the definition of a command inhibits category code changes. –  egreg Sep 29 '11 at 20:55
–  Marco Daniel Sep 30 '11 at 7:02

In your code the whole lstlisting code is read as a macro argument before the code is executed. When (La)TeX reads some code it does some processing like it strips comments, combines multiple spaces to one, converts line breaks to spaces and two line breaks in a row to \par etc.

However, the lstlisting environment and all other verbatim environments or macros want to have all of these characters (space, line break, comment characters) in their unchanged, verbatim form. For this the change the internal configuration of them by alter the so called category codes (catcodes), so that e.g. % is now a normal character and doesn't start a comment any longer, the \ doesn't start a macro any longer etc.

Now, when the code is already read as part of a macro argument all catcodes have already be assigned to the characters and some have already be transformed as mentioned above, so that the changes made by the verbatim environment afterwards when it is executed do not have any effects any longer.

In general there is the rule that verbatim material can't be used inside a macro argument or pseudo-environment (an environment which reads its whole content, see e.g. the environ package, but also tabularx does it). Luckily boxes are read and processed like normal text, so you can use e.g. the lrbox environment to store the lstlisting in a savebox and use it later using \usebox. However, you can't use the \sbox or \savebox macro because they read the content also as macro argument. I wrote the realboxes package just to provide alternatives which read the content as box, so you could use \Sbox and \Savebox instead after loading that package.

-

The listings package provides some experimental features that allows you to capture it in a macro/command. However, as stated in the package documentation, this is not advised (section 5.1 Listings inside arguments, p 46):

There are some things to consider if you want to use \lstinline or the lstlisting environment inside arguments. Since TeX reads the argument before the lst-macro is executed, this package can't do anything to preserve the input: spaces shrink to one space, the tabulator and the end of line are converted to spaces, TeX's comment character is not printable, and so on. Hence, you must work a bit more. You have to put a backslash in front of each of the following four characters: \{}%. Moreover you must protect spaces in the same manner if: (i) there are two or more spaces following each other or (ii) the space is the ﬁrst character in the line. That's not enough: Each line must be terminated with a "line feed" ^^J. And you can’t escape to LaTeX inside such listings! ... You might wonder that this feature is still experimental. The reason: You shouldn't use listings inside arguments; it’s not always safe!

As such, the following works:

\documentclass{scrbook}
\usepackage{listings}
\newcommand{\demo}{%
\begin{lstlisting}^^J
foobar^^J
\end{lstlisting}
}

\begin{document}
\demo

Some text

\demo
\end{document}


This does not answer your question, but instead provides a different work-around, if you're interested. Not sure how effective this is in general, but you can store an lstlisting in a box (using the lrbox environment). That is, I'm not sure whether there are some limitation that may stem from options passed to a lstlisting environment. It works for this minimal case.:

\documentclass{scrbook}
\usepackage{listings}% http://ctan.org/pkg/listings
\begin{document}
\newsavebox{\mylisting}
\begin{lrbox}{\mylisting}
\begin{lstlisting}
foobar
\end{lstlisting}%
\end{lrbox}

\usebox{\mylisting}% Print box mylisting

Some text.

\usebox{\mylisting}% Print box mylisting
\end{document}

-
I wouldn't use \box0: Matthias wants to define \demo in the preamble and use it afterwards, so a box register should be allocated. –  egreg Sep 29 '11 at 21:00
The lrbox environment instead of \setbox would be better here because it adds the required internal color commands. Otherwise there might be color issues when placing the saved box. –  Martin Scharrer Sep 30 '11 at 6:14
@MartinScharrer: Thanks for the suggestion; modified my answer accordingly. –  Werner Sep 30 '11 at 6:22
Adding the minipage environment to manually set the width might also be useful. –  Martin Scharrer Sep 30 '11 at 6:27