Insert correct checksums.
[mdwtools] / doafter.dtx
CommitLineData
86f6a31e 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