Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Triple-wrapping of \colorbox → \NewEnviron → \newenvironment fails

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.

like image 484
kolypto Avatar asked May 26 '10 02:05

kolypto


2 Answers

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.

like image 63
Alexey Malistov Avatar answered Sep 28 '22 11:09

Alexey Malistov


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
            }%
        }%
    }%
like image 36
kolypto Avatar answered Sep 28 '22 10:09

kolypto