summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/sauerj/collect.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/sauerj/collect.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/sauerj/collect.dtx')
-rw-r--r--macros/latex/contrib/sauerj/collect.dtx815
1 files changed, 815 insertions, 0 deletions
diff --git a/macros/latex/contrib/sauerj/collect.dtx b/macros/latex/contrib/sauerj/collect.dtx
new file mode 100644
index 0000000000..05a8f50c76
--- /dev/null
+++ b/macros/latex/contrib/sauerj/collect.dtx
@@ -0,0 +1,815 @@
+% \iffalse meta-comment
+% Line endings: UNIX
+% Tab size: 4
+%
+% Copyright 2004 Jonathan Sauer
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2003/12/01 or later.
+%
+% This work has the LPPL maintenance status "maintained".
+%
+% The Current Maintainer of this work is Jonathan Sauer
+% (<jonathan.sauer@gmx.de>).
+%
+% This work consists of the files collect.dtx and collect.ins
+% and the derived file collect.sty.
+%
+% \fi
+%
+% \iffalse
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{collect}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+% Modification of verbatim for tabs in listings
+\makeatletter
+{\catcode`\ =\active%
+\catcode`\^^I=\active%
+\gdef\@vobeyspaces{%
+\catcode`\ \active\let \@xobeysp%
+\catcode`\^^I\active\def^^I{~~}%
+}}%
+\makeatother
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+%
+%<package>\NeedsTeXFormat{LaTeX2e}
+%<package>\ProvidesPackage{collect}
+%<package> [2004/09/12 v0.9 collect the contents of an environment]
+%
+% \fi
+%
+% \CheckSum{256}
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+%
+% \DoNotIndex{\@currenvir,\@ehc,\@ifundefined,\@input}
+% \DoNotIndex{\@tempa,\@tempb,\bgroup,\catcode,\closeout,\csname}
+% \DoNotIndex{\def,\edef,\egroup,\else,\end,\endcsname,\expandafter}
+% \DoNotIndex{\fi,\futurelet,\gdef,\global,\ifx,\immediate,\jobname,\let,\long}
+% \DoNotIndex{\meaning,\newcommand,\newenvironment,\newif,\newwrite}
+% \DoNotIndex{\openout,\PackageError,\par,\strip@prefix,\the,\toks@}
+% \DoNotIndex{\write}
+%
+% \GetFileInfo{\jobname.sty}
+%
+% \title{The \textsf{collect} package\thanks{This document
+% corresponds to \textsf{\filename}~\fileversion, dated \filedate.}}
+%
+% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}}
+%
+% \date{\filedate}
+%
+% \maketitle
+%
+% \begin{abstract}
+% This file describes the \textsf{collect} package that
+% makes it possible to collect text for later use.
+%
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \section{Introduction}
+%
+% Suppose you are writing the specification of a programming language.
+% Then you will surely insert definitions of the grammar (i.e. using
+% the \textsf{syntax} package). Most likely you will insert the
+% grammar for i.e. loops, conditions et cetera in the appropriate
+% chapter, but for easy implementation of a parser, you will want to
+% include the complete grammar as an appendix, so that one does not
+% have to collect the complete grammar from the bits in each chapter.
+%
+% Of course you could do this by hand using the copy-and-paste
+% facility of your text editor. But this is cumbersome and errorprone
+% if you modify the grammar afterwards, i.e. for a second version.
+%
+% This package provides the |collect| environment that typesets
+% its contents and collects it for later use as well.
+%
+% In other situations you will want to save the contents of an
+% environment in a macro. Then the |collectinmacro| environment
+% should do the trick.
+%
+%
+%
+% \section{Usage}
+%
+% \paragraph{General note} If an environment exists in a normal and a
+% starred form (i.e. |collect| and |collect*|), then the former does
+% not typeset the environment contents, while the latter typesets it.
+% Note, too, that the normal and the starred version of an environment
+% often have a different number of parameters.
+%
+% \paragraph{Stripping of spaces} All environments strip any leading
+% space before the start of the text and any trailing space after the
+% end of the text. Trailing |\par|s (i.e. resulting from a blank line
+% at the end of the environment) are \emph{not} removed.
+%
+%
+%
+%
+% \subsection{\texttt{collect}}
+%
+% You can define several \emph{collections}. Each collection can be
+% used independently to collect text across the document. You define a
+% collection using |\definecollection|, use it in the |collect| and
+% |collect*| environment and typeset it using |\includecollection|.
+%
+% \paragraph{Note} The name of the collection is used as the suffix of
+% the file that stores the collection (the complete name is
+% \meta{jobname}|.|\meta{name)}. So you should not name a collection
+% |tex|, |log|, |dvi|, |pdf| and so on.
+%
+% \paragraph{Note} You can only include a collection after completely
+% collecting it. If you include it and continue to collect afterwards,
+% the collection will be cleared after its inclusion.
+%
+% This can be used to recycle a collection: Use it in the first part
+% of your document to collect text, typeset this text using
+% |\includecollection| and then reuse the collection in the second
+% part of your document to collect new text which will finally be
+% typeset using |\includecollection| a second time.
+%
+%
+% \DescribeMacro{\definecollection} Usage: |\definecollection|
+% \marg{name}.
+%
+% Defines a collection of the name \meta{name}.
+%
+%
+% \DescribeEnv{collect*} Usage: |\begin{collect*}|
+% \marg{name} \marg{before} \marg{after} \marg{beforecol}
+% \marg{aftercol} \ldots\ |\end{collect*}|.
+%
+% Collects the text inside the environment in the collection
+% \meta{name}. Then typesets the text. \meta{name} must have been
+% defined using |\definecollection|.
+%
+% \meta{before} and \meta{after} are tokens inserted before and after
+% the environment contents in the collection as well as the typeset
+% text.
+%
+% \meta{beforecol} and \meta{aftercol} are tokens inserted before and
+% after the environment contents only in the collection. This can be
+% used to insert a section heading (\meta{beforecol}) and a backref to
+% the section where the text has been collected (\meta{aftercol}).
+%
+% \paragraph{Note} The |collect*| environment uses a temporary file
+% \meta{jobname}|.tmp| to temporarily store the environment contents
+% and include it afterwards.\footnote{This way, catcode changes inside
+% the environment are honored.}
+%
+%
+% \DescribeEnv{collect} Usage: |\begin{collect}| \marg{name}
+% \marg{beforecol} \marg{aftercol} \ldots\ |\end{collect}|.
+%
+% Collects the text inside the environment in the collection
+% \meta{name}. \emph{Does not} typeset the text (therefore, the two
+% parameters \meta{before} and \meta{after} are missing); except for
+% that, this environment is identical to |collect*|.
+%
+%
+% \DescribeMacro{\includecollection} Usage: |\includecollection|
+% \marg{name}. Includes the collection \meta{name}. Afterwards, the
+% collection is reset.
+%
+% You can include the collection \emph{before} it is actually
+% collected in the same way you can include a table of contents at the
+% beginning of your document. Simply say |\includecollection| and then
+% use the |collect*| or |collect| environment to collect text. Then
+% run \LaTeX\ on your file \emph{twice}. (the first time to collect
+% the text, the second time to put it in the document using
+% |\includecollection|)
+%
+%
+%
+% \subsection{Other environments}
+%
+% \DescribeEnv{collectinmacro} Usage: |\begin{collectinmacro}|
+% \marg{macro} \marg{before} \marg{after} \ldots\
+% |\end{collectinmacro}|.
+%
+% Collects the contents of an environment inside a macro \meta{macro}
+% without typesetting it. If \meta{macro} has been defined prior to
+% using this environment, its previous meaning is lost. The new
+% definition is global.
+%
+% \meta{before} and \meta{after} are tokens inserted before and after
+% the environment contents in the macro.
+%
+% \paragraph{Important note} This environment differs slightly from
+% |collect| and |collect*|: Some macros, i.e. |\verb|, do not work
+% correctly when \meta{macro} is used later on.\footnote{As the
+% catcodes have already been set when collecting the contents and
+% cannot be changed afterwards, at least not without e\TeX.}
+%
+%
+%
+%
+% \section{Examples}
+%
+% \subsection{\texttt{collect}}
+%
+% \begin{verbatim}
+% \begin{collect*}{tst}{Before\par}{\par After}{Before file\par}{\par After file}
+% This is a test
+% \end{collect*}
+% \end{verbatim}
+%
+% \noindent This results in the following text typeset directly:
+%
+% \begin{verbatim}
+% Before
+% This is a test
+% After
+% \end{verbatim}
+%
+% \noindent And following text is typeset when the collection |tst| is
+% included using |\includecollection{tst}|:
+%
+% \begin{verbatim}
+% Before file
+% Before
+% This is a test
+% After
+% After file
+% \end{verbatim}
+%
+%
+%
+%
+% \subsection{Other environments}
+%
+% \begin{verbatim}
+% \begin{collectinmacro}{\collectedtext}{Before\par}{\par After}
+% This is a test
+% \end{collectinmacro}
+% \end{verbatim}
+%
+% \noindent This results in no text typeset directly and the following
+% text stored in the macro |\collectedtext|:
+%
+% \begin{verbatim}
+% Before\par This is a test\par After
+% \end{verbatim}
+%
+%
+%
+%
+% \section{Creating your own environment}
+%
+% You can create your own environment based on any of the environments
+% in this package, i.e. to create a |grammarpart| environment to
+% typeset part of a grammar.
+%
+% You can for example say:
+%
+% \begin{verbatim}
+% \definecollection{gra}
+%
+% \newenvironment{grammarpart}[1]{%
+% \@nameuse{collect*}{gra}{%
+% \emph{Start of grammar `#1'}\par%
+% }{%
+% \par\emph{End of grammar}\par%
+% }{%
+% \subsection{#1}%
+% }{%
+% \par See some section in the text.
+% }%
+% }{%
+% \@nameuse{endcollect*}%
+% }
+% \end{verbatim}
+%
+% \noindent This will create a |grammarpart| environment with one
+% parameter, the part of the grammar defined. (i.e. `Identifiers') At
+% the start of the environment the text `\emph{Start of grammar
+% \meta{part}}' will be typeset, followed by the grammar (the contents
+% of the environment), and finally a line `\emph{End of grammar}' will
+% be added.
+%
+% When including the collected grammar parts using
+% |\includecollection| each grammar part will be prefixed by a
+% subsection heading bearing the grammar part as its title and
+% suffixed by `See some section in the text.' (this could be extended
+% to include a backref using |\ref|\meta{label})
+%
+% \paragraph{Note} If you use any of the environments inside a custom
+% environment to afterwards collect text with this custom environment
+% (as in the example of the |grammarpart| environment above), you
+% \emph{must not} begin and end it using |\begin| and |\end|, or the
+% environment contents will not be collected correctly. You must use
+% |\@nameuse{|\meta{environment}|}| and
+% |\@nameuse{end|\meta{environment}|}| as in the example above, or, if
+% the environment is not starred, |\|\meta{environment} and
+% |\end|\meta{environment}.
+%
+% \paragraph{Note} You still can use the environments of this package
+% inside other environments (i.e. a |itemize| environment) without any
+% problems.
+%
+%
+%
+%
+% \section{Notes}
+%
+% \begin{itemize}
+% \item If you use any of the environments inside your own
+% environment, note that the end of the environment is
+% executed, but not included in the collected text! (that's
+% why the the environments |collect*| and |collectinmacro|
+% have two parameters for including text before and after
+% the environment, \meta{before} and \meta{after}).
+%
+% \end{itemize}
+%
+%
+%
+%
+% \StopEventually{}
+%
+% \section{Implementation}
+%
+% \subsection{Main environments and macros}
+%
+% \subsubsection{\texttt{collect}}
+%
+% \begin{macro}{\definecollection}
+%
+% Usage: |\definecollection| \marg{name}
+%
+% Defines a collection \meta{name}.
+%
+% This macro allocates a |\newwrite| |CE@@|\meta{name}|@out| and
+% defines a |\newif| |CE@@|\meta{name}|open|.
+%
+% \begin{macrocode}
+\newcommand{\definecollection}[1]{%
+ \@ifundefined{CE@@#1@out}{%
+ \expandafter\newwrite\csname CE@@#1@out\endcsname%
+ \expandafter\newif\csname ifCE@@#1@open\endcsname%
+ \csname CE@@#1@openfalse\endcsname%
+ }{%
+ \PackageError{collect}{Collection `#1' has already %
+ been defined}{\@ehc}%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{environment}{collect*}
+%
+% Usage: |\begin{collect*}| \marg{name} \marg{before}
+% \marg{after} \marg{beforecol} \marg{aftercol} \ldots\
+% |\end{collect*}|.
+%
+% \begin{macrocode}
+\newenvironment{collect*}[5]{%
+ \global\toks@{}%
+ \def\CE@file{#1}%
+ \def\CE@preenv{#2}%
+ \def\CE@postenv{#3}%
+ \def\CE@prefileenv{#4}%
+ \def\CE@postfileenv{#5}%
+ \CE@get@env@body@start%
+}{%
+% \end{macrocode}
+%
+% What are we doing? We make sure the collection is open, then we save
+% \meta{beforecol}, \meta{before}, the collected environment contents,
+% \meta{after} and \meta{aftercol} in the collection file.
+%
+% \begin{macrocode}
+ \CE@ensure@opened{\CE@file}%
+ \edef\@tempa{\csname CE@@\CE@file @out\endcsname}%
+ \immediate\write\@tempa{\CE@meaning\CE@prefileenv}%
+ \immediate\write\@tempa{\CE@meaning\CE@preenv}%
+ \immediate\write\@tempa{\the\toks@}%
+ \immediate\write\@tempa{\CE@meaning\CE@postenv}%
+ \immediate\write\@tempa{\CE@meaning\CE@postfileenv}%
+% \end{macrocode}
+%
+% Now we repeat the same thing, but with the temporary file and
+% writing only \meta{before}, the collected environment contents and
+% \meta{after}. Then we include the temporary file.
+%
+% Why so complicated, as we have the contents of the environment in
+% |\toks@|? Because the catcodes might not be correct, i.e. if |\verb|
+% is used inside the environment. So we have to read the environment
+% contents again, which without e\TeX\ is only possible using a
+% temporary file.
+%
+% \begin{macrocode}
+ \immediate\openout\CE@tmp@out=\jobname.tmp%
+ \immediate\write\CE@tmp@out{\CE@meaning\CE@preenv}%
+ \immediate\write\CE@tmp@out{\the\toks@}%
+ \immediate\write\CE@tmp@out{\CE@meaning\CE@postenv}%
+ \immediate\closeout\CE@tmp@out%
+ \@input{\jobname.tmp}%
+ \par%
+}
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \begin{environment}{collect}
+%
+% Usage: |\begin{collect}| \marg{name} \marg{beforecol}
+% \marg{aftercol} \ldots\ |\end{collect}|.
+%
+% \begin{macrocode}
+\newenvironment{collect}[3]{%
+ \global\toks@{}%
+ \def\CE@file{#1}%
+ \def\CE@prefileenv{#2}%
+ \def\CE@postfileenv{#3}%
+ \CE@get@env@body@start%
+}{%
+% \end{macrocode}
+%
+% As this environment, contrary to |collect*|, does not typeset its
+% contents, we only write to the collection file:
+%
+% \begin{macrocode}
+ \CE@ensure@opened{\CE@file}%
+ \edef\@tempa{\csname CE@@\CE@file @out\endcsname}%
+ \immediate\write\@tempa{\CE@meaning\CE@prefileenv}%
+ \immediate\write\@tempa{\the\toks@}%
+ \immediate\write\@tempa{\CE@meaning\CE@postfileenv}%
+}
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \begin{macro}{\includecollection}
+%
+% Usage: |\includecollection| \marg{name}.
+%
+% Includes the collection \meta{name} which must have been defined
+% previously using |\definecollection|. Afterwards, the collection is
+% cleared.
+%
+% \begin{macrocode}
+\newcommand{\includecollection}[1]{%
+ \CE@ensure@closed{#1}%
+ \@input{\jobname.#1}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsubsection{Other environments}
+%
+% \begin{environment}{collectinmacro}
+%
+% Usage: |\begin{collectinmacro}| \marg{macro} \marg{before}
+% \marg{after} \ldots\ |\end{collectinmacro}|.
+%
+% Collects the contents of an environment inside a macro.
+%
+% \begin{macrocode}
+\newenvironment{collectinmacro}[3]{%
+ \def\CE@destmacro{#1}%
+ \def\CE@postenv{#3}%
+% \end{macrocode}
+%
+% We initialize the result with \meta{before}:
+%
+% \begin{macrocode}
+ \toks@{#2}%
+ \CE@get@env@body@start%
+}{%
+% \end{macrocode}
+%
+% We add \meta{after}:
+%
+% \begin{macrocode}
+ \toks@\expandafter\expandafter\expandafter{%
+ \expandafter\the\expandafter\toks@\CE@postenv}%
+% \end{macrocode}
+%
+% Finally we globally define \meta{macro} to contain the collected
+% contents:
+%
+% \begin{macrocode}
+ \expandafter\expandafter\expandafter%
+ \gdef\expandafter\CE@destmacro\expandafter{\the\toks@}%
+ \toks@{}%
+}
+% \end{macrocode}
+% \end{environment}
+%
+%
+%
+%
+% \subsection{Internal environments and macros}
+%
+% We allocate a new |\newwrite| for the processing of a temporary
+% file:
+%
+% \begin{macrocode}
+\newwrite\CE@tmp@out
+% \end{macrocode}
+%
+%
+% \begin{macro}{\CE@get@env@body@start}
+%
+% Starts the collecting of the contents of an environment. (the
+% environment starts immediately after the macro)
+%
+% \begin{macrocode}
+\def\CE@get@env@body@start{%
+ \let\@tempa\CE@get@env@body%
+% \end{macrocode}
+%
+% We may have to gobble leading spaces, therefore we check the first
+% character in the environment:
+%
+% \begin{macrocode}
+ \futurelet\@tempb\CE@get@env@body@start@%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\CE@get@env@body@start@}
+%
+% Support macro for |\CE@get@env@body@start|. Checks if the next token
+% is a space, then calls |\CE@get@env@body@start@@|. Otherwise, the
+% collecting of the environment contents is started.
+%
+% \begin{macrocode}
+\def\CE@get@env@body@start@{%
+% \end{macrocode}
+%
+% |\@sptoken| contains a single space and is defined in
+% \textsf{ltdefns.dtx}:
+%
+% \begin{macrocode}
+ \ifx\@tempb\@sptoken%
+ \expandafter\CE@get@env@body@start@@%
+ \else%
+ \expandafter\CE@get@env@body%
+ \fi%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\CE@get@env@body@start@@}
+%
+% Support macro for |\CE@get@env@body@start@|. Gobbles up any space
+% following the macro, then start the collecting of the environment
+% contents using |\CE@get@env@body|.
+%
+% \begin{macrocode}
+\def\CE@get@env@body@start@@{%
+ \afterassignment\CE@get@env@body%
+ \let\@tempb= %
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\CE@get@env@body}
+%
+% Usage: |\CE@get@env@body| \marg{body} |\end| \marg{envname}.
+%
+% To ensure proper initialization, this macro should not be called
+% directly; instead |\CE@get@env@body@start| should be called.
+%
+% First we change the catcode of |Q| to 3 (math switch) in order to
+% have a really unique character for parameter matching later
+% on.\footnote{Taken from `Around the bend 15'} We do this in a group
+% in order to easily restore the catcode later on and make all macro
+% definitions global:
+%
+% \begin{macrocode}
+\bgroup
+\catcode`\Q=3
+% \end{macrocode}
+%
+% Now we begin the macro:
+%
+% \begin{macrocode}
+\long\gdef\CE@get@env@body#1\end#2{%
+% \end{macrocode}
+%
+% Right at the beginning of the macro, we are at an |\end| (and |#1|
+% contains the contents prior to it). We check if it ends the current
+% environment (|#2| contains the name of the environment ended):
+%
+% \begin{macrocode}
+ \def\@tempb{#2}%
+ \ifx\@tempb\@currenvir%
+% \end{macrocode}
+%
+% \paragraph{Yes, it ends the current environment.} We add the
+% contents to |\toks@| and are done. But we do not add the contents
+% directly as there may be a trailing space left (multiple spaces have
+% been collapsed into one space by \TeX). So we call
+% |\CE@get@env@body@| using delimited parameters (note that |Q| has
+% catcode 3, therefore a normal |Q| is not matched).
+%
+% What exactly is going on here? Suppose we have the text
+%
+% \begin{verbatim}
+% Hello World_
+% \end{verbatim}
+% %
+% \noindent (the |_| denotes the trailing space). Then
+% |\CE@get@env@body@| is called like this:
+%
+% \begin{verbatim}
+% \CE@get@env@body@Hello World Q Q
+% \end{verbatim}
+% %
+% \noindent |\CE@get@env@body@| matches the parameters like this: |#1|
+% is `Hello World'; leaving |_Q| (added by the call from
+% |\CE@get@env@body|) in the input. |\CE@get@env@body@| then calls
+% |\CE@get@env@body@@| using |#1| and |Q|, resulting in the call:
+%
+% \begin{verbatim}
+% \CE@get@env@body@@Hello WorldQ Q
+% \end{verbatim}
+% %
+% \noindent |\CE@get@env@body@@| matches its parameter like this: |#1|
+% is `Hello World' again, and |#2| is the second |Q|.
+%
+% But what happened to the space between the two |Q|s? As |#2| is not
+% a delimited parameter, \TeX\ skips spaces after matching the first
+% |Q| until it reaches the second |Q|, thus gobbling up the space
+% inbetween.\footnote{c.f. \TeX book chapter 20.}
+%
+% \addvspace{\baselineskip}\noindent Now suppose we have the text
+% \begin{verbatim}
+% Hello World
+% \end{verbatim}
+% %
+% \noindent without any trailing space. Then |\CE@get@env@body@| is
+% called like this:
+%
+% \begin{verbatim}
+% \CE@get@env@body@Hello WorldQ Q
+% \end{verbatim}
+% %
+% \noindent |\CE@get@env@body@| matches its parameters like this: |#1|
+% is `Hello WorldQ'. |\CE@get@env@body@| then calls
+% |\CE@get@env@body@@| using |#1| and |Q|, resulting in the call:
+%
+% \begin{verbatim}
+% \CE@get@env@body@@Hello WorldQQ
+% \end{verbatim}
+% %
+% \noindent |\CE@get@env@body@@| matches its parameter like this: |#1|
+% is `Hello World' without the trailing `Q', and |#2| is the second
+% |Q|. The only difference to the situation described above is the
+% missing space between the two |Q|s.
+%
+% Remember that the `Q' is always `Q' with catcode 3, thus no `Q' in
+% the environment contents is matched.
+%
+% \begin{macrocode}
+ \CE@get@env@body@#1Q Q%
+ \def\@tempa{\end{#2}}%
+ \else
+% \end{macrocode}
+%
+% \paragraph{No, it ends another environment.} We add the contents as
+% well as the |\end|\meta{environment} to |\toks@|. Then we continue
+% collecting:
+%
+% \begin{macrocode}
+ \toks@\expandafter{\the\toks@#1\end{#2}}%
+ \fi%
+ \@tempa%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\CE@get@env@body@}
+%
+% Support macro for |\CE@get@env@body|. See |\CE@get@env@body| for
+% explanations.
+%
+% \begin{macrocode}
+\long\gdef\CE@get@env@body@#1 Q{%
+ \CE@get@env@body@@#1Q%
+}
+% \end{macrocode}
+% \end{macro}
+%
+
+% \begin{macro}{\CE@get@env@body@@}
+%
+% Support macro for |\CE@get@env@body@|. See |\CE@get@env@body| for
+% explanations.
+%
+% \begin{macrocode}
+\long\gdef\CE@get@env@body@@#1Q#2{%
+ \toks@\expandafter{\the\toks@#1}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% Finally we end the group, thus restoring the catcode of |Q|:
+%
+% \begin{macrocode}
+\egroup
+% \end{macrocode}
+%
+%
+% \begin{macro}{\CE@meaning}
+%
+% Usage: |\CE@meaning| \marg{macro}.
+%
+% Expands to the meaning of \meta{macro}.
+%
+% \begin{macrocode}
+\long\def\CE@meaning#1{%
+ \expandafter\strip@prefix\meaning#1%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\CE@ensure@opened}
+%
+% Usage: |\CE@ensure@opened| \marg{name}.
+%
+% Ensures that the file for collection \meta{name} is opened.
+%
+% \begin{macrocode}
+\def\CE@ensure@opened#1{%
+ \@ifundefined{ifCE@@#1@open}{%
+ \PackageError{collect}{Collection `#1' has not been defined}{\@ehc}%
+ }{%
+ \csname ifCE@@#1@open\endcsname\else%
+ \expandafter\immediate\expandafter\openout%
+ \csname CE@@#1@out\endcsname=\jobname.#1%
+ \expandafter\global\csname CE@@#1@opentrue\endcsname%
+ \fi%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\CE@ensure@closed}
+%
+% Usage: |\CE@ensure@closed| \marg{name}.
+%
+% Ensures that the file for collection \meta{name} is closed.
+%
+% \begin{macrocode}
+\def\CE@ensure@closed#1{%
+ \@ifundefined{ifCE@@#1@open}{%
+ \PackageError{collect}{Collection `#1' has not been defined}{\@ehc}%
+ }{%
+ \csname ifCE@@#1@open\endcsname%
+ \expandafter\immediate\expandafter\closeout%
+ \csname CE@@#1@out\endcsname%
+ \expandafter\global\csname CE@@#1@openfalse\endcsname%
+ \fi%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \Finale
+% \PrintChanges
+% \PrintIndex
+\endinput \ No newline at end of file