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.

Suppose I want to define an environment which is essentially a modification of an existing one. I tried something like that:

\newenvironment{newenv}{%
  \formatcommand{\begin{oldenv}%
}{%
  \end{oldenv}}%
}

I would expect

\begin{newenv}Foo\end{newenv}

to result in the same output as

\formatcommand{\begin{oldenv}Foo\end{oldenv}}

But whenever I use \begin{newenv}, pdflatex says

Missing } inserted

and skrews up everything afterwards, of course. Without \formatcommand everything is fine, so apparently the orphan { form \formatcommand is the culprit.

My guess is that pdflatex tries to treat stuff inside environment definition parts as something syntactically correct---which what I do clearly is not---instead of "just" to replace text and parse afterwards.

Is there a way to get around this, i.e. have a command span from a new environments beginning to end?

Use case:

\newenvironment{card}{%
  \resizebox{55mm}{85mm}{\begin{tabular*}{55mm}{| p{50.5mm} |}%
  \hline%
}{%
  \hline\end{tabular*}}%
}

If I put the same resizebox around the usage site of card, it compiles and resizes (even though not the way I intended, but that's for another day).

share|improve this question
    
Not sure what you are tying to do here. Why are you passing the \begin{oldenv} to \formatcommand? –  Peter Grill Sep 28 '11 at 20:56
1  
It mostly depends on what \formatcommand is supposed to do and on what oldenv is. A "real world" example is needed. –  egreg Sep 28 '11 at 20:57
    
I would have thought that this issue relates to general properties of (La)TeX, but there you go. –  Raphael Sep 28 '11 at 21:07
    
@PeterGrill I want to have \formatcommand applied to the whole environment oldenv. As I repeat card often in the application and need the same resize, I figured an environment def would be the place to put it. –  Raphael Sep 28 '11 at 21:12
add comment

4 Answers

up vote 5 down vote accepted

For applying some macro/command to the body of an environment, you may want to extract the entire body into a macro itself. This can be done (to whatever limited extent) using the environ package. Here is a short example:

\documentclass{article}
\usepackage{environ}% http://ctan.org/pkg/environ
\NewEnviron{itquote}{%
  \itshape% Set shape to italics
  \begin{quote}
    \BODY% regular \BODY of itquote environment
  \end{quote}
}
\begin{document}
\begin{quote}% Original quote environment
  Here is a very simple quote
\end{quote}
\begin{itquote}% New itquote environment
  Here is a very simple quote
\end{itquote}
\end{document}
​

enter image description here

In the above (admittedly elementary) example, itquote italicizes its contents (stored in the macro \BODY). For some, it provides a more intuitive way of working with environments within environments.

Additionally, it is always good to view the package documentation (and sometimes even the package source .sty). For example, although minipage is an environment and is typically used in the context of \begin{minipage}{<width>} ... \end{minipage} it can also be used in a "macro pair form" using \minipage{<width} ... \endminipage. Again, for some, this allows for a more intuitive way of splitting environment begin/end's over a new environment definition.

share|improve this answer
    
That works wonderfully, thanks! Good hint regarding macro pairs, too, even though I don't see myself digging is sty files. –  Raphael Sep 28 '11 at 21:25
add comment

You can't leave unbalanced braces in a definition. That's forbidden by TeX's syntax rules.

There is a workaround:

\newsavebox{\cardbox}
\newenvironment{card}
  {\begin{lrbox}{\cardbox}
   \begin{tabular*}{55mm}{| p{50.5mm} |}
   \hline
  }
  {\hline
   \end{tabular}
   \end{lrbox}%
   \resizebox{55mm}{85mm}{\usebox{\cardbox}}%
  }

The contents of the environment is saved in the \cardbox bin which is later processed.

See Werner's answer for another method which is particularly useful in other situations.

share|improve this answer
    
I don't understand what happens here, and it seems a lot of boilerplate compared to environ. Does your solution have technical advantages? –  Raphael Sep 28 '11 at 21:26
    
For example, environments defined with environ can't go in the argument of commands, nor in the definition of other environments. The lrbox way uses only kernel methods (except \resizebox, of course). –  egreg Sep 28 '11 at 21:31
    
I see. In my case, the environment in queston is going to be top-level so I'll stick with environ, but I appreciate your answer. –  Raphael Sep 28 '11 at 21:34
add comment

Here is an example of defining a new environment:

\documentclass{article}
\usepackage{lipsum}
\newenvironment{MyQuote}{%
    \begin{quote}%
    % Add customization that goes after the start of the environment here
}{%
    % Add customization that goes before the end of the environment here
    \end{quote}%
}%

\begin{document}
  \begin{MyQuote}
    \lipsum[1]
  \end{MyQuote}
\end{document}

I suspect that you are trying to use some macro of the form \macro{} and attempting to add the \macro{ at the beginning and } at the end environment. Don't think this is allowed with the standard \newenvironment. You could use the environ package, with which provides access to the body of the environment via \BODY. Here is an example:

\documentclass{article}
\usepackage{lipsum}
\usepackage{xcolor}
\usepackage{environ}

\NewEnviron{MyQuote}{%
  \quote%
  \textcolor{red}{\BODY}%
}{%
  \endquote%
}
\begin{document}
  \begin{MyQuote}
    \lipsum[1]
  \end{MyQuote}
\end{document}
share|improve this answer
    
This answer does not relate to the question. I tried to clarify that the general way of defining new environments is not the issue (or so I think) but specifically how to have a command span from before its begin to after its end. –  Raphael Sep 28 '11 at 21:03
    
See updated regarding the environ package. –  Peter Grill Sep 28 '11 at 21:13
    
That works wonderfully, thanks! –  Raphael Sep 28 '11 at 21:24
add comment

What should \formatcommand do?

Your definition has no balanced braces, I hope the following sequence shows, what happens:

\newenvironment{newenv}{%Open parameter 2 of \newenvironment
  \formatcommand{\begin{oldenv}%
}%this closes formatcommand
{%you open a group
  \end{oldenv}
}%The group is closed%
}%you close parameter 2 of \newenvironment
%%Now you should get the 3rd parameter of \newenvironment
share|improve this answer
    
This clearly is what happens and I stated as much in the question. Do you have a solution? –  Raphael Sep 28 '11 at 21:09
add comment

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.