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