18

I'm working on an exam document class where the user enters in questions something like this:

\multiplechoice{Question}
{Answer #1}
{Answer #2}
{Answer #3}
{Answer #4}
{Correct answer}
{Explanation}

I'd like to process this information in various ways in one LaTeX run (to create an answer sheet, key, and the test itself), so the questions need to be stored in a macro. The awkwardness comes when one defines:

\newcommand{\sectionA}[1]{\newcommand{\putsectionA}{#1}}

and then asks the user to put 15 questions as an argument to \sectionA. I'd much rather have those questions be the contents of an environment, like so:

\begin{sectionA}
lots of questions
\end{sectionA}

Mostly because I find it much easier to keep track of environment declarations than curly brackets. Is it possible to have the contents of an environment get packaged up into a macro?

Edit:

The solution would seem to be to us the environ package, but it doesn't seem to be working. Here's what I'm trying:

\documentclass{article}
\usepackage{environ}
\NewEnviron{foo}{\edef\foot{\BODY}}
\begin{document}
\begin{foo}
  Store This
\end{foo}
\foot
\end{document}

However when running this code \foot remains undefined. It actually seems impossible to define any macro using environ. Even when not using \BODY. For example, replacing the definition above with

\NewEnviron{foo}{\newcommand{\foot}{Print me}}

still fails. I've also tried \Collect@Body from the environ package with similar results. Does \NewEnvrion somehow prohibit defining new commands?

20

The environ package gives you access to the environment body over the \BODY macro. You can copy it e.g. using \let or \edef:

\NewEnviron{sectionA}{\global\let\putsectionA\BODY}

or

\NewEnviron{sectionA}{\xdef\putsectionA{\BODY}}

\xdef is like a global \newcommand but doesn't check if the command existed before and expands its content before the definition. This is important because the definition of \BODY will of course change after the environment.

  • Thanks for the prompt reply! That makes a lot of sense to me, but for whatever reason the macro where I wish to store the questions remains undefined. I'm not sure this is proper practice, but I've edited my question to include an example of the issue I encountered when trying your suggestion. – Silver Mar 28 '11 at 8:03
  • 1
    @Silver: I forgot that the code is executed as part of the environment and is therefore grouped! This means that you need to use \global\let or \xdef instead. I will update my answer. – Martin Scharrer Mar 28 '11 at 8:24
  • This didn’t quite work for me: it breaks when the environment body given includes \vspace, or other macros that mustn’t be expanded too early. Modifying it to \NewEnviron{sectionA}{\xdef\putsectionA{\unexpanded\expandafter{\BODY}}} fixes this, making it more closely equivalent to \newcommand{\putsectionA}{ […stuff…] }, since then the stuff passed as the body doesn’t get expanded until it’s later invoked with \putsectionA. – Peter LeFanu Lumsdaine Aug 12 '17 at 19:19

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.