18

I want to use an environment defined with NewEnviron from environ in another environment definition:

\documentclass{article}

\usepackage{environ}

\NewEnviron{inner}[1]{%
  \textbf{#1:} \BODY
}

\newenvironment{out}{%
  \begin{inner}{Using outer}%
}{%
  \end{inner}%
}

\begin{document}
  \begin{inner}{Using inner}
    Lorem ipsum\ldots
  \end{inner}

  \begin{out}
    Lorem ipsum\ldots
  \end{out}
\end{document}

The resulting PDF looks as desired:

enter image description here

But the log shows some erros:

./test.tex:22: LaTeX Error: \begin{inner} on input line 20 ended by \end{out}.
 ...                                              
l.22 \end{out}

./test.tex:23: LaTeX Error: \begin{out} on input line 20 ended by \end{document
}.
 ...                                                  
l.23 \end{document}

...
(\end occurred inside a group at level 1)

### semi simple group (level 1) entered at line 20 (\begingroup)
### bottom level

If I define out using NewEnviron, that is

\NewEnviron{out}{%
  \begin{inner}{Using outer}%
    \BODY
  \end{inner}%
}

then pdflatex does not terminate.

Apparently, something is mixed up (presented to the parser in the wrong order). What is going wrong?

  • @Raphael From the examples it's hard to understand why you want environ in the first place. But nesting two \NewEnviron defined (pseudo)environments will lead to assign to \BODY something that contains \BODY: an infinite loop is waiting for you. – egreg Oct 22 '12 at 17:48
  • @egreg In dependence of some value, I want to drop the content of an environment. Using xifthen, I did not see a (LaTeX) way to do it without NewEnviron, and it works beautifully with. Ah, right, \BODY prevents nesting; I think I encountered that one before. – Raphael Oct 22 '12 at 17:50
15

Environments within environments causing errors can be circumvented using the command-form of the environment. So, try

\newenvironment{out}
  {% \begin{out}
    \inner{Using outer}%
  }{% \end{out}
    \endinner%
  }

As mentioned in comment by egreg, nesting \NewEnvirons would lead to a circular reference to \BODY - the captured environment contents macro.

  • Defining out using NewEnviron and \inner/\endinner does not work, so you are skrewed if you need NewEnviron for the outer environment? – Raphael Oct 22 '12 at 17:51
  • While you don't explicitly state this, this answer may be interpreted as it is ok to use \inner and \endinner for environments created by \NewEnviron. This contradicts your answer for “Runaway argument?” error with \NewEnviron which states "\NewEnviron{myenv} creates a macro \myenv which designates the start of the environment, and this macro is on the lookout for exactly \end{myenv}... nothing else". Or am I misinterpreting something? – Peter Grill Nov 9 '18 at 18:12
  • @PeterGrill: I don't infer that nor should it be interpreted that way. – Werner Nov 9 '18 at 18:16
  • @Werner: Ok. Can you edit the answer to explicitly state that. Or, do you think having these comments is adequate? I am currently have an issue with nested \NewEnviron and came across this answer before the other one and that is how I interpreted it. Spent sometime trying to get the macro version of a \NewEnviron working, before coming across the other answer. – Peter Grill Nov 9 '18 at 18:21
12

The nesting problem is due to the fact that every (pseudo)environment defined with \NewEnviron uses \BODY for storing the contents.

Actually the control sequence name can be modified, but not after an environment has started. One might use directly \collect@body or \Collect@Body, but this would be very cumbersome.

My suggestion is to define two versions of the same environment:

\newenvironment{innerx}[1]
 {\textbf{#1:}}
 {}

\NewEnviron{inner}[1]{%
  \innerx{#1} \BODY
}

\newenvironment{outx}
  {\innerx{Using outer}}
  {\endinnerx}

\NewEnviron{out}{\outx~\BODY\endoutx}

Of course, in the present example the outx environment is not necessary and

\NewEnviron{out}{\innerx{Using outer} \BODY\endinnerx}

would suffice.

Complete example:

\documentclass{article}

\usepackage{environ}

\newenvironment{innerx}[1]
 {\textbf{#1:}}
 {}

\NewEnviron{inner}[1]{%
  \innerx{#1} \BODY
}

\newenvironment{outx}
  {\innerx{Using outer}}
  {\endinnerx}

\NewEnviron{out}{\outx~\BODY\endoutx}

\begin{document}
  \begin{inner}{Using inner}
    Lorem ipsum\ldots
  \end{inner}

  \begin{out}
    Lorem ipsum\ldots
  \end{out}
\end{document}

Update

With environ version 0.3, dated 2014/05/04, it's easier to have nested environments defined with \NewEnviron. When the

\environbodyname<control sequence>

command is found, every \NewEnviron from that point on should be defined using <control sequence> instead of \BODY. Here's an example based on the previous code.

\documentclass{article}
\usepackage{environ}

\NewEnviron{out}{%
  \begin{inner}{Using outer}%
    \BODY
  \end{inner}%
}

\environbodyname\innerBODY
\NewEnviron{inner}[1]{%
  \textbf{#1:} \innerBODY
}

\begin{document}

\begin{inner}{Using inner}
Lorem ipsum\ldots
\end{inner}

\begin{out}
Lorem ipsum\ldots
\end{out}

\end{document}

enter image description here

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.