chiark / gitweb /
mdwtab.dtx: Add a sneaky kern after `\multicolumn'.
[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 file is part of the `mdwtools' LaTeX package collection.
9 %%
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.
19 %%
20 %% You should have received a copy of the GNU General Public License
21 %% along with `mdwtools'.  If not, write to the Free Software Foundation,
22 %% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 %</package>
24 %%
25 % \end{meta-comment}
26 %
27 % \begin{meta-comment} <Package preamble>
28 %<+latex2e>\NeedsTeXFormat{LaTeX2e}
29 %<+latex2e>\ProvidesPackage{doafter}
30 %<+latex2e>                [2020/09/06 1.14.0 Aftergroup hacking]
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