chiark / gitweb /
Colour support! Better rule attribute handling. Lots of new hooks.
[mdwtools] / doafter.dtx
1 % \begin{meta-comment}
2 %
3 % $Id: doafter.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
4 %
5 % Insert tokens to be read after a group has been processed
6 %
7 % (c) 1996 Peter Schmitt and Mark Wooding
8 %
9 %----- Revision history -----------------------------------------------------
10 %
11 % $Log: doafter.dtx,v $
12 % Revision 1.1  2002/02/03 20:49:03  mdw
13 % Checkin for new build system.
14 %
15 % Revision 1.2  1996/11/19 20:49:08  mdw
16 % Entered into RCS
17 %
18 %
19 % \end{meta-comment}
20 %
21 % \begin{meta-comment} <general public licence>
22 %%
23 %% doafter package -- insert a token really after a group
24 %% Copyright (c) 1996 Peter Schmitt and Mark Wooding
25 %<*package>
26 %%
27 %% This program is free software; you can redistribute it and/or modify
28 %% it under the terms of the GNU General Public License as published by
29 %% the Free Software Foundation; either version 2 of the License, or
30 %% (at your option) any later version.
31 %%
32 %% This program is distributed in the hope that it will be useful,
33 %% but WITHOUT ANY WARRANTY; without even the implied warranty of
34 %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35 %% GNU General Public License for more details.
36 %%
37 %% You should have received a copy of the GNU General Public License
38 %% along with this program; if not, write to the Free Software
39 %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40 %</package>
41 %%
42 % \end{meta-comment}
43 %
44 % \begin{meta-comment} <Package preamble>
45 %<+latex2e>\NeedsTeXFormat{LaTeX2e}
46 %<+latex2e>\ProvidesPackage{doafter}
47 %<+latex2e>                [1996/05/08 1.2 Aftergroup hacking (PS/MDW)]
48 % \end{meta-comment}
49 %
50 % \CheckSum{259}
51 %\iffalse
52 %<*package>
53 %\fi
54 %% \CharacterTable
55 %%  {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
56 %%   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
57 %%   Digits        \0\1\2\3\4\5\6\7\8\9
58 %%   Exclamation   \!     Double quote  \"     Hash (number) \#
59 %%   Dollar        \$     Percent       \%     Ampersand     \&
60 %%   Acute accent  \'     Left paren    \(     Right paren   \)
61 %%   Asterisk      \*     Plus          \+     Comma         \,
62 %%   Minus         \-     Point         \.     Solidus       \/
63 %%   Colon         \:     Semicolon     \;     Less than     \<
64 %%   Equals        \=     Greater than  \>     Question mark \?
65 %%   Commercial at \@     Left bracket  \[     Backslash     \\
66 %%   Right bracket \]     Circumflex    \^     Underscore    \_
67 %%   Grave accent  \`     Left brace    \{     Vertical bar  \|
68 %%   Right brace   \}     Tilde         \~}
69 %%
70 %\iffalse
71 %</package>
72 %\fi
73 %
74 % \begin{meta-comment} <driver>
75 %
76 %<*driver>
77 \input{mdwtools}
78 \describespackage{doafter}
79 \author{Peter Schmitt\thanks{%
80   Peter came up with the basic implementation after I posed the problem
81   in the \texttt{comp.text.tex} newsgroup.  I fixed some really piddly little
82   things, to improve it a bit, wrote the documentation, and turned the code
83   into a nice \package{doc}ced package.  Then Peter gave me an updated
84   version, and I upgraded this from memory.  Then he gave me some more tweaks
85   which I haven't incorporated.}
86   \and Mark Wooding}
87 \def\author#1{}
88 \mdwdoc
89 %</driver>
90 %
91 % \end{meta-comment}
92 %
93 % \section{Description}
94 %
95 % \subsection{What it's all about}
96 %
97 % \DescribeMacro{\doafter}
98 % It's common for the \TeX\ primitive |\aftergroup| to be used to `tidy up'
99 % after a group.  For example, \LaTeX's colour handling uses this to insert
100 % appropriate |\special|s when the scope of a colour change ends.  This
101 % causes several problems, though; for example, extra grouping must be added
102 % within boxes to ensure that the |\special|s don't `leak' out of their box
103 % and appear in odd places in the document.  \LaTeX\ usually solves this
104 % problem by reading the box contents as an argument, although this isn't
105 % particularly desirable.  The |\doafter| macro provided here will solve the
106 % problem in a different way, by allowing a macro to regain control after
107 % all the |\aftergroup| things have been processed.
108 %
109 % The macro works like this:
110 % \begin{grammar}
111 % <doafter-cmd> ::= \[[
112 %   "\\doafter" <token> <group>
113 % \]]
114 % \end{grammar}
115 % The \<token> can be any token you like, except an explicit braces, since
116 % it's read as an undelimited macro argument.  The \<group> is a normal
117 % \TeX\ group, surrounded by either implicit or explicit braces, or by
118 % |\begingroup| and |\endgroup| tokens.  Once the final closing token of the
119 % \<group> is read, and any tokens saved up by |\aftergroup| have been
120 % processed, the \<token> is inserted and processed.  Under normal
121 % circumstances, this will be a macro.
122 %
123 % There are some subtle problems with the current implementation, which you
124 % may need to be aware of:
125 %
126 % \begin{itemize}
127 %
128 % \item Since we're inserting things after all the |\aftergroup| tokens,
129 %       those tokens might read something they're not expecting if they try
130 %       to look ahead at the text after the group (e.g., with |\futurelet|).
131 %       This is obviously totally unavoidable.
132 %
133 % \item Implicit braces (like |\bgroup| and |\egroup|) inserted using
134 %       |\aftergroup| may be turned into \emph{explicit} $|{|_1$ and $|}|_2$
135 %       characters within a |\doafter| group.  This can cause probems under
136 %       very specialised circumstances.  The names |\bgroup| and |\egroup|
137 %       are treated specially, and they will work normally (remaining as
138 %       implicit braces).  This should minimise problems caused by this
139 %       slight difference.  (This only applies to the last |\aftergroup|
140 %       token in a group.)
141 %
142 % \item To handle the |\aftergroup| tokens properly, |\doafter| has to insert
143 %       some |\aftergroup| tokens of its own.  It will then process the
144 %       other tokens some more, and set them up to be read again.  This does
145 %       mean that after the group ends, some assignments and other `stomach
146 %       operations' will be performed, which may cause problems in
147 %       alignments and similar places.
148 %
149 % \end{itemize}
150 %
151 %
152 % \subsection{Package options}
153 %
154 % There are a fair few \textsf{docstrip} options provided by this packge:
155 %
156 % \begin{description}
157 % \item [driver] extracts the documentation driver.  This isn't usually
158 %       necessary.
159 % \item [package] extracts the code as a standalone package, formatted for
160 %       either \LaTeXe\ or Plain~\TeX.
161 % \item [latex2e] inserts extra identification code for a \LaTeXe\ package.
162 % \item [plain] inserts some extra code for a Plain \TeX\ package.
163 % \item [macro] just extracts the raw code, for inclusion in another package.
164 % \item [test] extracts some code for testing the current implementation.
165 % \end{description}
166 %
167 %
168 % \implementation
169 %
170 % \section{Implementation}
171 %
172 % \subsection{The main macro}
173 %
174 % We start outputting code here.  If this is a Plain~\TeX\ package, we must
175 % make \lit{@} into a letter.
176 %
177 %    \begin{macrocode}
178 %<*macro|package>
179 %<+plain>\catcode`\@=11
180 %    \end{macrocode}
181 %
182 % \begin{macro}{\doafter}
183 %
184 % The idea is to say \syntax{"\\doafter" <token> <group>} and expect the
185 % \synt{token} to be processed after the group has finished its stuff,
186 % even if it contains |\aftergroup| things.  My eternal gratitude goes to
187 % Peter Schmitt, who came up with most of the solution implemented here;
188 % I've just tidied up some very minor niggles and things later.
189 %
190 % Let's start with some preamble.  I'll save the (hopefully) primitive
191 % |\aftergroup| in a different token.
192 %
193 %    \begin{macrocode}
194 \let\@@aftergroup\aftergroup
195 %    \end{macrocode}
196 %
197 % Now to define the `user' interface.  It takes a normal undelimited
198 % argument, although this must be a single token; otherwise eveything will
199 % go wrong.  It assumes that the token following is some kind of group
200 % opening thing (an explicit or implicit character with catcode~1, or
201 % a |\begingroup| token).  To make this work, I'll save the token,
202 % together with an |\@@aftergroup| (to save an |\expandafter| later) in
203 % a temporary macro which no-one will mind me using, and then look ahead at
204 % the beginning-group token.
205 %
206 %    \begin{macrocode}
207 \def\doafter#1{%
208   \def\@tempa{\@@aftergroup#1}%
209   \afterassignment\doafter@i\let\@let@token%
210 }
211 %    \end{macrocode}
212 %
213 % I now have the token in |\@let@token|, so I'll put that in.  I'll then
214 % make |\aftergroup| do my thing rather than the normal thing, and queue
215 % the tokens |\@prepare@after| and the |\doafter| argument for later use.
216 %
217 %    \begin{macrocode}
218 \def\doafter@i{%
219   \@let@token%
220   \let\aftergroup\@my@aftergroup%
221   \@@aftergroup\@prepare@after\@tempa%
222 }
223 %    \end{macrocode}
224 %
225 % \end{macro}
226 %
227 % \begin{macro}{\@my@aftergroup}
228 %
229 % Now the cleverness begins.  We keep two macros (Peter's original used
230 % count registers) which keep counts of the numbers of |\aftergroup|s,
231 % both locally and globally.  Let's call the local counter~$n$ and the
232 % global one $N$.  Every time we get a call to our |\aftergroup| hack,
233 % we set~$n := n+1$ and~$N := n$, and leave the token given to us for later
234 % processing.  When we actually process an |\aftergroup| token properly,
235 % set~$N := N-1$ to indicate that it's been handled; when they're all done,
236 % we'll have $N=n$, which is exactly what we'd have if there weren't any
237 % to begin with.
238 %
239 %    \begin{macrocode}
240 \def\ag@cnt@local{0 }
241 \let\ag@cnt@global\ag@cnt@local
242 %    \end{macrocode}
243 %
244 % Now we come to the definition of my version of |\aftergroup|.  I'll just
245 % add the token |\@after@token| before every |\aftergroup| token I find.
246 % This means there's two calls to |\aftergroup| for every one the user makes,
247 % but these things aren't all that common, so it's OK really.  I'll also
248 % bump the local counter, and synchronise them.
249 %
250 %    \begin{macrocode}
251 \def\@my@aftergroup{%
252   \begingroup%
253     \count@\ag@cnt@local%
254     \advance\count@\@ne%
255     \xdef\ag@cnt@global{\the\count@\space}%
256   \endgroup%
257   \let\ag@cnt@local\ag@cnt@global%
258   \@@aftergroup\@after@token\@@aftergroup%
259 }
260 %    \end{macrocode}
261 %
262 % \end{macro}
263 %
264 % Now what does |\@after@token| we inserted above actually do?  Well, this
265 % is more exciting.  There are actually two different variants of the
266 % macro, which are used at different times.
267 %
268 % \begin{macro}{\@after@token}
269 %
270 % The default |\@after@token| starts a group, which will `catch'
271 % |\aftergroup| tokens which I throw at it.  I put the two counters into
272 % some scratch count registers.  (There's a slight problem here: Plain \TeX\
273 % only gives us one.  For the sake of evilness I'll use |\clubpenalty| as the
274 % other one.  Eeeek.)  I then redefine |\@after@token| to the second
275 % variant, and execute it.  The |\@start@after@group| macro starts the
276 % group, because this code is shared with |\@prepare@after| below.
277 %
278 %    \begin{macrocode}
279 \def\@after@token{%
280   \@start@after@group%
281   \@after@token%
282 }
283 \def\@start@after@group{%
284   \begingroup%
285   \count@\ag@cnt@global%
286   \clubpenalty\ag@cnt@local%
287   \let\@after@token\@after@token@i%
288 }
289 %    \end{macrocode}
290 %
291 % \end{macro}
292 %
293 % \begin{macro}{\@after@token@i}
294 %
295 % I have $|\count@| = N$ and $|\@tempcnta| = n$.  I'll decrement~$N$,
296 % and if I have $N = n$, I know that this is the last token to do, so I
297 % must insert an |\@after@all| after the token.  This will close the group,
298 % and maybe insert the original |\doafter| token if appropriate.
299 %
300 %    \begin{macrocode}
301 \def\@after@token@i{%
302   \advance\count@\m@ne%
303   \ifnum\count@=\clubpenalty%
304     \global\let\ag@cnt@global\ag@cnt@local%
305     \expandafter\@after@aftertoken\expandafter\@after@all%
306   \else%
307     \expandafter\@@aftergroup%
308   \fi%
309 }
310 %    \end{macrocode}
311 %
312 % Finally, establish a default meaning for |\@after@all|.
313 %
314 %    \begin{macrocode}
315 \let\@after@all\endgroup
316 %    \end{macrocode}
317 %
318 % \end{macro}
319 %
320 % \begin{macro}{\@prepare@after}
321 %
322 % If this group is handled by |\doafter|, then the first |\aftergroup| token
323 % isn't |\@after@token|; it's |\@prepare@after|.
324 %
325 % There are some extra cases to deal with:
326 % \begin{itemize}
327 % \item If $N=n$ then there were no |\aftergroup| tokens, so we have an easy
328 %       job.  I'll just let the token do its stuff directly.
329 % \item Otherwise, $N>n$, and there are |\aftergroup| tokens.  I'll open
330 %       the group, and let |\@after@token| do all the handling.
331 % \end{itemize}
332 %
333 %    \begin{macrocode}
334 \def\@prepare@after{%
335   \ifx\ag@cnt@local\ag@cnt@global\else%
336     \expandafter\@prepare@after@i%
337   \fi%
338 }
339 \def\@prepare@after@i#1{%
340   \@start@after@group%
341   \def\@after@all{\@@aftergroup#1\endgroup}%
342 }
343 %    \end{macrocode}
344 %
345 % \end{macro}
346 %
347 % \begin{macro}{\@after@aftertoken}
348 %
349 % This is where all the difficulty lies.  The next token in the stream is
350 % an |\aftergroup| one, which could be more or less anything.  We have an
351 % argument, which is some code to do \emph{after} the token has been
352 % |\aftergroup|ed.
353 %
354 % If the token is anything other than a brace (i.e., an  explicit character
355 % of category~1 or~2) then I have no problem; I can scoop up the token with
356 % an undelimited macro argument.  But the only way I can decide if this token
357 % is a brace (nondestructively) is with |\futurelet|, which makes the token
358 % implicit, so I can't decide whether it's really dangerous.
359 %
360 % There is a possible way of doing this\footnote{Due to Peter Schmitt,
361 % again.} which relates to nobbling the offending token with |\string| and
362 % sifting through the results.  The problem here involves scooping up all the
363 % tokens of a |\string|ed control sequence, which may turn out to be
364 % `|\csname\endcsname|' or something equally horrid.
365 %
366 % The solution I've used is much simpler: I'll change |\bgroup| and |\egroup|
367 % to stop them from being implicit braces before comparing.
368 %
369 %    \begin{macrocode}
370 \def\@after@aftertoken#1{%
371   \let\bgroup\relax\let\egroup\relax%
372   \toks@{#1}%
373   \futurelet\@let@token\@after@aftertoken@i%
374 }
375 \def\@after@aftertoken@i{%
376   \ifcat\noexpand\@let@token{%
377     \@@aftergroup{%
378   \else\ifcat\noexpand\@let@token}%
379     \@@aftergroup}%
380   \else%
381     \def\@tempa##1{\@@aftergroup##1\the\toks@}%
382     \expandafter\expandafter\expandafter\@tempa%
383   \fi\fi%
384 }
385 %    \end{macrocode}
386 %
387 % \end{macro}
388 %
389 %
390 % Phew!
391 %
392 %    \begin{macrocode}
393 %<+plain>\catcode`\@=12
394 %</macro|package>
395 %    \end{macrocode}
396 %
397 % \subsection{Test code}
398 %
399 % The following code gives |\doafter| a bit of a testing.  It's based on
400 % the test suite I gave to comp.text.tex, although it's been improved a
401 % little since then.
402 %
403 % The first thing to do is define a control sequence with an \lit{@} sign
404 % in its name, so we can test catcode changes.  This also hides an
405 % |\aftergroup| within a macro, making life more difficult for prospective
406 % implementations.
407 %
408 %    \begin{macrocode}
409 %<*test>
410 \catcode`\@=11
411 \def\at@name{\aftergroup\saynine}
412 \def\saynine{\say{ix}}
413 \catcode`\@=12
414 %    \end{macrocode}
415 %
416 % Now define a command to write a string to the terminal.  The name will
417 % probably be familiar to REXX hackers.
418 %
419 %    \begin{macrocode}
420 \def\say{\immediate\write16}
421 %    \end{macrocode}
422 %
423 % Test one: This is really easy; it just tests that the thing works at all.
424 % If your implementation fails this, it's time for a major rethink.
425 %
426 %    \begin{macrocode}
427 \say{Test one... (1--2)}
428 \def\saytwo{\say{ii}}
429 \doafter\saytwo{\say{i}}
430 %    \end{macrocode}
431 %
432 % Test two: Does |\aftergroup| work?
433 %
434 %    \begin{macrocode}
435 \say{Test two... (1--4)}
436 \def\saythree{\say{iii}}
437 \def\sayfour{\say{iv}}
438 \doafter\sayfour{\say{i}\aftergroup\saythree\say{ii}}
439 %    \end{macrocode}
440 %
441 % Test three: Test braces and |\iffalse| working as they should.  Several
442 % proposed solutions based on |\write|ing the group to a file get upset by
443 % this test, although I forgot to include it in the torture test.  It also
444 % tests whether literal braces can be |\aftergroup|ed properly.  (Added a new
445 % test here, making sure that |\bgroup| is left as an implicit token.)
446 %
447 %    \begin{macrocode}
448 \say{Test three... (1--4, `\string\bgroup', 5)}
449 \def\sayfive{\say{v}}
450 \doafter\sayfive{%
451   \say{i}%
452   \aftergroup\say%
453   \aftergroup{%
454   \aftergroup\romannumeral\aftergroup3%
455   \aftergroup}%
456   \iffalse}\fi%
457   \aftergroup\def%
458   \aftergroup\sayfouretc%
459   \aftergroup{%
460   \aftergroup\say%
461   \aftergroup{%
462   \aftergroup i%
463   \aftergroup v%
464   \aftergroup}%
465   \aftergroup\say%
466   \aftergroup{%
467   \aftergroup\string%
468   \aftergroup\bgroup%
469   \aftergroup}%
470   \aftergroup}%
471   \aftergroup\sayfouretc%
472   \say{ii}%
473 }
474 %    \end{macrocode}
475 %
476 % Test four: Make sure the implementation isn't leaking things.  This just
477 % makes sure that |\aftergroup| is its normal reasonable self.
478 %
479 %    \begin{macrocode}
480 \say{Test four... (1--3)}
481 {\say{i}\aftergroup\saythree\say{ii}}
482 %    \end{macrocode}
483 %
484 % Test five: Nesting, aftergroup, catcodes, grouping.  This is the `torture'
485 % test I gave to comp.text.tex, slightly corrected (oops) and amended.  It
486 % ensures that nested groups and |\doafter|s work properly (the latter is
487 % actually more likely than might be imagined).
488 %
489 %    \begin{macrocode}
490 \say{Test five... (1--14)}
491 \def\sayten{\say{x}}
492 \def\saythirteen{\say{xiii}}
493 \def\sayfourteen{\say{xiv}}
494 \doafter\sayfourteen\begingroup%
495   \say{i}%
496   {\say{ii}\aftergroup\sayfour\say{iii}}%
497   \def\saynum{\say{viii}}%
498   \doafter\sayten{%
499     \say{v}%
500     \def\saynum{\say{vii}}%
501     \catcode`\@=11%
502     \aftergroup\saynum%
503     \say{vi}%
504     \at@name%
505     \saynum%
506   }%
507   \say{xi}%
508   \aftergroup\saythirteen%
509   \say{xii}%
510 \endgroup
511 \end
512 %</test>
513 %    \end{macrocode}
514 %
515 % That's it.  All present and correct.
516 %
517 % \Finale
518 %
519 \endinput