chiark / gitweb /
.mdw-build.conf: Don't try `vpath' builds with this package.
[mdwtools] / at.dtx
1 % \begin{meta-comment}
2 %
3 % $Id: at.dtx,v 1.1 2002/02/03 20:49:02 mdw Exp $
4 %
5 % Allow @-commands
6 %
7 % (c) 1995 Mark Wooding
8 %
9 % \end{meta-comment}
10 %
11 % \begin{meta-comment} <general public licence>
12 %%
13 %% at package -- support for `@' commands'
14 %% Copyright (c) 1996 Mark Wooding
15 %%
16 %% This program is free software; you can redistribute it and/or modify
17 %% it under the terms of the GNU General Public License as published by
18 %% the Free Software Foundation; either version 2 of the License, or
19 %% (at your option) any later version.
20 %%
21 %% This program is distributed in the hope that it will be useful,
22 %% but WITHOUT ANY WARRANTY; without even the implied warranty of
23 %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 %% GNU General Public License for more details.
25 %%
26 %% You should have received a copy of the GNU General Public License
27 %% along with this program; if not, write to the Free Software
28 %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 %%
30 % \end{meta-comment}
31 %
32 % \begin{meta-comment} <Package preamble>
33 %<+package>\NeedsTeXFormat{LaTeX2e}
34 %<+package>\ProvidesPackage{at}
35 %<+package>                [1996/05/02 1.3 @-command support (MDW)]
36 % \end{meta-comment}
37 %
38 % \CheckSum{355}
39 %% \CharacterTable
40 %%  {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
41 %%   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
42 %%   Digits        \0\1\2\3\4\5\6\7\8\9
43 %%   Exclamation   \!     Double quote  \"     Hash (number) \#
44 %%   Dollar        \$     Percent       \%     Ampersand     \&
45 %%   Acute accent  \'     Left paren    \(     Right paren   \)
46 %%   Asterisk      \*     Plus          \+     Comma         \,
47 %%   Minus         \-     Point         \.     Solidus       \/
48 %%   Colon         \:     Semicolon     \;     Less than     \<
49 %%   Equals        \=     Greater than  \>     Question mark \?
50 %%   Commercial at \@     Left bracket  \[     Backslash     \\
51 %%   Right bracket \]     Circumflex    \^     Underscore    \_
52 %%   Grave accent  \`     Left brace    \{     Vertical bar  \|
53 %%   Right brace   \}     Tilde         \~}
54 %%
55 %
56 % \begin{meta-comment} <driver>
57 %
58 %<*driver>
59 \input{mdwtools}
60 \describespackage{at}
61 \aton
62 \atlet p=\package
63 \atdef at{\package{at}}
64 \atdef={\mbox{-}}
65 \atdef-{@@@=}
66 \atlet.=\syntax
67 \mdwdoc
68 %</driver>
69 %
70 % \end{meta-comment}
71 %
72 % \section{User guide}
73 %
74 % The @at\ package is an attempt to remove a lot of tedious typing that
75 % ends up in \LaTeX\ documents, by expanding the number of short command
76 % names available.  The new command names begin with the `|@|' character,
77 % rather than the conventional `|\|', so you can tell them apart.
78 %
79 % The package provides some general commands for defining @-commands, and
80 % then uses them to define some fairly simple ones which will be useful to
81 % most people.
82 %
83 % The rules for @-command names aren't terribly complex:
84 % \begin{itemize}
85 % \item If the first character of the name is a letter, then the command name
86 %       consists of all characters up to, but not including, the first
87 %       nonletter.  Spaces following the command name are ignored.
88 % \item If the first character of the name is a backslash, then the @-command
89 %       name consists of the control sequence introduced by the backslash.
90 % \item Otherwise, the command name consists only of that first character.
91 %       Spaces following the name are not ignored, unless that character
92 %       was itself a space character.
93 % \end{itemize}
94 %
95 % Usually, digits are not considered to be letters.  However, the
96 % \package{at} package will consider digits to be letters if you give it the
97 % \textsf{digits} option in the |\usepackage| command.  (Note that this
98 % only affects the \package{at} package; it won't change the characters
99 % allowed in normal command names.)
100 %
101 % \DescribeMacro{\atallowdigits}
102 % \DescribeMacro{\atdisallowdigits}
103 % You can enable and disable digits being considered as letters dynamically.
104 % The |\atallowdigits| command allows digits to be used as letters;
105 % |\atdisallowdigits| prevents this.  Both declarations follow \LaTeX's
106 % usual scoping rules.  Both of these commands have corresponding
107 % environments with the same names (without the leading `|\|', obviously).
108 %
109 % \subsection{Defining @-commands}
110 %
111 % \DescribeMacro{\newatcommand}
112 % \DescribeMacro{\renewatcommand}
113 % The |\newatcommand| command will define a new @-command using a syntax
114 % similar to |\newcommand|.  For example, you could define
115 % \begin{listing}
116 %\newatcommand c[1]{\chapter{#1}}
117 % \end{listing}
118 % to make @.{"@c{"<name>"}"} equivalent to @.{"\\chapter{"<name>"}"}.
119 %
120 % A |\renewatcommand| is also provided to redefine existing commands, should
121 % the need arise.
122 %
123 % \DescribeMacro{\atdef}
124 % For \TeX\ hackers, the |\atdef| command defines @-commands using a syntax
125 % similar to \TeX's built-in |\def|.
126 %
127 % As an example, the following command makes @.{"@/"<text>"/"} write its
128 % argument \<text> in italics:
129 % \begin{listing}
130 %\atdef/#1/{\textit{#1}}
131 % \end{listing}
132 % The real implementation of the |@/|\dots|/| command is a bit more
133 % complex, and is given in the next section.
134 %
135 % You can use all of \TeX's features for defining the syntax of your
136 % command.  (See chapter~20 of @/The \TeX book/ for more details.)
137 %
138 % \DescribeMacro{\atlet}
139 % Since |\atdef| is provided to behave similarly to |\def|, @at\ provides
140 % |\atlet| which works similarly to |\let|.  For example you can say
141 % \begin{listing}
142 %\atlet!=\index
143 % \end{listing}
144 % to allow the short |@!| to behave exactly like |\index|.
145 %
146 % Note that all commands defined using these commands are robust even if you
147 % use fragile commands in their definitions.  Unless you start doing very
148 % strange things, @-commands never need |\protect|ing.
149 %
150 % \subsection{Predefined @-commands}
151 %
152 % A small number of hopefully useful commands are provided by default.
153 % These are described in the table below:
154 %
155 % \bigskip \begin{center} \begin{tabular}{lp{3in}}                    \hline
156 % \bf Command        & \bf Meaning                                 \\ \hline
157 % @.{"@@"}           & Typesets an `@@' character.                 \\
158 % @.{"@/"<text>"/"}  & In text (LR or paragraph) mode, typesets its
159 %                      argument emphasised.  In maths mode, it
160 %                      always chooses italics.                     \\
161 % @.{"@*"<text>"*"}  & Typesets its argument \<text> in bold.      \\
162 % @.{"@i{"<text>"}"} & Equivalent to `@.{"\\index{"<text>"}"}'.    \\
163 % @.{"@I{"<text>"}"} & As for |@i|, but also writes its argument
164 %                      to the document.                            \\ \hline
165 % \end{tabular} \end{center} \bigskip
166 %
167 % Package writers should not rely on any predefined @-commands -- they're
168 % provided for users, and users should be able to redefine them without
169 % fear of messing anything up.  (This includes the `standard' commands
170 % provided by the @at\ package, by the way.  They're provided in the vague
171 % hope that they might be useful, and as examples.)
172 %
173 % \implementation
174 %
175 % \section{Implementation}
176 %
177 %    \begin{macrocode}
178 %<*package>
179 %    \end{macrocode}
180 %
181 % \subsection{Options handling}
182 %
183 % We need a switch to say whether digits should be allowed.  Since this
184 % is a user thing, I'll avoid |\newif| and just define the thing by hand.
185 %
186 %    \begin{macrocode}
187 \def\atallowdigits{\let\ifat@digits\iftrue}
188 \def\atdisallowdigits{\let\ifat@digits\iffalse}
189 %    \end{macrocode}
190 %
191 % Now define the options.
192 %
193 %    \begin{macrocode}
194 \DeclareOption{digits}{\atallowdigits}
195 \DeclareOption{nodigits}{\atdisallowdigits}
196 \ExecuteOptions{nodigits}
197 \ProcessOptions
198 %    \end{macrocode}
199 %
200 % \subsection{How the commands work}
201 %
202 % Obviously we make the `@@' character active.  It inspects the next
203 % character (or argument, actually -- it can be enclosed in braces for
204 % longer commands, although this is a bit futile), and builds the command
205 % name from that.
206 %
207 % The |\at| command is equivalent to the active `@@' character always.
208 %
209 %
210 % \subsection{Converting command names}
211 %
212 % We need to be able to read an @-command name, and convert it to a normal
213 % \TeX\ control sequence.  First, we declare some control sequences for
214 % braces, which we need later.
215 %
216 %    \begin{macrocode}
217 \begingroup
218 \catcode`\<1
219 \catcode`\>2
220 \catcode`\{12
221 \catcode`\}12
222 \gdef\at@lb<{>
223 \gdef\at@rb<}>
224 \gdef\at@spc< >
225 \endgroup
226 %    \end{macrocode}
227 %
228 % I'll set up some helper routines now, to help me read the command
229 % names.  The way this works is that we |\futurelet| the token into
230 % |\@let@token|.  These routines will then sort out what to do next.
231 %
232 % \begin{macro}{\at@test}
233 %
234 % Given an |\if|\dots\ test, does its first or second argument.
235 %
236 %    \begin{macrocode}
237 \def\at@test#1\then{%
238   #1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi%
239 }
240 %    \end{macrocode}
241 %
242 % \end{macro}
243 %
244 % \begin{macro}{\at@ifcat}
245 %
246 % Checks the category code of the current character.  If it matches the
247 % argument, it does its second argument, otherwise it does the third.
248 %
249 %    \begin{macrocode}
250 \def\at@ifcat#1{\at@test\ifcat#1\noexpand\@let@token\then}
251 %    \end{macrocode}
252 %
253 % \end{macro}
254 %
255 % \begin{macro}{\at@ifletter}
256 %
257 % This routine tests the token to see if it's a letter, and if so adds
258 % it to the token list and does the first argument; otherwise it does the
259 % second argument.  It accepts digits as letters if the switch is turned
260 % on.
261 %
262 % There's some fun later, so I'll describe this slowly.  First, we compare
263 % the category code to a letter, and if we have a match, we know we're done;
264 % we need to pick up the letter as an argument.  If the catcode is `other',
265 % we must compare with numbers to see if it's in range.
266 %
267 %    \begin{macrocode}
268 \def\at@ifletter#1#2{%
269   \at@ifcat x%
270     {\at@ifletter@ii{#1}}%
271     {\at@ifcat 0%
272       {\at@ifletter@i{#1}{#2}}%
273       {#2}%
274     }%
275 }
276 %    \end{macrocode}
277 %
278 % Right.  It's `other' (so it's safe to handle as a macro argument) and we
279 % need to know if it's a digit.  This is a little tricky: I use |\if| to
280 % compare two characters.  The first character is~`1' or~`0' depending on the
281 % `digit' switch; the second is~`1' or~`x' depending on whether it's actually
282 % a digit.  They'll only match if everything's worked out OK.
283 %
284 %    \begin{macrocode}
285 \def\at@ifletter@i#1#2#3{%
286   \at@test\if%
287     \ifat@digits1\else0\fi%
288     \ifnum`#3<`0x\else\ifnum`#3>`9x\else1\fi\fi%
289   \then%
290     {\at@ifletter@ii{#1}{#3}}%
291     {#2#3}%
292 }
293 %    \end{macrocode}
294 %
295 % Right; we have the character, so add it to the list and carry on.
296 %
297 %    \begin{macrocode}
298 \def\at@ifletter@ii#1#2{\toks@\expandafter{\the\toks@#2}#1}
299 %    \end{macrocode}
300 %
301 % \end{macro}
302 %
303 % Now we define the command name reading routines.  We have @/almost/ the
304 % same behaviour as \TeX, although we can't support `|%|' characters for
305 % reasons to do with \TeX's tokenising algorithm.
306 %
307 % \begin{macro}{\at@read@name}
308 %
309 % The routine which actually reads the command name works as follows:
310 % \begin{enumerate}
311 % \item Have a peek at the next character.  If it's a left or right brace,
312 %       then use the appropriate character.
313 % \item If the character is not a letter, just use the character (or whole
314 %       control sequence.
315 % \item Finally, if it's a letter, keep reading letters until we find one
316 %       that wasn't.
317 % \end{enumerate}
318 %
319 % First, we do some setting up and read the first character
320 %
321 %    \begin{macrocode}
322 \def\at@read@name#1{%
323   \let\at@next=#1%
324   \toks@{}%
325   \futurelet\@let@token\at@rn@i%
326 }
327 %    \end{macrocode}
328 %
329 % Next, sort out what to do, based on the category code.
330 %
331 %    \begin{macrocode}
332 \def\at@rn@i{%
333   \def\@tempa{\afterassignment\at@rn@iv\let\@let@token= }%
334   \at@ifletter%
335     {\futurelet\@let@token\at@rn@iii}%
336     {\at@ifcat\bgroup%
337       {\toks@\expandafter{\at@lb}\@tempa}%
338       {\at@ifcat\egroup%
339         {\toks@\expandafter{\at@rb}\@tempa}%
340         {\at@ifcat\at@spc%
341           {\toks@{ }\@tempa}%
342           {\at@rn@ii}%
343         }%
344       }%
345     }%
346 }
347 %    \end{macrocode}
348 %
349 % Most types of tokens can be fiddled using |\string|.
350 %
351 %    \begin{macrocode}
352 \def\at@rn@ii#1{%
353   \toks@\expandafter{\string#1}%
354   \at@rn@iv%
355 }
356 %    \end{macrocode}
357 %
358 % We've found a letter, so we should check for another one.
359 %
360 %    \begin{macrocode}
361 \def\at@rn@iii{%
362   \at@ifletter%
363     {\futurelet\@let@token\at@rn@iii}%
364     {\@ifnextchar.\at@rn@iv\at@rn@iv}%
365 }
366 %    \end{macrocode}
367 %
368 % Finally, we need to pass the real string, as an argument, to the
369 % macro.  We make |\@let@token| relax, since it might be something which will
370 % upset \TeX\ later, e.g., a |#| character.
371 %
372 %    \begin{macrocode}
373 \def\at@rn@iv{%
374   \let\@let@token\relax%
375   \expandafter\at@next\csname at.\the\toks@\endcsname%
376 }
377 %    \end{macrocode}
378 %
379 % \end{macro}
380 %
381 % \begin{macro}{\at@cmdname}
382 %
383 % Given a control sequence, work out which @-command it came from.
384 %
385 %    \begin{macrocode}
386 \def\at@cmdname#1{\expandafter\at@cmdname@i\string#1\@@foo}
387 %    \end{macrocode}
388 %
389 % Now extract the trailing bits.
390 %
391 %    \begin{macrocode}
392 \def\at@cmdname@i#1.#2\@@foo{#2}
393 %    \end{macrocode}
394 %
395 % \end{macro}
396 %
397 % \begin{macro}{\at@decode}
398 %
399 % The |\at@decode| macro takes an extracted @-command name, and tries to
400 % execute the correct control sequence derived from it.
401 %
402 %    \begin{macrocode}
403 \def\at@decode#1{%
404   \at@test\ifx#1\relax\then{%
405     \PackageError{at}{Unknown @-command `@\at@cmdname#1'}{%
406       The @-command you typed wasn't recognised, so I've ignored it.
407     }%
408   }{%
409     #1%
410   }%
411 }
412 %    \end{macrocode}
413 %
414 % \end{macro}
415 %
416 % \begin{macro}{\@at}
417 %
418 % We'd like a measure of compatibility with @p{amsmath}.  The @-commands
419 % provided by @p{amsmath} work only in maths mode, so this gives us a way of
420 % distinguishing.  If the control sequence |\Iat| is defined, and we're in
421 % maths mode, we'll call that instead of doing our own thing.
422 %
423 %    \begin{macrocode}
424 \def\@at{%
425   \def\@tempa{\at@read@name\at@decode}%
426   \ifmmode\ifx\Iat\not@@defined\else%
427     \let\@tempa\Iat%
428   \fi\fi%
429   \@tempa%
430 }
431 %    \end{macrocode}
432 %
433 % \end{macro}
434 %
435 %
436 % \subsection{Defining new commands}
437 %
438 % \begin{macro}{\at@buildcmd}
439 %
440 % First, we define a command to build these other commands:
441 %
442 %    \begin{macrocode}
443 \def\at@buildcmd#1#2{%
444   \expandafter\def\csname\expandafter
445     \@gobble\string#1@decode\endcsname##1{#2##1}%
446   \edef#1{%
447     \noexpand\at@read@name%
448     \expandafter\noexpand%
449       \csname\expandafter\@gobble\string#1@decode\endcsname%
450   }%
451 }
452 %    \end{macrocode}
453 %
454 % \end{macro}
455 %
456 % \begin{macro}{\newatcommand}
457 % \begin{macro}{\renewatcommand}
458 % \begin{macro}{\provideatcommand}
459 % \begin{macro}{\atdef}
460 % \begin{macro}{\atshow}
461 %
462 % Now we define the various operations on @-commands.
463 %
464 %    \begin{macrocode}
465 \at@buildcmd\newatcommand\newcommand
466 \at@buildcmd\renewatcommand\renewcommand
467 \at@buildcmd\provideatcommand\providecommand
468 \at@buildcmd\atdef\def
469 \at@buildcmd\atshow\show
470 %    \end{macrocode}
471 %
472 % \end{macro}
473 % \end{macro}
474 % \end{macro}
475 % \end{macro}
476 % \end{macro}
477 %
478 % \begin{macro}{\atlet}
479 %
480 % |\atlet| is rather harder than the others, because we want to allow people
481 % to say things like @.{"\\atlet"<name>"=@"<name>}.  The following hacking
482 % does the trick.  I'm trying very hard to duplicate |\let|'s behaviour with
483 % respect to space tokens here, to avoid any surprises, although there
484 % probably will be some differences.  In particular, |\afterassignment|
485 % won't work in any sensible way.
486 %
487 % First, we read the name of the @-command we're defining.  We also open
488 % a group, to stop messing other people up, and make `@@' into an `other'
489 % token, so that it doesn't irritatingly look like its meaning as a control
490 % sequence.
491 %
492 %    \begin{macrocode}
493 \def\atlet{%
494   \begingroup%
495   \@makeother\@%
496   \at@read@name\atlet@i%
497 }
498 %    \end{macrocode}
499 %
500 % Put the name into a scratch macro for later use.  Now see if there's an
501 % equals sign up ahead.  If not, this will gobble any spaces in between the
502 % @-command name and the argument.
503 %
504 %    \begin{macrocode}
505 \def\atlet@i#1{%
506   \def\at@temp{#1}%
507   \@ifnextchar=\atlet@ii{\atlet@ii=}%
508 }
509 %    \end{macrocode}
510 %
511 % Now we gobble the equals sign (whatever catcode it is), and peek at the
512 % next token up ahead using |\let| with no following space.
513 %
514 %    \begin{macrocode}
515 \def\atlet@ii#1{\afterassignment\atlet@iii\global\let\at@gnext=}
516 %    \end{macrocode}
517 %
518 % The control sequence |\at@gnext| is now |\let| to be whatever we want the
519 % @-command to be, unless it's picked up an `@@' sign.  If it has, we've
520 % eaten the |@| token, so just read the name and pass it on.  Otherwise,
521 % we can |\let| the @-command directly to |\at@gnext|.  There's some
522 % nastiness here to make |\the\toks@| expand before we close the group and
523 % restore its previous definition.
524 %
525 %    \begin{macrocode}
526 \def\atlet@iii{%
527   \if @\noexpand\at@gnext%
528     \expandafter\at@read@name\expandafter\atlet@iv%
529   \else%
530     \expandafter\endgroup%
531     \expandafter\let\at@temp= \at@gnext%
532   \fi%
533 }
534 %    \end{macrocode}
535 %
536 % We've read the source @-command name, so just copy the definitions over.
537 %
538 %    \begin{macrocode}
539 \def\atlet@iv#1{%
540   \expandafter\endgroup%
541   \expandafter\let\at@temp=#1%
542 }
543 %    \end{macrocode}
544 %
545 % \end{macro}
546 %
547 %
548 % \subsection{Robustness of @-commands}
549 %
550 % We want all @-commands to be robust.  We could leave them all being
551 % fragile, although making robust @-commands would then be almost impossible.
552 % There are two problems which we must face:
553 %
554 % \begin{itemize}
555 %
556 % \item The `|\@at|' command which scans the @-command name is (very)
557 %       fragile.  I could have used |\DeclareRobustCommand| for it (and in
558 %       fact I did in an earlier version), but that doesn't help the other
559 %       problem at all.
560 %
561 % \item The `name' of the @-command may contain active characters or control
562 %       sequences, which will be expanded at the wrong time unless we do
563 %       something about it now.
564 %
565 % \end{itemize}
566 %
567 % We must also be careful not to introduce extra space characters into any
568 % files written, because spaces are significant in @-commands.  Finally,
569 % we have a minor problem in that most auxiliary files are read in with
570 % the `@@' character set to be a letter.
571 %
572 % \begin{macro}{\at}
573 %
574 % Following the example of \LaTeX's `short' command handling, we'll define
575 % |\at| to decide what to do depending on what |\protect| looks like.  If
576 % we're typesetting, we just call |\@at| (above) and expect it to cope.
577 % Otherwise we call |\at@protect|, which scoops up the |\fi| and the |\@at|,
578 % and inserts other magic.
579 %
580 %    \begin{macrocode}
581 \def\at{\ifx\protect\@typeset@protect\else\at@protect\fi\@at}
582 %    \end{macrocode}
583 %
584 % \end{macro}
585 %
586 % \begin{macro}{\at@protect}
587 %
588 % Since we gobbled the |\fi| from the above, we must put that back.  We then
589 % need to do things which are more complicated.  If |\protect| is behaving
590 % like |\string|, then we do one sort of protection.  Otherwise, we assume
591 % that |\protect| is being like |\noexpand|.
592 %
593 %    \begin{macrocode}
594 \def\at@protect\fi#1{%
595   \fi%
596   \ifx\protect\string%
597     \expandafter\at@protect@string%
598   \else%
599     \expandafter\at@protect@noexpand%
600   \fi%
601 }
602 %    \end{macrocode}
603 %
604 % \end{macro}
605 %
606 % \begin{macro}{\at@protect@string}
607 %
608 % When |\protect| is |\string|, we don't need to be able to recover the
609 % original text particularly accurately -- it's for the user to look at.
610 % Therefore, we just output a $|@|_{11}$ and use |\string| on the next
611 % token.  This must be sufficient, since we only allow multi-token command
612 % names if the first token is a letter (code~11).
613 %
614 %    \begin{macrocode}
615 \def\at@protect@string{@\string}
616 %    \end{macrocode}
617 %
618 % \end{macro}
619 %
620 % \begin{macro}{\at@protect@noexpand}
621 %
622 % This is a little more complex, since we're still expecting to be executed
623 % properly at some stage.  However, there's a cheeky dodge we can employ
624 % since the |\at| command is thoroughly robustified (or at least it will be
625 % by the time we've finished this).  All |\@unexpandable@protect| does
626 % is confer repeated robustness on a fragile command.  Since our command
627 % is robust, we don't need this and we can get away with just using a
628 % single |\noexpand|, both for the |\@at@| command and the following token
629 % (which we must robustify, because no-one else can do it for us -- if
630 % anyone tries, they end up using the |@\protect| command which is rather
631 % embarassing).
632 %
633 % I'll give the definition, and then examine how this expands in various
634 % cases.
635 %
636 %    \begin{macrocode}
637 \def\at@protect@noexpand{\noexpand\@at@ @\noexpand}
638 \def\@at@#1{\at}
639 %    \end{macrocode}
640 %
641 % A few points, before we go into the main examination of the protection.
642 % I've inserted a $|@|_{11}$ token, which is gobbled by |\@at@| when the
643 % thing is finally expanded fully.  This prevents following space tokens
644 % in an |\input| file from being swallowed because they follow a control
645 % sequence.  (I can't use the normal $|@|_{13}$ token, because when files
646 % like the |.aux| file are read in, |@| is given code~11 by
647 % |\makeatletter|.)
648 %
649 % \setbox0\hbox{|@at@|}
650 % Now for a description of why this works.  When |\at| is expanded, it works
651 % out that |\protect| is either |\noexpand| or |\@unexpandable@protect|, and
652 % becomes |\at@protect@noexpand|.  Because of the |\noexpand| tokens, this
653 % stops being expanded once it reaches $\fbox{\box0}\,|@|_{11}\,x$ (where
654 % $x$ is the token immediately following the $|@|_{13}$ character).  If this
655 % is expanded again, for example in another |\edef|, or in a |\write| or a
656 % |\mark|, the |\@at@| wakes up, gobbles the following |@| (whatever catcode
657 % it is -- there may be intervening |\write| and |\input| commands) and
658 % becomes |\at|, and the whole thing can start over again.
659 %
660 % \end{macro}
661 %
662 %
663 % \subsection{Enabling and disabling @-commands}
664 %
665 % \begin{macro}{\aton}
666 %
667 % We define the |\aton| command to enable all of our magic.  We store
668 % the old catcode in the |\atoff| command, make `@@' active, and make it
669 % do the stuff.
670 %
671 %    \begin{macrocode}
672 \def\aton{%
673   \ifnum\catcode`\@=\active\else%
674     \edef\atoff{\catcode`\noexpand\@\the\catcode`\@}%
675     \catcode`\@\active%
676     \lccode`\~`\@%
677     \lowercase{\let~\at}%
678   \fi%
679 }
680 %    \end{macrocode}
681 %
682 % \end{macro}
683 %
684 % \begin{macro}{\atoff}
685 %
686 % The |\atoff| command makes `@@' do the stuff it's meant to.  We remember
687 % the old catcode and revert to it.  This is largely unnecessary.
688 %
689 %    \begin{macrocode}
690 \def\atoff{\catcode`\@12}
691 %    \end{macrocode}
692 %
693 % \end{macro}
694 %
695 % \begin{macro}{\makeatother}
696 %
697 % Now we make our active `@@' the default outside of package files.
698 %
699 %    \begin{macrocode}
700 \let\makeatother\aton
701 %    \end{macrocode}
702 %
703 % \end{macro}
704 %
705 % And we must make sure that the user can use all of our nice commands.
706 % Once the document starts, we allow @-commands.
707 %
708 %    \begin{macrocode}
709 \AtBeginDocument{\aton}
710 %    \end{macrocode}
711 %
712 % \begin{macro}{\dospecials}
713 % \begin{macro}{\@sanitize}
714 %
715 % We must add the `@@' character to the various specials lists.
716 %
717 %    \begin{macrocode}
718 \expandafter\def\expandafter\dospecials\expandafter{\dospecials\do\@}
719 \expandafter\def\expandafter\@sanitize\expandafter{%
720   \@sanitize\@makeother\@}
721 %    \end{macrocode}
722 %
723 % \end{macro}
724 % \end{macro}
725 %
726 % \subsection{Default @-commands}
727 %
728 % We define some trivial examples to get the user going.
729 %
730 %    \begin{macrocode}
731 \expandafter\chardef\csname at.@\endcsname=`\@
732 \atdef*#1*{\ifmmode\mathbf{#1}\else\textbf{#1}\fi}
733 \atdef/#1/{\ifmmode\mathit{#1}\else\emph{#1}\fi}
734 \atlet i=\index
735 \atdef I#1{#1\index{#1}}
736 %</package>
737 %    \end{macrocode}
738 %
739 % \hfill Mark Wooding, \today
740 %
741 % \Finale
742 %
743 \endinput