@@@ reinstate build-depends on mdwfonts, strayman
[mdwtools] / mdwlist.dtx
1 % \begin{meta-comment} <general public licence>
2 %%
3 %% mdwlist package -- various list-related things
4 %% Copyright (c) 1996, 2002, 2003 Mark Wooding
5 %%
6 %% This file is part of the `mdwtools' LaTeX package collection.
7 %%
8 %% `mdwtools' is free software: you can redistribute it and/or modify it
9 %% under the terms of the GNU General Public License as published by the
10 %% Free Software Foundation; either version 2 of the License, or (at your
11 %% option) any later version.
12 %%
13 %% `mdwtools' is distributed in the hope that it will be useful, but
14 %% WITHOUT ANY WARRANTY; without even the implied warranty of
15 %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 %% General Public License for more details.
17 %%
18 %% You should have received a copy of the GNU General Public License
19 %% along with `mdwtools'. If not, write to the Free Software Foundation,
20 %% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 %%
22 % \end{meta-comment}
23 %
24 % \begin{meta-comment} <Package preambles>
25 %<+package>\NeedsTeXFormat{LaTeX2e}
26 %<+package>\ProvidesPackage{mdwlist}
27 %<+package> [2020/09/06 1.14.0 Various list-related things]
28 % \end{meta-comment}
29 %
30 % \CheckSum{183}
31 %% \CharacterTable
32 %% {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
33 %% 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
34 %% Digits \0\1\2\3\4\5\6\7\8\9
35 %% Exclamation \! Double quote \" Hash (number) \#
36 %% Dollar \$ Percent \% Ampersand \&
37 %% Acute accent \' Left paren \( Right paren \)
38 %% Asterisk \* Plus \+ Comma \,
39 %% Minus \- Point \. Solidus \/
40 %% Colon \: Semicolon \; Less than \<
41 %% Equals \= Greater than \> Question mark \?
42 %% Commercial at \@ Left bracket \[ Backslash \\
43 %% Right bracket \] Circumflex \^ Underscore \_
44 %% Grave accent \` Left brace \{ Vertical bar \|
45 %% Right brace \} Tilde \~}
46 %%
47 %
48 % \begin{meta-comment}
49 %
50 %<*driver>
51 \input{mdwtools}
52 \describespackage{mdwlist}
53 \def\defaultdesc{%
54 \desclabelwidth{80pt}%
55 \desclabelstyle\nextlinelabel%
56 \def\makelabel{\bfseries}%
57 }
58 \newenvironment{cmdlist}
59 {\basedescript{\let\makelabel\cmd}}
60 {\endbasedescript}
61 \mdwdoc
62 %</driver>
63 %
64 % \end{meta-comment}
65 %
66 % \section{User guide}
67 %
68 % This package provides some vaguely useful list-related commands and
69 % environments:
70 % \begin{itemize*}
71 % \item A way of building \env{description}-like environments.
72 % \item Commands for making `compacted' versions of list environments
73 % \item A method for suspending and resuming enumerated lists.
74 % \end{itemize*}
75 %
76 % \subsection{Description list handling}
77 %
78 % Different sorts of description-type lists require different sorts of
79 % formatting: I think that's fairly obvious. There are essentially three
80 % different attributes which should be changable:
81 % \begin{itemize*}
82 % \item the indentation of the items being described,
83 % \item the handling of labels which don't fit properly, and
84 % \item the style used to typeset the label text.
85 % \end{itemize*}
86 % The first two items should usually be decided for all description-like
87 % lists in the document, to ensure consistency of appearance. The last
88 % depends much more on the content of the labels.
89 %
90 % \DescribeEnv{basedescript}
91 % The \env{basedescript} environment acts as a `skeleton' for description
92 % environments. It takes one argument, which contains declarations to
93 % be performed while constructing the list. I'd consider it unusual for
94 % the \env{basedescript} environment to be used in the main text: it's
95 % intended to be used to build other environments.
96 %
97 % The declarations which can be used to define description-type environments
98 % include all of those which are allowed when setting up a list (see the
99 % \LaTeX\ book for information here). Some others, which apply specifically
100 % to description lists, are also provided:
101 %
102 % \begin{itemize}
103 %
104 % \item \DescribeMacro{\desclabelwidth}
105 % The \syntax{"\\desclabelwidth{"<length>"}"} declaration sets labels
106 % to be left-aligned, with a standard width of \<length>; the item
107 % text is indented by \<length> plus the value of |\labelsep|.
108 %
109 % \item \DescribeMacro{\desclabelstyle}
110 % The label style determines how overlong labels are typeset. A style
111 % may be set using the \syntax{"\\desclabelstyle{"<style>"}"}
112 % declaration. The following \<style>s are provided:
113 % \begin{cmdlist}
114 % \item [\nextlinelabel] If the label is too wide to fit next to the
115 % first line of text, then it is placed on a line by itself;
116 % the main text is started on the next line with the usual
117 % indentation.
118 % \item [\multilinelabel] The label is typeset in a parbox with the
119 % appropriate width; if it won't fit on one line, then the
120 % text will be split onto subsequent lines.
121 % \item [\pushlabel] If the label is too wide to fit in the space
122 % allocated to it, the start of the item's text will be `pushed'
123 % over to the right to provide space for the label. This is
124 % the standard \LaTeX\ \env{description} behaviour.
125 % \end{cmdlist}
126 %
127 % \item \DescribeMacro{\makelabel}
128 % The |\makelabel| command is responsible for typesetting a label.
129 % It is given one argument, which is the text given as an argument
130 % to the |\item| command; it should typeset it appropriately. The
131 % text will then be arranged appropriately according to the chosen
132 % label style. This command should be redefined using |\renewcommand|.
133 %
134 % \end{itemize}
135 %
136 % \begin{figure}
137 % \begin{demo}[w]{Various labelling styles}
138 %\begin{basedescript}{\desclabelstyle{\nextlinelabel}}
139 %\item [Short label] This is a short item, although it has quite a
140 % lot of text attached to it.
141 %\item [Slightly longer label text] This is a rather longer piece
142 % of text, with a correspondingly slightly longer label.
143 %\end{basedescript}
144 %\medskip
145 %\begin{basedescript}{\desclabelstyle{\multilinelabel}}
146 %\item [Short label] This is a short item, although it has quite a
147 % lot of text attached to it.
148 %\item [Slightly longer label text] This is a rather longer piece
149 % of text, with a correspondingly slightly longer label.
150 %\end{basedescript}
151 %\medskip
152 %\begin{basedescript}{\desclabelstyle{\pushlabel}}
153 %\item [Short label] This is a short item, although it has quite a
154 % lot of text attached to it.
155 %\item [Slightly longer label text] This is a rather longer piece
156 % of text, with a correspondingly slightly longer label.
157 %\end{basedescript}
158 % \end{demo}
159 % \end{figure}
160 %
161 % \DescribeMacro{\defaultdesc}
162 % To allow document designers to control the global appearance of description
163 % lists, the |\defaultdesc| command may be redefined; it is called while
164 % setting up a new \env{basedescript} list, before performing the user's
165 % declarations. By default, it attempts to emulate the standard \LaTeX\
166 % \env{description} environment:\footnote{^^A
167 % This is a slightly sanitised version of the real definition, which is
168 % given in the implementation section of this document.}
169 % \begin{listing}
170 %\providecommand{\defaultdesc}{%
171 % \desclabelstyle{\pushlabel}%
172 % \renewcommand{\makelabel}[1]{\bfseries##1}%
173 % \setlength{\labelwidth}{0pt}%
174 %}
175 % \end{listing}
176 % Unfortunately, \LaTeX\ doesn't provide a means for overriding a command
177 % which may or may not have been defined yet; in this case, I'd probably
178 % recommend using the \TeX\ primitive |\def| to redefine |\defaultdesc|.
179 %
180 % If you want to redefine the \env{description} environment in terms of
181 % the commands in this package, the following method is recommended:
182 % \begin{listing}
183 %\renewenvironment{description}{%
184 % \begin{basedescript}{%
185 % \renewcommand{\makelabel}[1]{\bfseries##1}%
186 % }%
187 %}{%
188 % \end{basedescript}%
189 %}
190 % \end{listing}
191 % This ensures that labels are typeset in bold, as is usual, but other
192 % properties of the list are determined by the overall document style.
193 %
194 % \subsection{Compacted lists}
195 %
196 % \LaTeX\ tends to leave a certain amount of vertical space between list
197 % items. While this is normally correct for lists in which the items are
198 % several lines long, it tends to look odd if all or almost all the items
199 % are only one line long.
200 %
201 % \DescribeMacro{\makecompactlist}
202 % The command
203 % \syntax{"\\makecompactlist{"<new-env-name>"}{"<old-env-name>"}"}
204 % defines a new environment \<new-env-name> to be a `compacted' version of
205 % the existing environment \<old-env-name>; i.e., the two environments are
206 % the same except that the compacted version leaves no space between items
207 % or paragraphs within the list.
208 %
209 % \DescribeEnv{itemize*}
210 % \DescribeEnv{enumerate*}
211 % \DescribeEnv{description*}
212 % So that the most common cases are already handled, the package creates
213 % compacted $*$-variants of the \env{itemize}, \env{enumerate} and
214 % \env{description} environments. These were created using the commands
215 % \begin{listing}
216 %\makecompactlist{itemize*}{itemize}
217 %\makecompactlist{enumerate*}{enumerate}
218 %\makecompactlist{description*}{description}
219 % \end{listing}
220 %
221 % Some list environments accept arguments. You can pass an argument to a
222 % list environment using an optional argument to its compact variant. For
223 % example,
224 % \begin{listing}
225 %\begin{foolist*}[{someargument}]
226 % \end{listing}
227 %
228 % \subsection{Suspending and resuming list environments}
229 %
230 % \DescribeMacro{\suspend}
231 % \DescribeMacro{\resume}
232 % The |\suspend| and |\resume| commands allow you to temporarily end a list
233 % environment and then pick it up where you left off. The syntax is fairly
234 % simple:
235 %
236 % \begin{grammar}
237 %
238 % <suspend-cmd> ::= \[[
239 % "\\suspend"
240 % \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}"
241 % \]]%
242 %
243 % <resume-cmd> ::= \[[
244 % "\\resume"
245 % \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}"
246 % \begin{stack} \\ "[" <text> "]" \end{stack}
247 % \]]%
248 %
249 % \end{grammar}
250 %
251 % The \<env-name> is the name of the environment; this will more often than
252 % not be the \env{enumerate} environment. The \<name> is a magic name you
253 % can use to identify the suspended environment; if you don't specify this,
254 % the environment name is used instead.
255 %
256 % \begin{demo}{Suspended environments}
257 %Here's some initial text. It's
258 %not very interesting.
259 %\begin{enumerate*}
260 %\item This is an item.
261 %\item This is another.
262 %\suspend{enumerate*}
263 %Some more commentry text.
264 %\resume{enumerate*}
265 %\item Another item.
266 %\end{enumerate*}
267 % \end{demo}
268 %
269 % You can pass arguments to a resumed list environment through the second
270 % optional argument of the |\resume| command. If, for example, you're using
271 % David Carlisle's \package{enumerate} package, you could say something like
272 % \begin{listing}
273 %\begin{enumerate}[\bfseries{Item} i]
274 %\item An item
275 %\item Another item
276 %\suspend{enumerate}
277 %Some intervening text.
278 %\resume{enumerate}[{[\bfseries{Item} i]}]
279 %\item Yet another item
280 %\end{enumerate}
281 % \end{listing}
282 %
283 % \implementation
284 %
285 % \section{Implementation}
286 %
287 % \begin{macrocode}
288 %<*package>
289 % \end{macrocode}
290 %
291 % \subsection{Description lists}
292 %
293 % \subsubsection{Label styles}
294 %
295 % \begin{macro}{\nextlinelabel}
296 %
297 % The idea here is that if the label is too long to fit in its box, we put
298 % it on its own line and start the text of the item on the next. I've
299 % used |\sbox| here to capture colour changes properly, even though I have
300 % deep moral objections to the use of \LaTeX\ boxing commands. Anyway,
301 % I capture the text in box~0 and compare its width to the amount of space
302 % I have in the label box. If there's enough, I can just unbox the box;
303 % otherwise I build a vbox containing the label text and an empty hbox --
304 % |\baselineskip| glue inserted between the two boxes makes sure we get
305 % the correct spacing between the two lines, and the vboxness of the vbox
306 % ensures that the baseline of my strange thing is the baseline of the
307 % \emph{bottom} box. I then bash the vbox on the nose, so as to make its
308 % width zero, and leave that as the result. Either way, I then add glue
309 % to left align whatever it is I've created.
310 %
311 % \begin{macrocode}
312 \def\nextlinelabel#1{%
313 \sbox\z@{#1}%
314 \ifdim\wd\z@>\labelwidth%
315 \setbox\z@\vbox{\box\z@\hbox{}}%
316 \wd\z@\z@%
317 \box\z@%
318 \else%
319 \unhbox\z@%
320 \fi%
321 \hfil%
322 }
323 % \end{macrocode}
324 %
325 % \end{macro}
326 %
327 % \begin{macro}{\multilinelabel}
328 %
329 % A different idea -- make the label text wrap around onto the next line if
330 % it's too long. This is really easy, actually. I use a parbox to contain
331 % the label text, set to be ragged right, because there won't be enough
332 % space to do proper justification. There's also a funny hskip there --
333 % this is because \TeX\ only hyphenates things it finds sitting \emph{after}
334 % glue items. The parbox is top-aligned, so the label text and the item
335 % run downwards together. I put the result in box~0, and remove the depth,
336 % so as not to make the top line of the item text look really strange.
337 %
338 % All this leaves a little problem, though: if the item text isn't very long,
339 % the label might go further down the page than the main item, and possibly
340 % collide with the label below. I must confess that I'm not actually sure
341 % how to deal with this possibility, so I just hope it doesn't happen.
342 %
343 % By the way, I don't have moral objections to |\parbox|.
344 %
345 % \begin{macrocode}
346 \def\multilinelabel#1{%
347 \setbox\z@\hbox{%
348 \parbox[t]\labelwidth{\raggedright\hskip\z@skip#1}%
349 }%
350 \dp\z@\z@%
351 \box\z@%
352 \hfil%
353 }
354 % \end{macrocode}
355 %
356 % \end{macro}
357 %
358 % \begin{macro}{\pushlabel}
359 %
360 % Now we implement the old style behaviour -- if the label is too wide, we
361 % just push the first line of the item further over to the right. This
362 % is really very easy indeed -- we just stick some |\hfil| space on the
363 % right hand side (to left align if the label comes up too short). The
364 % `push' behaviour is handled automatically by \LaTeX's item handling.
365 %
366 % \begin{macrocode}
367 \def\pushlabel#1{{#1}\hfil}
368 % \end{macrocode}
369 %
370 % \end{macro}
371 %
372 % \subsubsection{The main environment}
373 %
374 % \begin{macro}{\desclabelstyle}
375 %
376 % This is a declaration intended to be used only in the argument to the
377 % \env{basedescript} environment. It sets the label style for the list.
378 % All we do is take the argument and assign it to a magic control sequence
379 % which \env{basedescript} will understand later.
380 %
381 % \begin{macrocode}
382 \def\desclabelstyle#1{\def\desc@labelstyle{#1}}
383 % \end{macrocode}
384 %
385 % \end{macro}
386 %
387 % \begin{macro}{\desclabelwidth}
388 %
389 % We set the label width and various other bits of information which will
390 % make all the bits of the description line up beautifully. We set
391 % |\labelwidth| to the value we're given (using |\setlength|, so that
392 % people can use the \package{calc} package if they so wish), and make
393 % the |\leftmargin| equal $|\labelwidth|+|\labelsep|$.
394 %
395 % \begin{macrocode}
396 \def\desclabelwidth#1{%
397 \setlength\labelwidth{#1}%
398 \leftmargin\labelwidth%
399 \advance\leftmargin\labelsep%
400 }
401 % \end{macrocode}
402 %
403 % \end{macro}
404 %
405 % \begin{environment}{basedescript}
406 %
407 % This is the new description environment. It does almost everything you
408 % could want from a description environment, I think. The argument is a
409 % collection of declarations to be performed while setting up the list.
410 %
411 % This environment isn't really intended to be used by users -- it's here
412 % so that you can define other description environments in terms of it,
413 %
414 % The environment is defined in two bits -- the `start' bit here simply
415 % starts the list and inserts the user declarations in an appropriate
416 % point, although sensible details will be inerted if the argument was
417 % empty.
418 %
419 % \begin{macrocode}
420 \def\basedescript#1{%
421 % \end{macrocode}
422 %
423 % We must start the list. If the |\item| command's optional argument is
424 % missing, we should just leave a blank space, I think.
425 %
426 % \begin{macrocode}
427 \list{}{%
428 % \end{macrocode}
429 %
430 % So far, so good. Now put in some default declarations. I'll use a
431 % separate macro for this, so that the global appearance of lists can be
432 % configured.
433 %
434 % \begin{macrocode}
435 \defaultdesc%
436 % \end{macrocode}
437 %
438 % Now we do the user's declarations.
439 %
440 % \begin{macrocode}
441 #1%
442 % \end{macrocode}
443 %
444 % Now set up the other parts of the list. We set |\itemindent| so that the
445 % label is up against the current left margin. (The standard version
446 % actually leaves the label hanging to the left of the margin by a
447 % distance of |\labelsep| for a reason I can't quite comprehend -- there's
448 % an |\hspace{\labelsep}| in the standard |\makelabel| to compensate for
449 % this. Strange\dots)
450 %
451 % To make the label start in the right place, the text of the item must
452 % start a distance of $|\labelwidth|+|\labelsep|$ from the (pre-list) left
453 % hand margin; this means that we must set |\itemindent| to be
454 % $|\labelwidth|+|\labelsep|-|\leftmargin|$. Time for some \TeX\ arithmetic.
455 %
456 % \begin{macrocode}
457 \itemindent\labelwidth%
458 \advance\itemindent\labelsep%
459 \advance\itemindent-\leftmargin%
460 % \end{macrocode}
461 %
462 % Now we must set up the label typesetting. We'll take the |\makelabel|
463 % provided by the user, remember it, and then redefine |\makelabel| in
464 % terms of the |\desclabelstyle| and the saved |\makelabel|.
465 %
466 % \begin{macrocode}
467 \let\desc@makelabel\makelabel%
468 \def\makelabel##1{\desc@labelstyle{\desc@makelabel{##1}}}%
469 % \end{macrocode}
470 %
471 % I can't think of anything else which needs doing, so I'll call it a day
472 % there.
473 %
474 % \begin{macrocode}
475 }%
476 }
477 % \end{macrocode}
478 %
479 % Now we define the `end-bit' of the environment. Since all we need to do
480 % is to close the list, we can be ever-so slightly clever and use |\let|.
481 %
482 % \begin{macrocode}
483 \let\endbasedescript\endlist
484 % \end{macrocode}
485 %
486 % Note that with these definitions, the standard \env{description}
487 % environment can be emulated by saying simply:
488 % \begin{listing}
489 %\renewenvironment{description}{%
490 % \begin{basedescript}{}%
491 %}{%
492 % \end{basedescript}
493 %}
494 % \end{listing}
495 %
496 % \end{environment}
497 %
498 % \begin{macro}{\defaultdesc}
499 %
500 % Now to set up the standard description appearance. In the absence
501 % of any other declarations, the label will `push' the text out the way if
502 % the text is too long. The standard |\labelsep| and |\leftmargin| are not
503 % our problem. We typeset the label text in bold by default. Also,
504 % |\labelwidth| is cleared to 0\,pt, because this is what \LaTeX's usual
505 % \env{description} does.
506 %
507 % \begin{macrocode}
508 \providecommand\defaultdesc{%
509 \desclabelstyle\pushlabel%
510 \def\makelabel##1{\bfseries##1}%
511 \labelwidth\z@%
512 }
513 % \end{macrocode}
514 %
515 % \end{macro}
516 %
517 % \subsubsection{An example}
518 %
519 % \begin{environment}{note}
520 %
521 % The \env{note} environment is a simple application of the general
522 % description list shown above. It typesets the label (by default, the
523 % text `\textbf{note}') at the left margin, and the note text indented by
524 % the width of the label.
525 %
526 % The code is simple -- we take the environment's argument (which may have
527 % been omitted), store it in a box (using |\sbox| again, to handle colour
528 % changes correctly), set the label width from the width of the box, and
529 % then create a single item containing the label text. The text of the
530 % environment then appears in exactly the desired place.
531 %
532 % I've not used |\newcommand| here, for the following reasons:
533 % \begin{itemize}
534 %
535 % \item I don't like it much, to be honest.
536 %
537 % \item Until very recently, |\newcommand| only allowed you to define
538 % `long' commands, where new paragraphs were allowed to be started
539 % in command arguments; this removes a useful check which traps
540 % common errors like missing out `|}|' characters. I'd prefer to
541 % be compatible with older \LaTeX s than to use the new |\newcommand|
542 % which provides a $*$-form to work around this restriction.
543 %
544 % \end{itemize}
545 %
546 % \begin{macrocode}
547 \ifx\note\@@undefined
548 \def\note{\@ifnextchar[\note@i{\note@i[Note]}}
549 \def\note@i[#1]{%
550 \basedescript{%
551 \sbox\z@{\makelabel{#1}}%
552 \desclabelwidth{\wd\z@}%
553 }%
554 \item[\box\z@]%
555 }
556 \let\endnote\endbasedescript
557 \fi
558 % \end{macrocode}
559 %
560 % \end{environment}
561 %
562 %
563 % \subsection{Compacted environments}
564 %
565 % Normal lists tend to have rather too much space between items if all or
566 % most of the item texts are one line or less each. We therefore define
567 % a macro |\makecompactlist| whuch creates `compacted' versions of existing
568 % environments.
569 %
570 % \begin{macro}{\makecompactlist}
571 %
572 % We're given two arguments: the name of the new environment to create, and
573 % the name of the existing list environment to create.
574 %
575 % The first thing to do is to ensure that the environment we're creating is
576 % actually valid (i.e., it doesn't exist already, and it has a sensible
577 % name). We can do this with the internal \LaTeX\ macro |\@ifdefinable|.
578 %
579 % \begin{macrocode}
580 \def\makecompactlist#1#2{%
581 \expandafter\@ifdefinable\csname#1\endcsname%
582 {\makecompactlist@i{#1}{#2}}%
583 }
584 % \end{macrocode}
585 %
586 % We also ought to ensure that the other environment already exists. This
587 % isn't too tricky. We'll steal \LaTeX's error and message for this.
588 %
589 % \begin{macrocode}
590 \def\makecompactlist@i#1#2{%
591 \@ifundefined{#2}{\me@err{Environment `#2' not defined}\@ehc}{}%
592 % \end{macrocode}
593 %
594 % The main work for starting a compact list is done elsewhere.
595 %
596 % \begin{macrocode}
597 \@namedef{#1}{\@compact@list{#2}}%
598 % \end{macrocode}
599 %
600 % Now to define the end of the environment; this isn't terribly difficult.
601 %
602 % \begin{macrocode}
603 \expandafter\let\csname end#1\expandafter\endcsname%
604 \csname end#2\endcsname%
605 % \end{macrocode}
606 %
607 % That's a compacted environment created. Easy, no?
608 %
609 % \begin{macrocode}
610 }
611 % \end{macrocode}
612 %
613 % The general case macro has to try slurping some arguments, calling the
614 % underlying environment, and removing vertical space.
615 %
616 % \begin{macrocode}
617 \def\@compact@list#1{\@testopt{\@compact@list@i{#1}}{}}
618 \def\@compact@list@i#1[#2]{%
619 \@nameuse{#1}#2%
620 \parskip\z@%
621 \itemsep\z@%
622 }%
623 % \end{macrocode}
624 %
625 % \end{macro}
626 %
627 % \begin{environment}{itemize*}
628 % \begin{environment}{enumerate*}
629 % \begin{environment}{description*}
630 %
631 % Let's build some compacted environments now. These are easy now that
632 % we've done all the work above.
633 %
634 % \begin{macrocode}
635 \makecompactlist{itemize*}{itemize}
636 \makecompactlist{enumerate*}{enumerate}
637 \makecompactlist{description*}{description}
638 % \end{macrocode}
639 %
640 % \end{environment}
641 % \end{environment}
642 % \end{environment}
643 %
644 %
645 % \subsection{Suspending and resuming lists}
646 %
647 % This is nowhere near perfect; it relies a lot on the goodwill of the user,
648 % although it seems to work fairly well.
649 %
650 % \begin{macro}{\suspend}
651 %
652 % The only thing that needs saving here is the list counter, whose name
653 % is stored in |\@listctr|. When I get a request to save the counter, I'll
654 % build a macro which will restore it when the environment is restored later.
655 %
656 % The first thing to do is to handle the optional argument. |\@dblarg| will
657 % sort this out, giving me a copy of the mandatory argument if there's no
658 % optional one provided.
659 %
660 % \begin{macrocode}
661 \def\suspend{\@dblarg\suspend@i}
662 % \end{macrocode}
663 %
664 % That's all we need to do here.
665 %
666 % \begin{macrocode}
667 \def\suspend@i[#1]#2{%
668 % \end{macrocode}
669 %
670 % Now I have a little problem; when I |\end| the environment, it will close
671 % off the grouping level, and the counter value will be forgotten. This is
672 % bad. I'll store all my definitions into a macro, and build the |\end|
673 % command into it; that way, everything will be expanded correctly. This
674 % requires the use of |\edef|, which means I must be a little careful.
675 %
676 % \begin{macrocode}
677 \edef\@tempa{%
678 % \end{macrocode}
679 %
680 % The first thing to do is to end the environment. I don't want |\end|
681 % expanded yet, so I'll use |\noexpand|.
682 %
683 % \begin{macrocode}
684 \noexpand\end{#2}%
685 % \end{macrocode}
686 %
687 % Now I must define the `resume' macro. I'll use |\csname| to build the
688 % named identifier into the name, so it won't go wrong (maybe). There's
689 % a little fun here to make the control sequence name but not expand it
690 % here.
691 %
692 % \begin{macrocode}
693 \def\expandafter\noexpand\csname resume.#1\endcsname{%
694 % \end{macrocode}
695 %
696 % The counter name is hidden inside |\@listctr|, so the actual counter is
697 % called `|\csname c@\@listctr\endcsname|'. I'll use |\the| to read its
698 % current value, and assign it to the counter when the macro is used later.
699 %
700 % \begin{macrocode}
701 \csname c@\@listctr\endcsname\the\csname c@\@listctr\endcsname%
702 % \end{macrocode}
703 %
704 % That's all we need to do there. Now close the macros and run them.
705 %
706 % \begin{macrocode}
707 }%
708 }%
709 \@tempa%
710 }
711 % \end{macrocode}
712 %
713 % \end{macro}
714 %
715 % \begin{macro}{\resume}
716 %
717 % Resuming environments is much easier. Since I use |\csname| to build the
718 % name, nothing happens if you try to resume environments which weren't
719 % suspended. I'll trap this and raise an error. Provide an optional
720 % argument for collecting arguments to the target list.
721 %
722 % \begin{macrocode}
723 \def\resume{\@dblarg\resume@i}
724 \def\resume@i[#1]#2{\@testopt{\resume@ii{#1}{#2}}{}}
725 \def\resume@ii#1#2[#3]{%
726 \begin{#2}#3%
727 \@ifundefined{resume.#1}{\ml@err@resume}{\@nameuse{resume.#1}}%
728 }
729 % \end{macrocode}
730 %
731 % \end{macro}
732 %
733 % That's all there is.
734 %
735 % \begin{macrocode}
736 %</package>
737 % \end{macrocode}
738 %
739 % \hfill Mark Wooding, \today
740 %
741 % \Finale
742 %
743 \endinput