1

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:

Sample

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

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

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.

enter image description here

\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}
8
  • 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
  • 2
    @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
  • 1
    Incredible! It works perfectly. Thank you so much. Feb 18 '18 at 21:38
2

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: output

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.