summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/mdwtools/mdwlist.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/mdwtools/mdwlist.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/mdwtools/mdwlist.dtx')
-rw-r--r--macros/latex/contrib/mdwtools/mdwlist.dtx756
1 files changed, 756 insertions, 0 deletions
diff --git a/macros/latex/contrib/mdwtools/mdwlist.dtx b/macros/latex/contrib/mdwtools/mdwlist.dtx
new file mode 100644
index 0000000000..40d56f1b95
--- /dev/null
+++ b/macros/latex/contrib/mdwtools/mdwlist.dtx
@@ -0,0 +1,756 @@
+% \begin{meta-comment}
+%
+% $Id: mdwlist.dtx,v 1.1 1996/11/19 20:52:26 mdw Exp $
+%
+% Various list-related things
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwlist.dtx,v $
+% Revision 1.1 1996/11/19 20:52:26 mdw
+% Initial revision
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwlist package -- various list-related things
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{mdwlist}
+%<+package> [1996/05/02 1.1 Various list-related things]
+% \end{meta-comment}
+%
+% \CheckSum{179}
+%% \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 \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{mdwlist}
+\def\defaultdesc{%
+ \desclabelwidth{80pt}%
+ \desclabelstyle\nextlinelabel%
+ \def\makelabel{\bfseries}%
+}
+\newenvironment{cmdlist}
+ {\basedescript{\let\makelabel\cmd}}
+ {\endbasedescript}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% This package provides some vaguely useful list-related commands and
+% environments:
+% \begin{itemize*}
+% \item A way of building \env{description}-like environments.
+% \item Commands for making `compacted' versions of list environments
+% \item A method for suspending and resuming enumerated lists.
+% \end{itemize*}
+%
+% \subsection{Description list handling}
+%
+% Different sorts of description-type lists require different sorts of
+% formatting: I think that's fairly obvious. There are essentially three
+% different attributes which should be changable:
+% \begin{itemize*}
+% \item the indentation of the items being described,
+% \item the handling of labels which don't fit properly, and
+% \item the style used to typeset the label text.
+% \end{itemize*}
+% The first two items should usually be decided for all description-like
+% lists in the document, to ensure consistency of appearance. The last
+% depends much more on the content of the labels.
+%
+% \DescribeEnv{basedescript}
+% The \env{basedescript} environment acts as a `skeleton' for description
+% environments. It takes one argument, which contains declarations to
+% be performed while constructing the list. I'd consider it unusual for
+% the \env{basedescript} environment to be used in the main text: it's
+% intended to be used to build other environments.
+%
+% The declarations which can be used to define description-type environments
+% include all of those which are allowed when setting up a list (see the
+% \LaTeX\ book for information here). Some others, which apply specifically
+% to description lists, are also provided:
+%
+% \begin{itemize}
+%
+% \item \DescribeMacro{\desclabelwidth}
+% The \syntax{"\\desclabelwidth{"<length>"}"} declaration sets labels
+% to be left-aligned, with a standard width of \<length>; the item
+% text is indented by \<length> plus the value of |\labelsep|.
+%
+% \item \DescribeMacro{\desclabelstyle}
+% The label style determines how overlong labels are typeset. A style
+% may be set using the \syntax{"\\desclabelstyle{"<style>"}"}
+% declaration. The following \<style>s are provided:
+% \begin{cmdlist}
+% \item [\nextlinelabel] If the label is too wide to fit next to the
+% first line of text, then it is placed on a line by itself;
+% the main text is started on the next line with the usual
+% indentation.
+% \item [\multilinelabel] The label is typeset in a parbox with the
+% appropriate width; if it won't fit on one line, then the
+% text will be split onto subsequent lines.
+% \item [\pushlabel] If the label is too wide to fit in the space
+% allocated to it, the start of the item's text will be `pushed'
+% over to the right to provide space for the label. This is
+% the standard \LaTeX\ \env{description} behaviour.
+% \end{cmdlist}
+%
+% \item \DescribeMacro{\makelabel}
+% The |\makelabel| command is responsible for typesetting a label.
+% It is given one argument, which is the text given as an argument
+% to the |\item| command; it should typeset it appropriately. The
+% text will then be arranged appropriately according to the chosen
+% label style. This command should be redefined using |\renewcommand|.
+%
+% \end{itemize}
+%
+% \begin{figure}
+% \begin{demo}[w]{Various labelling styles}
+%\begin{basedescript}{\desclabelstyle{\nextlinelabel}}
+%\item [Short label] This is a short item, although it has quite a
+% lot of text attached to it.
+%\item [Slightly longer label text] This is a rather longer piece
+% of text, with a correspondingly slightly longer label.
+%\end{basedescript}
+%\medskip
+%\begin{basedescript}{\desclabelstyle{\multilinelabel}}
+%\item [Short label] This is a short item, although it has quite a
+% lot of text attached to it.
+%\item [Slightly longer label text] This is a rather longer piece
+% of text, with a correspondingly slightly longer label.
+%\end{basedescript}
+%\medskip
+%\begin{basedescript}{\desclabelstyle{\pushlabel}}
+%\item [Short label] This is a short item, although it has quite a
+% lot of text attached to it.
+%\item [Slightly longer label text] This is a rather longer piece
+% of text, with a correspondingly slightly longer label.
+%\end{basedescript}
+% \end{demo}
+% \end{figure}
+%
+% \DescribeMacro{\defaultdesc}
+% To allow document designers to control the global appearance of description
+% lists, the |\defaultdesc| command may be redefined; it is called while
+% setting up a new \env{basedescript} list, before performing the user's
+% declarations. By default, it attempts to emulate the standard \LaTeX\
+% \env{description} environment:\footnote{^^A
+% This is a slightly sanitised version of the real definition, which is
+% given in the implementation section of this document.}
+% \begin{listing}
+%\providecommand{\defaultdesc}{%
+% \desclabelstyle{\pushlabel}%
+% \renewcommand{\makelabel}[1]{\bfseries##1}%
+% \setlength{\labelwidth}{0pt}%
+%}
+% \end{listing}
+% Unfortunately, \LaTeX\ doesn't provide a means for overriding a command
+% which may or may not have been defined yet; in this case, I'd probably
+% recommend using the \TeX\ primitive |\def| to redefine |\defaultdesc|.
+%
+% If you want to redefine the \env{description} environment in terms of
+% the commands in this package, the following method is recommended:
+% \begin{listing}
+%\renewenvironment{description}{%
+% \begin{basedescript}{%
+% \renewcommand{\makelabel}[1]{\bfseries##1}%
+% }%
+%}{%
+% \end{basedescript}%
+%}
+% \end{listing}
+% This ensures that labels are typeset in bold, as is usual, but other
+% properties of the list are determined by the overall document style.
+%
+% \subsection{Compacted lists}
+%
+% \LaTeX\ tends to leave a certain amount of vertical space between list
+% items. While this is normally correct for lists in which the items are
+% several lines long, it tends to look odd if all or almost all the items
+% are only one line long.
+%
+% \DescribeMacro{\makecompactlist}
+% The command
+% \syntax{"\\makecompactlist{"<new-env-name>"}{"<old-env-name>"}"}
+% defines a new environment \<new-env-name> to be a `compacted' version of
+% the existing environment \<old-env-name>; i.e., the two environments are
+% the same except that the compacted version leaves no space between items
+% or paragraphs within the list.
+%
+% \DescribeEnv{itemize*}
+% \DescribeEnv{enumerate*}
+% \DescribeEnv{description*}
+% So that the most common cases are already handled, the package creates
+% compacted $*$-variants of the \env{itemize}, \env{enumerate} and
+% \env{description} environments. These were created using the commands
+% \begin{listing}
+%\makecompactlist{itemize*}{itemize}
+%\makecompactlist{enumerate*}{enumerate}
+%\makecompactlist{description*}{description}
+% \end{listing}
+%
+% Some list environments accept arguments. You can pass an argument to a
+% list environment using an optional argument to its compact variant. For
+% example,
+% \begin{listing}
+%\begin{foolist*}[{someargument}]
+% \end{listing}
+%
+% \subsection{Suspending and resuming list environments}
+%
+% \DescribeMacro{\suspend}
+% \DescribeMacro{\resume}
+% The |\suspend| and |\resume| commands allow you to temporarily end a list
+% environment and then pick it up where you left off. The syntax is fairly
+% simple:
+%
+% \begin{grammar}
+%
+% <suspend-cmd> ::= \[[
+% "\\suspend"
+% \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}"
+% \]]%
+%
+% <resume-cmd> ::= \[[
+% "\\resume"
+% \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}"
+% \begin{stack} \\ "[" <text> "]" \end{stack}
+% \]]%
+%
+% \end{grammar}
+%
+% The \<env-name> is the name of the environment; this will more often than
+% not be the \env{enumerate} environment. The \<name> is a magic name you
+% can use to identify the suspended environment; if you don't specify this,
+% the environment name is used instead.
+%
+% \begin{demo}{Suspended environments}
+%Here's some initial text. It's
+%not very interesting.
+%\begin{enumerate*}
+%\item This is an item.
+%\item This is another.
+%\suspend{enumerate*}
+%Some more commentry text.
+%\resume{enumerate*}
+%\item Another item.
+%\end{enumerate*}
+% \end{demo}
+%
+% You can pass arguments to a resumed list environment through the second
+% optional argument of the |\resume| command. If, for example, you're using
+% David Carlisle's \package{enumerate} package, you could say something like
+% \begin{listing}
+%\begin{enumerate}[\bfseries{Item} i]
+%\item An item
+%\item Another item
+%\suspend{enumerate}
+%Some intervening text.
+%\resume{enumerate}[{[\bfseries{Item} i]}]
+%\item Yet another item
+%\end{enumerate}
+% \end{listing}
+%
+% \implementation
+%
+% \section{Implementation}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \subsection{Description lists}
+%
+% \subsubsection{Label styles}
+%
+% \begin{macro}{\nextlinelabel}
+%
+% The idea here is that if the label is too long to fit in its box, we put
+% it on its own line and start the text of the item on the next. I've
+% used |\sbox| here to capture colour changes properly, even though I have
+% deep moral objections to the use of \LaTeX\ boxing commands. Anyway,
+% I capture the text in box~0 and compare its width to the amount of space
+% I have in the label box. If there's enough, I can just unbox the box;
+% otherwise I build a vbox containing the label text and an empty hbox --
+% |\baselineskip| glue inserted between the two boxes makes sure we get
+% the correct spacing between the two lines, and the vboxness of the vbox
+% ensures that the baseline of my strange thing is the baseline of the
+% \emph{bottom} box. I then bash the vbox on the nose, so as to make its
+% width zero, and leave that as the result. Either way, I then add glue
+% to left align whatever it is I've created.
+%
+% \begin{macrocode}
+\def\nextlinelabel#1{%
+ \sbox\z@{#1}%
+ \ifdim\wd\z@>\labelwidth%
+ \setbox\z@\vbox{\box\z@\hbox{}}%
+ \wd\z@\z@%
+ \box\z@%
+ \else%
+ \unhbox\z@%
+ \fi%
+ \hfil%
+}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\multilinelabel}
+%
+% A different idea -- make the label text wrap around onto the next line if
+% it's too long. This is really easy, actually. I use a parbox to contain
+% the label text, set to be ragged right, because there won't be enough
+% space to do proper justification. There's also a funny hskip there --
+% this is because \TeX\ only hyphenates things it finds sitting \emph{after}
+% glue items. The parbox is top-aligned, so the label text and the item
+% run downwards together. I put the result in box~0, and remove the depth,
+% so as not to make the top line of the item text look really strange.
+%
+% All this leaves a little problem, though: if the item text isn't very long,
+% the label might go further down the page than the main item, and possibly
+% collide with the label below. I must confess that I'm not actually sure
+% how to deal with this possibility, so I just hope it doesn't happen.
+%
+% By the way, I don't have moral objections to |\parbox|.
+%
+% \begin{macrocode}
+\def\multilinelabel#1{%
+ \setbox\z@\hbox{%
+ \parbox[t]\labelwidth{\raggedright\hskip\z@skip#1}%
+ }%
+ \dp\z@\z@%
+ \box\z@%
+ \hfil%
+}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\pushlabel}
+%
+% Now we implement the old style behaviour -- if the label is too wide, we
+% just push the first line of the item further over to the right. This
+% is really very easy indeed -- we just stick some |\hfil| space on the
+% right hand side (to left align if the label comes up too short). The
+% `push' behaviour is handled automatically by \LaTeX's item handling.
+%
+% \begin{macrocode}
+\def\pushlabel#1{{#1}\hfil}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The main environment}
+%
+% \begin{macro}{\desclabelstyle}
+%
+% This is a declaration intended to be used only in the argument to the
+% \env{basedescript} environment. It sets the label style for the list.
+% All we do is take the argument and assign it to a magic control sequence
+% which \env{basedescript} will understand later.
+%
+% \begin{macrocode}
+\def\desclabelstyle#1{\def\desc@labelstyle{#1}}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\desclabelwidth}
+%
+% We set the label width and various other bits of information which will
+% make all the bits of the description line up beautifully. We set
+% |\labelwidth| to the value we're given (using |\setlength|, so that
+% people can use the \package{calc} package if they so wish), and make
+% the |\leftmargin| equal $|\labelwidth|+|\labelsep|$.
+%
+% \begin{macrocode}
+\def\desclabelwidth#1{%
+ \setlength\labelwidth{#1}%
+ \leftmargin\labelwidth%
+ \advance\leftmargin\labelsep%
+}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{basedescript}
+%
+% This is the new description environment. It does almost everything you
+% could want from a description environment, I think. The argument is a
+% collection of declarations to be performed while setting up the list.
+%
+% This environment isn't really intended to be used by users -- it's here
+% so that you can define other description environments in terms of it,
+%
+% The environment is defined in two bits -- the `start' bit here simply
+% starts the list and inserts the user declarations in an appropriate
+% point, although sensible details will be inerted if the argument was
+% empty.
+%
+% \begin{macrocode}
+\def\basedescript#1{%
+% \end{macrocode}
+%
+% We must start the list. If the |\item| command's optional argument is
+% missing, we should just leave a blank space, I think.
+%
+% \begin{macrocode}
+ \list{}{%
+% \end{macrocode}
+%
+% So far, so good. Now put in some default declarations. I'll use a
+% separate macro for this, so that the global appearance of lists can be
+% configured.
+%
+% \begin{macrocode}
+ \defaultdesc%
+% \end{macrocode}
+%
+% Now we do the user's declarations.
+%
+% \begin{macrocode}
+ #1%
+% \end{macrocode}
+%
+% Now set up the other parts of the list. We set |\itemindent| so that the
+% label is up against the current left margin. (The standard version
+% actually leaves the label hanging to the left of the margin by a
+% distance of |\labelsep| for a reason I can't quite comprehend -- there's
+% an |\hspace{\labelsep}| in the standard |\makelabel| to compensate for
+% this. Strange\dots)
+%
+% To make the label start in the right place, the text of the item must
+% start a distance of $|\labelwidth|+|\labelsep|$ from the (pre-list) left
+% hand margin; this means that we must set |\itemindent| to be
+% $|\labelwidth|+|\labelsep|-|\leftmargin|$. Time for some \TeX\ arithmetic.
+%
+% \begin{macrocode}
+ \itemindent\labelwidth%
+ \advance\itemindent\labelsep%
+ \advance\itemindent-\leftmargin%
+% \end{macrocode}
+%
+% Now we must set up the label typesetting. We'll take the |\makelabel|
+% provided by the user, remember it, and then redefine |\makelabel| in
+% terms of the |\desclabelstyle| and the saved |\makelabel|.
+%
+% \begin{macrocode}
+ \let\desc@makelabel\makelabel%
+ \def\makelabel##1{\desc@labelstyle{\desc@makelabel{##1}}}%
+% \end{macrocode}
+%
+% I can't think of anything else which needs doing, so I'll call it a day
+% there.
+%
+% \begin{macrocode}
+ }%
+}
+% \end{macrocode}
+%
+% Now we define the `end-bit' of the environment. Since all we need to do
+% is to close the list, we can be ever-so slightly clever and use |\let|.
+%
+% \begin{macrocode}
+\let\endbasedescript\endlist
+% \end{macrocode}
+%
+% Note that with these definitions, the standard \env{description}
+% environment can be emulated by saying simply:
+% \begin{listing}
+%\renewenvironment{description}{%
+% \begin{basedescript}{}%
+%}{%
+% \end{basedescript}
+%}
+% \end{listing}
+%
+% \end{environment}
+%
+% \begin{macro}{\defaultdesc}
+%
+% Now to set up the standard description appearance. In the absence
+% of any other declarations, the label will `push' the text out the way if
+% the text is too long. The standard |\labelsep| and |\leftmargin| are not
+% our problem. We typeset the label text in bold by default. Also,
+% |\labelwidth| is cleared to 0\,pt, because this is what \LaTeX's usual
+% \env{description} does.
+%
+% \begin{macrocode}
+\providecommand\defaultdesc{%
+ \desclabelstyle\pushlabel%
+ \def\makelabel##1{\bfseries##1}%
+ \labelwidth\z@%
+}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{An example}
+%
+% \begin{environment}{note}
+%
+% The \env{note} environment is a simple application of the general
+% description list shown above. It typesets the label (by default, the
+% text `\textbf{note}') at the left margin, and the note text indented by
+% the width of the label.
+%
+% The code is simple -- we take the environment's argument (which may have
+% been omitted), store it in a box (using |\sbox| again, to handle colour
+% changes correctly), set the label width from the width of the box, and
+% then create a single item containing the label text. The text of the
+% environment then appears in exactly the desired place.
+%
+% I've not used |\newcommand| here, for the following reasons:
+% \begin{itemize}
+%
+% \item I don't like it much, to be honest.
+%
+% \item Until very recently, |\newcommand| only allowed you to define
+% `long' commands, where new paragraphs were allowed to be started
+% in command arguments; this removes a useful check which traps
+% common errors like missing out `|}|' characters. I'd prefer to
+% be compatible with older \LaTeX s than to use the new |\newcommand|
+% which provides a $*$-form to work around this restriction.
+%
+% \end{itemize}
+%
+% \begin{macrocode}
+\def\note{\@ifnextchar[\note@i{\note@i[Note:]}}
+\def\note@i[#1]{%
+ \basedescript{%
+ \sbox\z@{\makelabel{#1}}%
+ \desclabelwidth{\wd\z@}%
+ }%
+ \item[\box\z@]%
+}
+\let\endnote\endbasedescript
+% \end{macrocode}
+%
+% \end{environment}
+%
+%
+% \subsection{Compacted environments}
+%
+% Normal lists tend to have rather too much space between items if all or
+% most of the item texts are one line or less each. We therefore define
+% a macro |\makecompactlist| whuch creates `compacted' versions of existing
+% environments.
+%
+% \begin{macro}{\makecompactlist}
+%
+% We're given two arguments: the name of the new environment to create, and
+% the name of the existing list environment to create.
+%
+% The first thing to do is to ensure that the environment we're creating is
+% actually valid (i.e., it doesn't exist already, and it has a sensible
+% name). We can do this with the internal \LaTeX\ macro |\@ifdefinable|.
+%
+% \begin{macrocode}
+\def\makecompactlist#1#2{%
+ \expandafter\@ifdefinable\csname#1\endcsname%
+ {\makecompactlist@i{#1}{#2}}%
+}
+% \end{macrocode}
+%
+% We also ought to ensure that the other environment already exists. This
+% isn't too tricky. We'll steal \LaTeX's error and message for this.
+%
+% \begin{macrocode}
+\def\makecompactlist@i#1#2{%
+ \@ifundefined{#2}{\me@err{Environment `#2' not defined}\@ehc}{}%
+% \end{macrocode}
+%
+% The main work for starting a compact list is done elsewhere.
+%
+% \begin{macrocode}
+ \@namedef{#1}{\@compact@list{#2}}%
+% \end{macrocode}
+%
+% Now to define the end of the environment; this isn't terribly difficult.
+%
+% \begin{macrocode}
+ \expandafter\let\csname end#1\expandafter\endcsname%
+ \csname end#2\endcsname%
+% \end{macrocode}
+%
+% That's a compacted environment created. Easy, no?
+%
+% \begin{macrocode}
+}
+% \end{macrocode}
+%
+% The general case macro has to try slurping some arguments, calling the
+% underlying environment, and removing vertical space.
+%
+% \begin{macrocode}
+\def\@compact@list#1{\@testopt{\@compact@list@i{#1}}{}}
+\def\@compact@list@i#1[#2]{%
+ \@nameuse{#1}#2%
+ \parskip\z@%
+ \itemsep\z@%
+}%
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{itemize*}
+% \begin{environment}{enumerate*}
+% \begin{environment}{description*}
+%
+% Let's build some compacted environments now. These are easy now that
+% we've done all the work above.
+%
+% \begin{macrocode}
+\makecompactlist{itemize*}{itemize}
+\makecompactlist{enumerate*}{enumerate}
+\makecompactlist{description*}{description}
+% \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+% \end{environment}
+%
+%
+% \subsection{Suspending and resuming lists}
+%
+% This is nowhere near perfect; it relies a lot on the goodwill of the user,
+% although it seems to work fairly well.
+%
+% \begin{macro}{\suspend}
+%
+% The only thing that needs saving here is the list counter, whose name
+% is stored in |\@listctr|. When I get a request to save the counter, I'll
+% build a macro which will restore it when the environment is restored later.
+%
+% The first thing to do is to handle the optional argument. |\@dblarg| will
+% sort this out, giving me a copy of the mandatory argument if there's no
+% optional one provided.
+%
+% \begin{macrocode}
+\def\suspend{\@dblarg\suspend@i}
+% \end{macrocode}
+%
+% That's all we need to do here.
+%
+% \begin{macrocode}
+\def\suspend@i[#1]#2{%
+% \end{macrocode}
+%
+% Now I have a little problem; when I |\end| the environment, it will close
+% off the grouping level, and the counter value will be forgotten. This is
+% bad. I'll store all my definitions into a macro, and build the |\end|
+% command into it; that way, everything will be expanded correctly. This
+% requires the use of |\edef|, which means I must be a little careful.
+%
+% \begin{macrocode}
+ \edef\@tempa{%
+% \end{macrocode}
+%
+% The first thing to do is to end the environment. I don't want |\end|
+% expanded yet, so I'll use |\noexpand|.
+%
+% \begin{macrocode}
+ \noexpand\end{#2}%
+% \end{macrocode}
+%
+% Now I must define the `resume' macro. I'll use |\csname| to build the
+% named identifier into the name, so it won't go wrong (maybe). There's
+% a little fun here to make the control sequence name but not expand it
+% here.
+%
+% \begin{macrocode}
+ \def\expandafter\noexpand\csname resume.#1\endcsname{%
+% \end{macrocode}
+%
+% The counter name is hidden inside |\@listctr|, so the actual counter is
+% called `|\csname c@\@listctr\endcsname|'. I'll use |\the| to read its
+% current value, and assign it to the counter when the macro is used later.
+%
+% \begin{macrocode}
+ \csname c@\@listctr\endcsname\the\csname c@\@listctr\endcsname%
+% \end{macrocode}
+%
+% That's all we need to do there. Now close the macros and run them.
+%
+% \begin{macrocode}
+ }%
+ }%
+ \@tempa%
+}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\resume}
+%
+% Resuming environments is much easier. Since I use |\csname| to build the
+% name, nothing happens if you try to resume environments which weren't
+% suspended. I'll trap this and raise an error. Provide an optional
+% argument for collecting arguments to the target list.
+%
+% \begin{macrocode}
+\def\resume{\@dblarg\resume@i}
+\def\resume@i[#1]#2{\@testopt{\resume@ii{#1}{#2}}{}}
+\def\resume@ii#1#2[#3]{%
+ \begin{#2}#3%
+ \@ifundefined{resume.#1}{\ml@err@resume}{\@nameuse{resume.#1}}%
+}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% That's all there is.
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput