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