5

Say I have an environment env which is used like this:

\begin{env}
    *Text*
\end{env}

Is it possible to "use" *Text* in the definition of the environment (top or bottom part) - similar as a parameter #1 is used within a command. I am aware that an environment is a completely different construct and actually consists of two commands which enclose *Text*. But I imagine a really cool hack which initiates scanning the text in the first command, and stores it to be used in the second. Is this at all possible?

  • 1
    Sounds very much like the X-Y problem :) Yes it's possible, but it's more work than you want to do. There are other 'box-saving' solutions, though. – Sean Allred Jul 21 '15 at 16:17
  • 2
    environ package does this. – Manuel Jul 21 '15 at 16:20
  • 1
    Defining \newenvironment{env}[1]{}{} will allow you to invoke it as \begin{env}{*Text*} ... \end{env}. Do you mean to use the complete text of the environment, or only the leading text? – Steven B. Segletes Jul 21 '15 at 16:27
  • It may be the X-Y problem in the sense that starting from scratch there might be a better solution. However, for legacy reasons I have to do exactly this... There are lots of environments in a big project, and I want to capture their body. – lukas.coenig Jul 21 '15 at 17:26
3

In principle, this is the way the environ package works:

The advantage to using environments is that their contents are not treated as a macro argument, so there are fewer restrictions on what can exist inside, and the processing can be more efficient for long pieces of document text.

The disadvantage of environments is that sometimes you really do want to collect up their body and apply some sort of command to the whole thing. This package provides a way to define such environments:

\NewEnviron{<name>}{<macro code>}[<final code>].

... the body of the environment is contained within the macro \BODY, and [<final code>] is the code executed at \end{<name>} ...

Here is a small example:

enter image description here

\documentclass{article}
\usepackage{environ}

\NewEnviron{italics}{\textit{\BODY}}

\begin{document}

\textit{Something}

\begin{italics}
  Something

  else
\end{italics}

\end{document}

You can pass \BODY - the body of the environment - to any macro as an argument.

  • This looks great, thanks :-) (I'll test it later.) – lukas.coenig Jul 21 '15 at 17:21
2

It wasn't clear whether you wanted to capture the complete environment body, or only the first item of the environment body. So I show both approaches.

To capture the complete body, I use an lrbox and then \unhbox it when needed.

For the partial capture, I supply it as an argument and then \gdef it inside the first part of the environment. That way, I can use its value inside the closing portion of the environment.

\documentclass{article}
\newsavebox\BODYBOX
\def\BODY{\unhbox\BODYBOX}
\newenvironment{env}
  {\begin{lrbox}{\BODYBOX}}
  {\end{lrbox}Here is \BODY} 
\begin{document}
\begin{env}
The body of my environment. The body of my environment. The body of my environment.
The body of my environment. The body of my environment. The body of my environment.
\end{env}

\noindent\hrulefill

\newenvironment{otherenv}[1]
  {\gdef\envvar{#1}\begin{itemize}\item My argument is #1}
  {\end{itemize}My argument was \envvar.\par} 

\begin{otherenv}{*Text*}
\item ... 
\end{otherenv}

\end{document}

enter image description here

  • This also looks great! I knew that this must be possible - it even seems to be much simpler than I thought! Btw. I wanted the whole body, but both is interesting, of course. – lukas.coenig Jul 21 '15 at 17:22

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.