# Collecting environment content with support for xparse arguments

I'm trying to create an environment which uses xparse style arguments but I have to be able to use the whole environment content in the environment definition, e.g. as an argument.

Ideally I'd like to write something like

\DeclareCollectedDocumentEnvironment { env } { o } {
Make use of optional Argument #1 and Content \CollectedBody.
}
\begin{env}[optional]
content
\end{env}


Is there a reason, why xparse doesn't provide something like this?

Using \NewEnviron from the environ package does not work for me, because I'm reliant on some of the argument-parsing features xparse provides.

Currently I've got this working:

\documentclass{article}
\usepackage{xparse}
\usepackage{environ}

\ExplSyntaxOn

\DeclareDocumentCommand { \myenv } { o u\q_nil } {
opt:~#1 \\
content:~#2
}
\cs_set:Npn \myenv_collect:n #1 {
\myenv #1 \q_nil
}
\makeatletter
\DeclareDocumentEnvironment { env } { } {
\Collect@Body \myenv_collect:n
} { }
\makeatother

\ExplSyntaxOff

\begin{document}

\begin{env}[99]
With optional argument
\end{env}

\begin{env}
Without optional argument
\end{env}

\end{document}


This however has some flaws:

• Multiple paragraphs inside the environment cause an infinite loop
• Nesting does not work as expected

I've also tried to declare the arguments for \DeclareDocumentEnvironment and somehow pass them onto \myenv_collect:n, but the behaviour of \Collect@Body made it difficult.

Is there a solution to my problem, preferably a latex3 one?

An interface similar to \NewEnviron would be a welcome addition to xparse; but you can use it indirectly:

\documentclass{article}
\usepackage{xparse,environ}

\NewDocumentEnvironment{env}{ O{default} }
{\Environenv{#1}}
{\endEnvironenv}

\NewEnviron{Environenv}[1]
{Do something with #1 and \BODY}

\begin{document}

\begin{env}
What is this?

Another paragraph.
\end{env}

\begin{env}[foo]
What is this?

Another paragraph.
\end{env}

\end{document}


If you call the command form of Environenv, it will know what environment it's been called in. That's the same trick for defining environments containing align in amsmath.

## Important news (March 2019)

With the release 2019-03-05 release of xparse, the functionality of environ has been implemented, with some adaptations. See below for a description.

Due to freezing of TeX Live, it is currently only available in TL2019/pretest or MiKTeX.

The above code can be reduced to

\documentclass{article}
\usepackage{xparse}

\NewDocumentEnvironment{env}{O{default}+b}
{Do something with #1 and #2}
{}

\begin{document}

\begin{env}
What is this?

Another paragraph.
\end{env}

\begin{env}[foo]
What is this?

Another paragraph.
\end{env}

\end{document}


Some notes: the argument specifier b denotes the body of the environment, which will be then collected as a macro argument, just like environ did. There is no \BODY to use: in this case b is the second argument, so one refers to it as #2.

The “end part” is to be specified, although it will be usually empty.

If paragraphs are expected in the body, the argument should be specified as +b, like all other “long arguments”.

• Is there an 'xparse only' approach now (3 years later)? – Andy Nov 11 '17 at 19:03
• @Andy Now there is news! :-) – egreg Mar 8 '19 at 12:49
• @egreg I saw the announcement of this on comp.text.tex, but the announcement has since disappeared. I'm using the 2019 TeXLive pretest, though I don't believe the new version has been installed. – sgmoye Mar 8 '19 at 13:03
• @sgmoye Use tlmgr to update it. – egreg Mar 8 '19 at 13:54
• @egreg Well, I have been doing just that (for 2019), successfully, though tlmgr.log makes no mention of xparse. Just ran sudo tlmgr update xparse and got this back: tlmgr: xparse mentioned, but neither new nor forcibly removed. This is certainly not critical, just curious. The fact that the announcement is now missing on CTT suggests that it was withdrawn? – sgmoye Mar 8 '19 at 14:04