2

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.)

3
  • 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
  • Related: tex.stackexchange.com/questions/159820/…
    – egreg
    Sep 29, 2016 at 20:29

1 Answer 1

1

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

enter image description here

Uncomment \excludecomment{solution} and compile to obtain

enter image description here

1
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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