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