# lstlisting vs csname problem with "Text dropped after beginning of listing"

For my class, I write exercises; I also include the solutions (for me and the TAs). I like to process a single document, but set a "flag" to say whether to produce solutions or not. This answer helped me make that work. But when I include a "lstlisting" within the optional material, things no longer work properly:

\documentclass{article}
\RequirePackage{listings}
\RequirePackage{etoolbox}

\newcommand{\solflag}{}

\newcommand{\version}[2]
{\ifcsdef{#1flag}{#2}{}}

\begin{document}

Before.

\version{sol}{
\begin{lstlisting}[language=C]
// An example of a C comment.
\end{lstlisting}
}

After.
\end{document}


Processing this with pdflatex on my Linux machine produces a warning (Package Listings Warning: Text dropped after begin of listing on input line 18.) followed by an "asterisk-waiting-for-input" state.

From this answer, I see that stuff after \begin{lstlisting} (on the same line) gets swallowed up and ignored and provokes that warning. Does the processing of arguments to macros swallow up all the end-of-line markers or something? And if so, is there something I can do to make this work?

(One answer: I can use \lstincludelisting, which seems to work fine...but it's nice to see small (10 line?) listings right in place rather than by reference. And switching over involves editing dozens of documents, too.)

• You're supplying verbatim-like content as part of a macro argument, and this is not allowed. Consider using the comment package which does what you'll after - allowing versions to comment in/out certain environments.
– Werner
Sep 29, 2016 at 20:24
• Thanks. What makes the listings content "verbatim-like", and how could I have known this in advance?
– John
Sep 29, 2016 at 20:26
• Sep 29, 2016 at 20:29

You cannot pass a listings environment - lstlisting or similar - as an argument to a macro (\version in your case) as lstlisting does a number of category code changes, all of which causes problems when gobbled as an argument. This is very similar in nature to supplying verbatim-like content as an argument, so see Why doesn't verbatim work within ...?

Instead of using "flags" as booleans, define a comment-like environment that distinguishes between your "solution" and "non-solution" version:

\documentclass{article}

\usepackage{listings,comment}

\includecomment{solution}% Include solution environment
%\excludecomment{solution}% Exclude solution environment

\setlength{\parindent}{0pt}% Just for this example

\begin{document}

Before.

\begin{solution}
\begin{lstlisting}[language=C,basicstyle=\ttfamily]
#include <iostream.h>

main()
{
cout << "Hello World!";
return 0;
}
\end{lstlisting}
\end{solution}

After.

\end{document}


Compile the above as-is to obtain

Uncomment \excludecomment{solution} and compile to obtain

• Thanks. THat's nice and clear. And to leave the exterior scripts that use this untouched, I can presumably use the "flag" to select the include/exclude options, since those are NOT verbatim-like. It does mean that I have to abandon my "\version{sol}" macro, though, and replace its braces with a begin/end pair, which is a pity (and a good deal of work). Thanks for the explanation of why this is necessary.
– John
Sep 30, 2016 at 0:49