views:

77

answers:

2

Hello! I am trying to wrap an environment created with \NewEnviron (package 'environ') into an old good \newenvironment:

\NewEnviron{test}{\colorbox[gray]{0.7}{\BODY}}
\newenvironment{wrapper}{\begin{test}}{\end{test}}

\begin{wrapper}
debug me
\end{wrapper}

However, this gives me a strange error:

LaTeX Error: \begin{test} on input line 15 ended by \end{wrapper}. LaTeX Error: \begin{wrapper} on input line 15 ended by \end{document}.

If I replace \NewEnviron{test}{aaa(\BODY)bbb} with \newenvironment{test}{aaa(}{)bbb} — everything works as expected! It seems like \NewEnviron fails to find its end for some reason.

I'm trying to do some magic with 'floatfig' wrapped into a \colorbox so I need a way to convert \colorbox to an environment and wrap it into another one. I can define a new command but it's not a very good idea.

Thanks in advance!

+4  A: 

The thing is that \NewEviron and \newenvironment works in different ways.

1) \newenvironment{test}{aaa(}{)bbb} defines two commands: \test is aaa( and \endtest is )bbb.

\begin{test} is expanded to \test.

\end{test} is expanded to \endtest and checks that your scope begins with begin{test} rather \begin{something else}, for example \begin{wrapper}.

2) \NewEviron{test}{aaa(\BODY)bbb} defines \test in different way. First of all \test catches the \BODY using the following trick

\def\test#1\end{\def\BODY{#1}aaa(\BODY)bbb\testcontinue}

(name \testcontinue may be different) and inserts aaa(\BODY)bbb. Then \testcontinue checks that \end on some input line ended by \end{test} rather than \end{something else}. Macro \endtest is not needed because it is never executed.

Look on your code:

\begin{wrapper}
debug me               
\end{wrapper} 

\begin{wrapper} is expanded to \begin{test}. Then \begin{test} is expanded to \test. \test catch \BODY. Attention! \BODY is equal to debug me. And now \testcontionue checks that \end after \BODY ended by \end{test}. It is not true. \end{test} is absent. There is \end{wrapper}.

You want to say that \end{wrapper} must be expanded to \end{test}. But \end before wrapper was eaten by

macro \test: #1\end{\def\BODY{#1}aaa(\BODY)bbb\testcontinue}

and can not be executed.

I hope I success to explain.

Alexey Malistov
Your explanation is great, thank you! I guess that means I can't wrap it into another environment? or maybe there's a trick I'm not aware of?
o_O Tync
Why don't you want to use `\newenvironment`?
Alexey Malistov
I need to create an environmental version of `\colorbox` and have no idea how to do it :)
o_O Tync
accepted: w/out your explanations I would have failed. Спасибо, земляк! :)
o_O Tync
+1 Excellent explanation. I had looked at the NewEnviron code and couldn't figure out Will's freaky staging of his arguments.
Charles Stewart
A: 

I've found a hacky trick to create an environment that can be wrapped in another one. One should use saveBoxes like this:

\newenvironment{example}[2][]{%
    \newsavebox{\exampleStore} % Box storage
    \begin{lrbox}{\exampleStore} % Start capturing the input
    }{%
        \end{lrbox} % Stop capturing the input
    \colorbox[gray]{0.7}{%
            \usebox{\NBstorage} % Load the box's contents
            }%
        }%
    }%
o_O Tync