% \title{A couple of things involving environments}
% \author{Will Robertson}
% \date{\filedate \qquad \fileversion}
%
% \maketitle
%
% \begin{abstract}
% \noindent This package provides two things, one for document authors and one for macro authors. For the document authors, a new method of defining environments that might be more convenient on occassion. And for the package writers, \pkg{amsmath}'s \cmd\collect@body\ command, and a long version of the same, \cmd\Collect@Body.
% \end{abstract}
%
% \section{Introduction}
%
% This packages provides new commands for defining environments. Here's a trivial example:
% \begin{example}{}
% \NewEnviron{test}{%
% \fbox{\parbox{1.5cm}{\BODY}}
% \color{red}
% \fbox{\parbox{1.5cm}{\BODY}}}
%
% \begin{test}
% par\par
% graf
% \end{test}
% \end{example}
%
% \cmd\RenewEnviron\ can be used with the same syntax to redefine a pre\"existing environment.
%
% \section{For the document author}
%
% \LaTeX's standard method of defining environments looks like this (ignoring arguments for now):
% The advantage to using environments is that their contents is not treated as a macro argument, so there are less 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 its body and apply some sort of command to the whole thing. This package provides a way to define such environments, and v0.2 of this package brings a new syntax:
% You saw an example in the introduction; the body of the environment is contained within the macro |\BODY|, and \oarg{final code} is the code executed at |\end|\marg{name} (more on this later).
%
% \subsection{Environment arguments}
%
% If you want to use arguments to the environment, these are specified in the usual way:
% where \marg{macro code} has arguments |#1|, |#2|, \dots, as per traditional \LaTeX\ environment mandatory and optional arguments. Here's an example with two arguments; one optional argument (|#1|, which is |\today| if omitted) and one mandatory argument (|#2|):
% \begin{example}{}
% \NewEnviron{test}[2][\today]{%
% \fbox{\parbox{3cm}{%
% \textbf{#2}\\
% \BODY\\
% (#1)}}}
%
% \begin{test}{Title}
% par\par graf
% \end{test}
%
% \begin{test}[Yesterday]{Title}
% par\par graf
% \end{test}
% \end{example}
%
% \subsection{\oarg{final code}}
% This is the code executed at |\end|\marg{name} of the environment.
% For the purposes of this package it is only designed (but is very useful indeed) for cleanup code such as space gobbling in the input text.
%
% \DescribeMacro{\environfinalcode}
% This macro sets a default value for the \oarg{final code} (unless manually specified) in each subsequent environment created with \cmd\NewEnviron. The default is to define each new environment postfixed by \cmd\ignorespacesafterend, like this:
% where \marg{macro code} has argument |#1| as everything inside the environment.
%
% Now, this kind of environment definition makes collecting arguments a little cumbersome. Arguments are defined with a separate macro that `gobbles up' the arguments inside the environment before the body is passed to \marg{macro code}.
% I've tried to ensure that whitespace is ignored at the appropriate places; without this additional code, there would be a space before `par' and after `graf' in the examples above.
%
% Environments created with \cmd\NewEnvironment\ are ended by the command \cmd\ignorespacesafterend, which means that if they're used in a paragraph then the |\end{...}| command will gobble space after it. (If the environment is a paragraph on its own, there will be no difference.)
%
% \newpage
% \section{For the macro author}
%
% The \pkg{amsmath} package contains a macro that facilitates the functionality in the previous section, which package writers may wish to use directly. The canonical command is \cmd\collect@body, which I've also defined in \cmd\long\ form to be useable for multi-paragraph environments (\cmd\Collect@Body). Here's how it's used:
%
% \begin{example}{}
% \long\def\wrap#1{[#1]}
% \newenvironment{test}{\Collect@Body\wrap}{}
% \begin{test}
% hello
%
% there
% \end{test}
% \end{example}
%
% And here's a crude example with environment arguments:
%
% \begin{example}{}
% \long\def\wrap#1{[\arg#1]}
% \def\arg#1{---#1---\par}
% \newenvironment{test}{\Collect@Body\wrap}{}
% \begin{test}{arg}
% hello
%
% there
% \end{test}
% \end{example}
%
% \StopEventually{}
%
% \clearpage
% \part{\pkg{\jobname} implementation}
%\iffalse
%<*package>
%\fi
%
% This is the package.
% \begin{macrocode}
\ProvidesPackage{environ}[2008/06/18 v0.2 A new way to define environments]
% \end{macrocode}
%
% \PrintChanges
%
% \section{Begin}
%
% \begin{macro}{\environbodyname}
% \darg{control sequence}
% Changes the control sequence used to represent the environment body in its definition. Not to be used as a user command; but maybe one day it will be. Don't change this after defining any |\NewEnviron| environments!
% \begin{macrocode}
\def\environbodyname#1{\def\env@BODY{#1}}
\environbodyname\BODY
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\environfinalcode}
% \darg{code}
% This is the \marg{code} that's executed by default at \cs{end}\marg{env.\,name}:
% Now, \pkg{amsmath} defines \cmd\collect@body\ for us. But that package may not be loaded, and we don't want to have to load the whole thing just for this one macro.
% |env@#1@parse| executes the body twice: the first time to save the body while ignoring the arguments; and the second time to process the environment definition itself while ignoring the environment body:
% \begin{macrocode}
\longdef@c{env@#1@parse}##1{%
\csname env@#1@save@env\endcsname##1\env@nil
\csname env@#1@process\endcsname##1\env@nil}%
% \end{macrocode}
% These must be defined on a per-environment basis in order to get the argument gobbling right: (because there are a variable number of arguments)
% If \cmd{\env@BODY} were variable, this macro would have to be saved for every environment definition individually; at the moment we just use a global definition.
% Use \cmd\trim@spaces\ to remove surrounding space:
% \begin{macrocode}
\long\def\env@save#1\env@nil{%
\expandafter\edef\env@BODY{%
\unexpanded\expandafter
\expandafter\expandafter{\trim@spaces{#1}}}}
% \end{macrocode}
% \end{macro}
% This is the same as a \cmd\@gobblenil\ but long and less likely to exist in the environment body:
% \begin{macrocode}
\long\def\env@ignore#1\env@nil{}
% \end{macrocode}
% \changes{v0.2}{2008/06/16}{Added.}
% \end{macro}
%
% \section{Backwards compatibility}
% \begin{macro}{\NewEnvironment}
% \darg{Environment name}
% \darg{Macro definition applied to env.\ body}
% Here's our new environment definition macro. First of all wrap it up appropriately for new- or renew-
% \begin{macrocode}
\newcommand\NewEnvironment{%
\let\env@newenvironment\newenvironment
\let\env@newcommand\newcommand
\Make@Environment}
\newcommand\RenewEnvironment{%
\let\env@newenvironment\renewenvironment
\let\env@newcommand\renewcommand
\Make@Environment}
% \end{macrocode}
% And here we go:
% \begin{macrocode}
\newcommand\Make@Environment[2]{%
% \end{macrocode}
% Initial `argument' parser, does nothing but remove leading space:
% Now precede the env.\ body by the argument parsing command, which may or may not be defined in \cmd\EnvironArgs\ (and \cmd\unskip\ removes trailing space)
% \begin{macrocode}
\longdef@c{env@@#1}##1{%
\csname env@@@#1\endcsname{%
\csname env@args@#1\endcsname##1\unskip}}%
% \end{macrocode}
% And then pass it all off to the environment macro (|#2|),
% \begin{macrocode}
\longdef@c{env@@@#1}##1{#2}}
% \end{macrocode}
% \changes{v0.2}{2008/06/11}{Changed \cs{@currenv} to \texttt{\#1} to allow nesting.}
% \changes{v0.2}{2008/06/16}{Deprecated.}
% \end{macro}
%
% \begin{macro}{\EnvironArgs}
% \darg{Environment name}
% \doarg{Number of arguments}
% \doarg{Optional argument}
% \darg{Argument macro code}
% Tedious argument parsing:
% \begin{macrocode}
\newcommand\EnvironArgs[1]{%
\@ifnextchar[
{\Env@Args{#1}}
{\Env@Args{#1}[0]}}
% \end{macrocode}
% Tedious argument parsing:
% \begin{macrocode}
\long\def\Env@Args#1[#2]{%
\@ifnextchar[
{\Env@@@Args{#1}[#2]}
{\Env@@Args{#1}[#2]}}
% \end{macrocode}
% This is when there is no optional argument. In this case and the next, we simply define a command that is inserted when the argument body is processed (see \cmd\NewEnvironment). \cmd\ignorespaces\ removes leading space after the arguments.