# Postponing environment content

I would like to create an environment foo and a command \listfoo so that:

• The content of the foo environment is hidden; and
• The command \listfoo lists all the text that was contained in a foo environment.

In other words, the following code:

\documentclass{article}
\usepackage{lipsum}
\newenvironment{foo}{% Some code here
}
{% Some code here
}
\newcommand{\listfoo}{
% Some code to list the content of the foo environments.
}

\begin{document}
\lipsum[1]

\begin{foo}
\bf Foo text 1
\end{foo}

\lipsum[2]

\begin{foo}
\bf Foo text 2
\end{foo}

\lipsum[3]

\begin{foo}
\bf Foo text 3
\end{foo}

\listfoo
\end{document}


should produce the following output:

Any suggestions for how to proceed would be much appreciated. Thanks!

• \bf is a deprecated command. You want \bfseries ...
– user31729
Feb 18 '18 at 18:23

This uses a macro \foocollect and \NewEnviron instead of \newenvironment, the \foocollect expands the previous \foocollect versions and then the local \BODY of the current environment.

\documentclass{article}
\usepackage{lipsum}

\usepackage{environ}

\def\foocollect{}

\NewEnviron{foo}{% Some code here
\xdef\foocollect{\expandafter\unexpanded\expandafter{\foocollect}\par\expandafter\unexpanded\expandafter{\BODY}}%
}[% Some code here
]

\newcommand{\listfoo}{%
\foocollect%
% Some code to list the content of the foo environments.
}

\begin{document}
\lipsum[1]

\begin{foo}
\bfseries Foo text 1
\end{foo}

\lipsum[2]

\begin{foo}
\bfseries Foo text 2
\end{foo}

\lipsum[3]

\begin{foo}
\bfseries Foo text 3
\end{foo}

\listfoo
\end{document}


Update with storing to a file instead of memory

\documentclass{article}
\usepackage{lipsum}

\usepackage{environ}
%\usepackage{morewrites}% only if you run out of filehandles

\newwrite\collectedcontentfile

\AtBeginDocument{%
% Automatically open the file at the beginning of the document
\immediate\openout\collectedcontentfile=\jobname.cll
}

\NewEnviron{foo}{% Some code here
\immediate\write\collectedcontentfile{%
\expandafter\unexpanded\expandafter{\BODY}^^J
}%
}[% Some code here
]

\newcommand{\listfoo}{%
%Closing the file
\immediate\closeout\collectedcontentfile%
\InputIfFileExists{\jobname.cll}{}{}
}

\begin{document}
\lipsum[1]

\begin{foo}
\bfseries Foo text 1
\end{foo}

\lipsum[2]

\begin{foo}
\bfseries Foo text 2
\end{foo}

\lipsum[3]

\begin{foo}
\bfseries Foo text 3
\end{foo}

\listfoo
\end{document}

• Thanks! This will do for now, though I'm having some issues with the \foocollect taking up too much memory. Feb 18 '18 at 20:11
• It is possible to write the whole content to a file and input the file later on.
– user31729
Feb 18 '18 at 21:09
• That's what I'm looking into and (at least currently) failing to implement. If you'd be willing to edit your answer to suggest a way of implementing that then I'd be very grateful. No worries if not. Feb 18 '18 at 21:15
• @CliveNewstead: See the update at the end, please. The stored file is named \jobname.cll, where .cll stands for collected, e.g. foo.cll if your document is called foo.tex
– user31729
Feb 18 '18 at 21:28
• Incredible! It works perfectly. Thank you so much. Feb 18 '18 at 21:38

An alternative using the scontents package:

\documentclass{article}
\usepackage{lipsum}
\usepackage{scontents}
\newenvsc{foo}[store-env=foopost,print-env=false]

\begin{document}
\lipsum[1]

\begin{foo}
\textbf{Foo text 1
\end{foo}

\lipsum[2]

\begin{foo}
\textbf{Foo text 2}
\end{foo}

\lipsum[3]

\begin{foo}
\textbf{Foo text 3}
\end{foo}
\noindent
\foreachsc[after={\\}]{foopost}
\end{document}


with the same proposed output: