Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to define an environment which typesets the contents in a box, and I'd like to use TikZ (I'm aware of alternatives like fancybox). So I would like something like

\newenvironment{abox}%
  {\begin{tikzpicture}\node(box){\begin{minipage}{0.8\textwidth}}%
  {\end{minipage}};}

However, this doesn't work, because the {...} that wraps the TikZ node can't be split across the beginning and end of the environment. Is there anyway around this? Thanks!

share|improve this question

2 Answers 2

up vote 31 down vote accepted

In such cases the environ page comes handy. Its command \NewEnviron collects the body which can be accessed as \BODY macro within your definition. Here's a complete example:

\documentclass{article}
\usepackage{tikz}
\usepackage{environ}
\NewEnviron{abox}{%
  \begin{tikzpicture}
      \node(box){%
        \begin{minipage}{0.8\textwidth}
          \BODY
        \end{minipage}};
   \end{tikzpicture}
}
\begin{document}
\begin{abox}
  Text
\end{abox}
\end{document}

This compiles without problems and draws the test box.

share|improve this answer
    
Extremely useful, thanks! –  Neil Olver Nov 19 '10 at 17:26
    
Didn't know about that one. Thanks. –  Matthew Leingang Nov 19 '10 at 18:45
    
+1 for pointing out the environ package; extremely useful also for other things (shameless plug). @Stefan, only one thing: \NewEnviron takes only 2 mandatory arguments (and one optional argument behind those); it won't see the pair of braces {}. –  Hendrik Vogt Nov 19 '10 at 20:52
    
@Hendrik: Thank you! I corrected that. –  Stefan Kottwitz Nov 20 '10 at 13:33

First of all: I never knew about environ and am impressed. My answer is not nearly so good, but I learned it from the LaTeX sources so it should count for something.

Try writing

\newenvironment{<stuff>{\iffalse}\fi}
               {\iffalse{\fi}<stuff>}

<stuff>, of course, is what you wrote. The point is that there are no unbalanced braces in this construction, because when parsing macro arguments, TeX does not actually expand anything, in particular, \iffalse. Thus, the "commented out" braces are present for the purposes of reading in the contents of the environment commands, and then absent for the purposes of executing them.

EDIT: In this and many other cases, the much simpler expedient of \bgroup...\egroup works too:

\newenvironment{<stuff>\bgroup}
               {\egroup<stuff>}

Since \bgroup is \let to equal { and \egroup is \let to }, this (in theory) is synonymous with using braces, except that (since these "implicit characters" don't count as far as nesting inside arguments being parsed is concerned) it doesn't break definitions.

Occasionally you come across a situation where literal braces are required; \def itself is an example. You must write

\def\cs{<def'n>}

and not

\def\cs\bgroup<def'n>\egroup

but in many higher-level constructions (including, my quick test shows, TikZ) this is not a problem.

share|improve this answer
    
+1, nice explanations. I'm not so sure about the trick with \iffalse: It looks useful, but is there any instance where you can use this trick, and \bgroup + \egroup doesn't work? (For \def it doesn't seem to help!) –  Hendrik Vogt Nov 21 '10 at 8:06
    
@Hendrik Vogt: Unfortunately \def is totally inflexible! So that was a bad example. But I have found exactly one situation where this trick is necessary: with \halign. See, \halign allows you to protect &s and \crs appearing inside its entries (as in, within a nested \halign) by surrounding them in {...}. These are required to be literal braces. So if you have an environment where an alignment entry is broken from \begin to \end, you need to use the \iffalse trick if you want to protect its contents. –  Ryan Reich Nov 21 '10 at 8:24
    
@Hendrik Vogt: By the way, you can make it work in \def if you unbalance the \iffalse trick: just write \def\cs{...\iffalse{\fi}. \def doesn't care if the inside has apparently unbalanced opening braces, but if the \iffalse{\fi} appears inside another macro argument, it will have properly balanced closing braces, which \def does care about. Of course, writing \def\cs{\iffalse}\fi...\iffalse{\fi} makes \cs = \iffalse and then gives an error as soon as \def finishes because you have a lonely \fi (unless you are in another conditional, when you get a subtler error...). –  Ryan Reich Nov 21 '10 at 8:49
    
Why do you say that your answer is not as good? With the \bgroup/\egroup trick, the text inside the environment can have verbatim in it, which the environ package does not allow. –  Philippe Goutet Nov 21 '10 at 20:04
    
@Philippe Goutet: I added \bgroup/\egroup after I made that comment. In my opinion, the \iffalse trick is just that: a trick, and not something to be recommended. As it is, I guess what I wrote is not so bad anymore. –  Ryan Reich Nov 21 '10 at 21:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.