4

I have a macro that requires some setup code before being called :

\documentclass{minimal}
\usepackage{color}
\begin{document}
% some setup code
\colorbox{green}{This is green.}
% some cleanup code
\end{document}

All is good, but I don't like duplicating the setup/cleanup code.

How can I get a similar result using Environments? That way I could place the setup code in the "begin" section and the cleanup in the "end" section.

I tried the following, but obviously that's not how it works :

\documentclass{minimal}
\usepackage{color}

% % % % THIS DOES NOT WORK % % % %
\newenvironment{green}{\colorbox{green}\begingroup}{\endgroup}
% % % % THIS DOES NOT WORK % % % %

\begin{document}

\begin{green}
This should be green as well.
\end{green}

\end{document}

This gives the error ! Extra }, or forgotten \endgroup. I tought that \begingroup and \endgroup were specifically for using in unbalanced situations.

What are my options?

  • In Lieu of my bad answer, let me leave my original comment: \begingroup and \endgroup only help if you want a group. To get unbalanced braces, one technique is to use \bgroup and \egroup, which are \let to { and }, but this doesn't help with macro arguments. It does help with (most) boxes, but that's special. – Ryan Reich Aug 27 '13 at 19:08

3 Answers3

7

enter image description here

You can use the lrbox environment to collect the contents.

\documentclass{minimal}
\usepackage{color}


\newenvironment{green}
{\begin{lrbox}{0}}
{\end{lrbox}\colorbox{green}{\usebox{0}}}


\begin{document}

\begin{green}
This should be green as well.
\end{green}

\end{document}
David Carlisle
  • 757,742
  • this doesn't work for long piece of texts with linebreaks in it though. How could one go in that case (without using environ)? – glS Oct 24 '16 at 13:56
  • @glS it uses colorbox as the OP requested, if you need a multi-line box then you need to nest minipage inside the lrbox, as usual. – David Carlisle Oct 24 '16 at 14:13
  • but with minipage you get that if you started the environment in the middle of a line the whole text in the environment starts from the middle of the line – glS Oct 24 '16 at 14:15
6

You can manage environments in a similar way you would macros by means of environ:

enter image description here

\documentclass{article}
\usepackage{environ}% http://ctan.org/pkg/environ
\usepackage{xcolor}% http://ctan.org/pkg/xcolor

\NewEnviron{green}{\colorbox{green}{\BODY}}%

\begin{document}

\colorbox{green}{This should be green as well.}

\begin{green}
This should be green as well.
\end{green}

\end{document}

The environment contents is grabbed and stored in \BODY, which can then be passed to a macro. However, this does not support boxing verbatim content, something an lrbox-approach does.

Werner
  • 603,163
1

While the other answers fully address the OP's question quite well, no one has mentioned the use of keys. I would take an approach very similar to @DavidCarlisle (though I also like @Werner 's approach too). But, I would create keys to manage the color (and possibly other set up material) to allow me to change the color later in the document for a particular use.

The OP's comment about set up code is what got me thinking about keys.

Here's a MWE:

\documentclass{article}
\usepackage{pgfkeys}
\usepackage{xcolor}

\pgfkeys{/jt/colored/box/.cd,
  color/.initial = green,
}

\newsavebox{\mycolorBox}
\newenvironment{mycolor}[1][green]
  {\pgfkeys{/jt/colored/box/.cd,color=#1}%%'
   \begin{lrbox}{\mycolorBox}}
  {\end{lrbox}%%'
   \colorbox
     {\pgfkeysvalueof{/jt/colored/box/color}}%%'
     {\usebox{\mycolorBox}}}
\pagestyle{empty}
\begin{document}

   \begin{mycolor}
    Green box
   \end{mycolor}

   \begin{mycolor}[blue!20]
    Blue box
   \end{mycolor}

\end{document}

enter image description here

Regarding keys, there are many nice packages out there for dealing with keys. Recently, I've been experimenting a lot with pgfkeys or working with l3keys. But there's also many other such packages: see A big list of every keyval package details about other possible key-value packages

A.Ellett
  • 50,533
  • I don't think those \expandafter's are necessary, as accessing the value requires two expansion steps. – egreg Aug 27 '13 at 20:11
  • @egreg You're right! Somehow things weren't working until I put those in. I must have inadvertently fixed the bug when I modified my code. – A.Ellett Aug 27 '13 at 20:28