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