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