1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
|
<head>
<title>UK TeX FAQ -- question label cmdasenv</title>
</head><body>
<h3>Collect command arguments in an environment</h3>
<p>The inquisitive user, who examines the code of the <code>lrbox</code>
environment, will find that, stripped of considerable complication
(which arises from the internal workings of LaTeX), the environment
consists of:
<blockquote>
<pre>
\newenvironment{lrbox}[1]{%
\setbox#1=\vbox\bgroup
}{%
\egroup
}
</pre>
</blockquote>
Which (even though it doesn't work as written here) might cause
optimism that one might redefine a command as an environment using
some elaboration of:
<blockquote>
<pre>
\newcommand{\fred}[1]{...}
\newenvironment{fredenv}{%
\fred\bgroup
}{%
\egroup
}
</pre>
</blockquote>
Sadly, it doesn't work like that: not even
<blockquote>
<pre>
\fred\bgroup ... \egroup
</pre>
</blockquote>
works. Putting stuff on the argument stack crucially requires
<em>real</em> braces.
<p>To use an environment to collect the argument of a command, one really
needs to store the body of the environment separately. Several
packages use such a technique, but the <i>amsmath</i> package makes
it half-visible, as an internal command. Use it as:
<blockquote>
<pre>
\usepackage{amsmath}
...
\makeatletter
\newenvironment{fredenv}%
{\collect@body \fred}%
{}
\makeatother
</pre>
</blockquote>
With this definition, the body of the <code>fredenv</code> will be
passed as an argument to the command <code>\</code><code>fred</code>.
<p>Note, however, that there's a tendency for stray spaces to appear in
the argument. Judicious use of <code>\</code><code>ignorespaces</code> before the argument,
and <code>\</code><code>unskip</code> after the argument, in the macro <code>\</code><code>fred</code>, may be
valuable.
<p>If you want a command <code>\</code><code>jim{arg1}{arg-to-collect}</code>, the obvious
<blockquote>
<pre>
...
{\collect@body{\jim{arg1}}}
...
</pre>
</blockquote>
doesn't work; the argument of <code>\</code><code>collect@body</code> has to be a single
token. You achieve what you need by:
<blockquote>
<pre>
\makeatletter
\newcommand{\jimtemp}{}
\newenvironment{jimenv}[1]%
{%
\renewcommand\jimtemp{\jim{#1}}
\collect@body \jimtemp}%
{}
\makeatother
</pre>
</blockquote>
<p>Unfortunately, while the construction may be useful in some instances, it
does <em>not</em> provide a means of avoiding restrictions on the use of
<code>\</code><code>verb</code> in command arguments: the whole of the environment's body
passes through the argument of a command embedded in <code>\</code><code>collect@body</code>.
<dl>
<dt><tt><i>amsmath.sty</i></tt><dd>Distributed as part of the AMSLaTeX bundle,
<a href="ftp://cam.ctan.org/tex-archive/macros/latex/required/amslatex.tar.gz">macros/latex/required/amslatex</a> (<a href="ftp://cam.ctan.org/tex-archive/macros/latex/required/amslatex.zip">zip</a>, <a href="http://www.tex.ac.uk/tex-archive/macros/latex/required/amslatex/">browse</a>)
</dl>
<p><p>This question on the Web: <a href="http://www.tex.ac.uk/cgi-bin/texfaq2html?label=cmdasenv">http://www.tex.ac.uk/cgi-bin/texfaq2html?label=cmdasenv</a>
</body>
|