Commit | Line | Data |
---|---|---|
e8f3554e MW |
1 | % \begin{meta-comment} |
2 | % | |
3 | % $Id: mdwref.dtx,v 1.3 2003/11/10 14:43:48 mdw Exp $ | |
4 | % | |
5 | % Slightly fancy cross-referencing stuff | |
6 | % | |
7 | % (c) 2007 Mark Wooding | |
8 | % | |
9 | % \end{meta-comment} | |
10 | % | |
11 | % \begin{meta-comment} <general public licence> | |
12 | %% | |
13 | %% mdwref package -- slightly fancy cross-referencing stuff | |
14 | %% Copyright (c) 2007 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 preambles> | |
33 | %<+package>\NeedsTeXFormat{LaTeX2e} | |
34 | %<+package>\ProvidesPackage{mdwref} | |
35 | %<+package> [2007/04/09 1.01 Cross-referencing] | |
36 | % \end{meta-comment} | |
37 | % | |
38 | % ^^A\CheckSum{96} | |
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} | |
57 | % | |
58 | %<*driver> | |
59 | \input{mdwtools} | |
60 | \describespackage{mdwref} | |
61 | \usepackage{mdwtab} | |
62 | \mdwdoc | |
63 | %</driver> | |
64 | % | |
65 | % \end{meta-comment} | |
66 | % | |
67 | %^^A------------------------------------------------------------------------- | |
68 | % | |
69 | % \section{User guide} | |
70 | % | |
71 | % I always name my cross-reference labels with a prefix telling me what kind | |
72 | % of thing they are. A figure might be |fig:foo| or a table |tab:bar|. When | |
73 | % I refer to the thing, then, I basically have to repeat myself: | |
74 | % `|see table~\ref{tab:bar}|'. Kinda silly. | |
75 | % | |
76 | % \DescribeMacro\xref | |
77 | % The |\xref| command understands my prefixing system. I can say | |
78 | % `|\xref{tab:bar}|' and it inserts a reference to `table~4', for example. | |
79 | % This is, of course, useless if you want to put the reference at the | |
80 | % beginning of a sentence: `Table~4 shows\dots'. | |
81 | % \DescribeMacro\Xref | |
82 | % The |\Xref| command (note the initial capital) handles this properly, so | |
83 | % you just type `|\Xref{tab:bar} shows|\dots'. | |
84 | % | |
85 | % The full syntax of the |\xref| command is like this. | |
86 | % \begin{grammar} | |
87 | % <xref-command> ::= \[[ | |
88 | % "\\xref" | |
89 | % \[ "[" <mangle> "]" \] | |
90 | % "{" <reference> "}" | |
91 | % \]] | |
92 | % \end{grammar} | |
93 | % The optional \<mangle> argument is a command to be applied to the generated | |
94 | % text: it \emph{must} be a single token. Rather than printing `table', or | |
95 | % whatever, it prints \syntax{<mangle>"{table}"}. | |
96 | % The most obvious application of this is the |\Xref| command, which uses a | |
97 | % helper |\toupper|. | |
98 | % \DescribeMacro\toupper | |
99 | % The call \syntax{"\\toupper{"<stuff>"}"} typesets \<stuff> with the first | |
100 | % character in uppercase. So |\Xref| is defined simply as\footnote{Modulo | |
101 | % the fact that the author is a dreadful \TeX\ hacker.} | |
102 | % \begin{listing} | |
103 | %\newcommand{\Xref}[1]{\xref[\toupper]{#1}} | |
104 | % \end{listing} | |
105 | % | |
e0464890 MW |
106 | % \DescribeMacro\formatxref |
107 | % The reference itself is typeset by calling | |
108 | % \syntax{"\\formatxref{"<mangle>"}{"<string>"}{"<label>"}"}, which can do as | |
109 | % it pleases: the \<mangle> token is from the |\xref| invocation; the | |
110 | % \<string> is category of thing being referred to (as established by | |
111 | % |\defxref| below); and \<label> is the label, again from |\xref| . The | |
112 | % default behaviour is to print | |
113 | % \syntax{<mangle>"{"<string>"}~\\ref{"<label>"}"}, but this can be | |
114 | % overridden. | |
115 | % (Not quite true: in fact, the default does something better if | |
116 | % \package{hyperref} is detected, but the idea is basically the same.) | |
117 | % | |
e8f3554e MW |
118 | % All that remains is to define the strings to be typeset for various kinds |
119 | % of labels. | |
120 | % \DescribeMacro\defxref | |
121 | % For this, we use the |\defxref| command: | |
122 | % \begin{grammar} | |
123 | % <definition> ::= \[[ | |
124 | % "\\defxref" | |
125 | % "{" <prefix> "}" | |
126 | % "{" <string> "}" | |
127 | % \]] | |
128 | % \end{grammar} | |
129 | % The \<prefix> is what you put on the front of your labels; the \<string> is | |
130 | % the string to be typeset by |\xref|. | |
131 | % | |
132 | % A number of useful prefixes are already defined, following my usual | |
133 | % preferences; they're shown in \xref{tab:defs}. | |
134 | % \begin{table} | |
135 | % \def\i#1#2{\texttt{#1}&\texttt{#2}\\} | |
136 | % \begin{tabular}[C]{ll} \hlx*{hv} | |
137 | % \textbf{Prefix} & \textbf{Text} \\ \hlx{vhv} | |
138 | % \csname xref@defs\endcsname | |
139 | % \hlx*{vh}\end{tabular} | |
140 | % \caption{Predefined reference prefixes} | |
141 | % \label{tab:defs} | |
142 | % \end{table} | |
143 | % | |
144 | % \implementation | |
145 | % \section{Implementation} | |
146 | % | |
147 | % \begin{macrocode} | |
148 | %<*package> | |
149 | % \end{macrocode} | |
150 | % | |
151 | % The following quark will be useful. | |
152 | % \begin{macrocode} | |
153 | \def\q@delim{\q@delim} | |
154 | % \end{macrocode} | |
155 | % | |
156 | % \begin{macro}{\defxref} | |
157 | % Defining prefixes is easy. We store the text for each prefix in a macro | |
158 | % called \syntax{"\\xref$"<prefix>}. The only catch is that, for the | |
159 | % purposes of generating \xref{tab:defs}, we maintain a list of the prefixes | |
160 | % which have been defined so far, but this is fairly easy. | |
161 | % \begin{macrocode} | |
162 | \def\defxref#1#2{% | |
163 | \toks@\expandafter{\xref@defs\i{#1}{#2}}\xdef\xref@defs{\the\toks@}% | |
164 | \expandafter\def\csname xref$#1\endcsname{#2}% | |
165 | } | |
166 | % \end{macrocode} | |
167 | % The list is obviously empty initially. | |
168 | % \begin{macrocode} | |
169 | \gdef\xref@defs{} | |
170 | % \end{macrocode} | |
171 | % \end{macro} | |
172 | % | |
e0464890 MW |
173 | % \begin{macro}{\formatxref} |
174 | % Output a cross-reference in the right way. | |
175 | % \begin{macrocode} | |
176 | \def\formatxref#1#2#3{% | |
177 | \ifx\hyperref\@@undefined #1{#2}~\ref{#3}% | |
178 | \else \hyperref[#3]{#1{#2}~\ref*{#3}}\fi% | |
179 | } | |
180 | % \end{macrocode} | |
181 | % \end{macro} | |
182 | % | |
e8f3554e MW |
183 | % \begin{macro}{\xref} |
184 | % We're meant to typeset a reference. The first job is to see whether | |
185 | % there's an optional argument. If so, grab it; otherwise |\relax| will do. | |
186 | % \begin{macrocode} | |
187 | \def\xref{\@ifnextchar[\xref@{\xref@[\relax]}} | |
188 | \def\xref@[#1]#2{\xref@@{#1}#2:\q@delim:\q@delim:\q@delim\q@delim} | |
189 | % \end{macrocode} | |
190 | % Right; now we abuse \TeX's argument parser to pick apart the reference | |
191 | % label, which ought to have the form \syntax{<prefix>":"<suffix>}. | |
192 | % \begin{macrocode} | |
193 | \def\xref@@#1#2:#3:\q@delim#4\q@delim\q@delim{% | |
194 | % \end{macrocode} | |
195 | % So, |#1| is the optional command, or |\relax|. |#2| should be the | |
196 | % prefix, and |#3| the suffix. However, if the string doesn't have any | |
197 | % colons in, then |#3| will be |\q@delim|. This is easy to check for using | |
198 | % |\ifx|. | |
199 | % \begin{macrocode} | |
200 | \def\@tempa{#2}\def\@tempb{#3}% | |
201 | \ifx\@tempb\q@delim% | |
202 | \PackageError{xref}{Bad ref syntax}% | |
203 | \else% | |
204 | \expandafter\let\expandafter\@tempa\csname xref$#2\endcsname% | |
205 | \ifx\@tempa\relax% | |
206 | \PackageError{xref}{Unknown ref kind `#2'}% | |
207 | \else% | |
e0464890 MW |
208 | \toks@\expandafter{\@tempa}% |
209 | \edef\next@##1{##1{\the\toks@}}% | |
210 | \next@{\formatxref{#1}}{#2:#3}% | |
e8f3554e MW |
211 | \fi% |
212 | \fi% | |
213 | } | |
214 | % \end{macrocode} | |
215 | % \end{macro} | |
216 | % | |
217 | % \begin{macro}{\toupper} | |
218 | % That's the difficult stuff done. Uppercasing is a matter of picking out | |
219 | % the first letter and passing it to \TeX's |\uppercase| primitive. | |
220 | % \begin{macrocode} | |
221 | \def\toupper#1{\toupper@#1} | |
222 | \def\toupper@#1{\uppercase{#1}} | |
223 | % \end{macrocode} | |
224 | % \end{macro} | |
225 | % | |
226 | % \begin{macro}{\Xref} | |
227 | % As promised, |\Xref| is very easy. | |
228 | % \begin{macrocode} | |
229 | \def\Xref{\xref[\toupper]} | |
230 | % \end{macrocode} | |
231 | % \end{macro} | |
232 | % | |
233 | % Now all that remains is to initialize the table of prefix strings. | |
234 | % \begin{macrocode} | |
235 | \defxref{ch}{chapter} | |
236 | \defxref{app}{appendix} | |
237 | \defxref{sec}{section} | |
238 | \defxref{def}{definition} | |
239 | \defxref{th}{theorem} | |
240 | \defxref{lem}{lemma} | |
241 | \defxref{prop}{proposition} | |
242 | \defxref{cor}{corollary} | |
243 | \defxref{fig}{figure} | |
244 | \defxref{tab}{table} | |
245 | \defxref{eq}{equation} | |
246 | \defxref{i}{item} | |
247 | \defxref{ex}{exercise} | |
248 | % \end{macrocode} | |
249 | % And we're done! | |
250 | % \begin{macrocode} | |
251 | %</package> | |
252 | % \end{macrocode} | |
253 | % \nopagebreak | |
254 | % | |
255 | % \hfill Mark Wooding, \today | |
256 | % | |
257 | % \Finale | |
258 | % | |
259 | \endinput |