3

I would like to include answers in an exam paper so that the paper could be compiled in two different ways: with and without the answers. The way this is usually done in British universities (or at least some of them) is to use the comment package, like this:

\documentclass{article}
\usepackage{comment}
\excludecomment{answer}
\newcommand{\showanswers}{\renewenvironment{answer}{\begin{answershown}}{\end{answershown}}}
\newenvironment{answershown}{\textbf{Answer:} }{}
% \showanswers  % comment out to hide the answer
\begin{document}
  Is the following command correct?
  \begin{verbatim}
    public class
  \end{verbatim}
  \begin{answer} % do not indent!
    The following command is not correct:
    \begin{verbatim}
      public class
    \end{verbatim}
  \end{answer} % do not indent!
\end{document}

Here \showanswer is a toggle between the clean version of the paper (without the answers) and the version containing the answers. The disadvantage is that the comment package does not allow indentation (which is important in that it clearly shows the structure, potentially complicated, of the paper), and so compiling the source code above produces an error message:

Runaway argument?
! File ended while scanning use of \next.
<inserted text>
                \par
<*> ./mwe.tex

?

To allow indentation, I can use the environ package:

\documentclass{article}
\usepackage{environ}
\NewEnviron{answer}{}
\newcommand{\showanswers}{\RenewEnviron{answer}{\textbf{Answer:} \BODY}}
\showanswers  % comment out to hide the answer
\begin{document}
  Is the following command correct?
  \begin{verbatim}
    public class
  \end{verbatim}
  \begin{answer}
    The following command is not correct:
    \begin{verbatim}
      public class
    \end{verbatim}
  \end{answer}
\end{document}

But environ does not like verbatim in the answer, and compiling the latter source code produces:

Runaway argument?
 public class \end {verbatim}\env@ignore  The following command is no\ETC.
! File ended while scanning use of \@xverbatim.
<inserted text>
                \par
<*> ./mwe.tex

?

Is there a way to have both indentation and verbatim (in answers)?

Vlad
  • 79
  • Any reason you don't use lstlisting to draw the code? I think to remember verbatim does not like being in many things ^^ Also, to indent you may find adjustwidth useful. – tobiasBora Nov 26 '21 at 21:21
  • Just don't use environ and use the normal \newenvironment from LaTeX, which does not grab the whole environment at once. (or if you really need to grab it use cprotEnv, but may be overkill) – user202729 Nov 27 '21 at 05:05
  • @tobiasBora: I am still getting an error when using lstlisting: Package Listings Warning: Text dropped after begin of listing on input line 19. ... (It says "warning" but in fact the system enters into a dialogue with me which I can't leave without simply closing the window.) I have tried both listings and mcode packages. But for my purpose it would be good to be able to deal with verbatim as well: I would like my colleagues to use my style file, and some of them like verbatim. – Vlad Nov 27 '21 at 08:29
  • @user202729: I do not know how to remove the body of the environment in \newenvironment (which I need in the clean version of the exam paper). (Things like \iffalse\fi did not work for me.) And no success with cprotEnv so far. – Vlad Nov 27 '21 at 08:49

2 Answers2

1

Seems that lstlisting and verbatim plays with catcodes and can't really be used inside environments, at least when we want to be able not to display them. I'm not sure if it's the best solution, but you can save your code before your environment inside a box using the package realboxes and the command \Sbox{\mylstbox}{your content} (make sure to create your box using \newsavebox{\mylstbox}) , and reuse it after inside your environment via \usebox{\mylstbox}. It works for both verbatim and lstlisting.

mode exam:

enter image description here

mode answers:

enter image description here

By the way, I think that tcolorbox also has a module for answers, you may like it (and I guess this solution also applies to tcolorbox mode).

%%% Comment/uncomment, or compile with:
%%%
%%% pdflatex -jobname=exam_answers "\def\showanswers{} \input{exam.tex}" && pdflatex -jobname=exam_no_answers "\input{exam.tex}"
%%%
%%% to produce automatically two versions without changing the file.
% \def\showanswers{}
\documentclass{article}
\usepackage{listings}
\usepackage{realboxes} % https://tex.stackexchange.com/questions/29971/why-can-lstlisting-not-be-saved-in-a-command
\usepackage{changepage} % For adjustwidth and indentation
\NewDocumentEnvironment{answer}{+b}{
  \ifdefined\showanswers
  \textbf{Answer}:

\begin{adjustwidth}{1cm}{0cm} % Indent #1 \end{adjustwidth} \else\fi}{} \newsavebox{\mylstbox}

\begin{document}

\noindent Is the following command correct? \begin{lstlisting} public class \end{lstlisting} \Sbox{\mylstbox}{% \begin{lstlisting} public class { hello } \end{lstlisting} } \begin{answer} The following command is not correct:

\usebox{\mylstbox} \end{answer} % do not indent! \end{document}

tobiasBora
  • 8,684
1

Okay, there are several possible solutions. (you can use either one of the first 2)

I rewrite them into separate questions (future readers are more likely to search for these terms).


How can I define a "comment" environment such that the environment delimiter can be indented?

Easy, use verbatim package.

\usepackage{verbatim}
\let\answer=\comment
\let\endanswer=\endcomment

Reference: Redefine environment to be a synonym for another

Note that it's actually possible to indent environments defined by comment package with tab, only space fails.

Alternatively:


How can I redefine an environment defined by the environ package, such that it allows catcode-changing commands (e.g. \verb, \begin{verbatim}) in its body?

There's nothing special with environments defined by the environ package. You can still use \renewenvironment to redefine it as usual.

\usepackage{environ}
\NewEnviron{answer}{}

\newcommand{\showanswers}{\renewenvironment{answer}{\begin{answershown}}{\end{answershown}}} \newenvironment{answershown}{\textbf{Answer:} }{}


Not that you need this one, but for reference:

How can I define an environment with the environ package, such that it allows catcode-changing commands in its body?

You can't. There are alternatives like savebox or scontents package.

Reference: Verbatim in environ’s \BODY

user202729
  • 7,143