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