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