Search code examples
latex

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.


Solution

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