f1da45c8b52ba7029dde925e585b12ac23fad622
[mdwtools] / mdwref.dtx
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 %
106 % All that remains is to define the strings to be typeset for various kinds
107 % of labels.
108 % \DescribeMacro\defxref
109 % For this, we use the |\defxref| command:
110 % \begin{grammar}
111 % <definition> ::= \[[
112 % "\\defxref"
113 % "{" <prefix> "}"
114 % "{" <string> "}"
115 % \]]
116 % \end{grammar}
117 % The \<prefix> is what you put on the front of your labels; the \<string> is
118 % the string to be typeset by |\xref|.
119 %
120 % A number of useful prefixes are already defined, following my usual
121 % preferences; they're shown in \xref{tab:defs}.
122 % \begin{table}
123 % \def\i#1#2{\texttt{#1}&\texttt{#2}\\}
124 % \begin{tabular}[C]{ll} \hlx*{hv}
125 % \textbf{Prefix} & \textbf{Text} \\ \hlx{vhv}
126 % \csname xref@defs\endcsname
127 % \hlx*{vh}\end{tabular}
128 % \caption{Predefined reference prefixes}
129 % \label{tab:defs}
130 % \end{table}
131 %
132 % \implementation
133 % \section{Implementation}
134 %
135 % \begin{macrocode}
136 %<*package>
137 % \end{macrocode}
138 %
139 % The following quark will be useful.
140 % \begin{macrocode}
141 \def\q@delim{\q@delim}
142 % \end{macrocode}
143 %
144 % \begin{macro}{\defxref}
145 % Defining prefixes is easy. We store the text for each prefix in a macro
146 % called \syntax{"\\xref$"<prefix>}. The only catch is that, for the
147 % purposes of generating \xref{tab:defs}, we maintain a list of the prefixes
148 % which have been defined so far, but this is fairly easy.
149 % \begin{macrocode}
150 \def\defxref#1#2{%
151 \toks@\expandafter{\xref@defs\i{#1}{#2}}\xdef\xref@defs{\the\toks@}%
152 \expandafter\def\csname xref$#1\endcsname{#2}%
153 }
154 % \end{macrocode}
155 % The list is obviously empty initially.
156 % \begin{macrocode}
157 \gdef\xref@defs{}
158 % \end{macrocode}
159 % \end{macro}
160 %
161 % \begin{macro}{\xref}
162 % We're meant to typeset a reference. The first job is to see whether
163 % there's an optional argument. If so, grab it; otherwise |\relax| will do.
164 % \begin{macrocode}
165 \def\xref{\@ifnextchar[\xref@{\xref@[\relax]}}
166 \def\xref@[#1]#2{\xref@@{#1}#2:\q@delim:\q@delim:\q@delim\q@delim}
167 % \end{macrocode}
168 % Right; now we abuse \TeX's argument parser to pick apart the reference
169 % label, which ought to have the form \syntax{<prefix>":"<suffix>}.
170 % \begin{macrocode}
171 \def\xref@@#1#2:#3:\q@delim#4\q@delim\q@delim{%
172 % \end{macrocode}
173 % So, |#1| is the optional command, or |\relax|. |#2| should be the
174 % prefix, and |#3| the suffix. However, if the string doesn't have any
175 % colons in, then |#3| will be |\q@delim|. This is easy to check for using
176 % |\ifx|.
177 % \begin{macrocode}
178 \def\@tempa{#2}\def\@tempb{#3}%
179 \ifx\@tempb\q@delim%
180 \PackageError{xref}{Bad ref syntax}%
181 \else%
182 \expandafter\let\expandafter\@tempa\csname xref$#2\endcsname%
183 \ifx\@tempa\relax%
184 \PackageError{xref}{Unknown ref kind `#2'}%
185 \else%
186 \toks@{#1}\toks\tw@\expandafter{\@tempa}%
187 \edef\next@{\the\toks@{\the\toks\tw@}}%
188 \next@~\ref{#2:#3}%
189 \fi%
190 \fi%
191 }
192 % \end{macrocode}
193 % \end{macro}
194 %
195 % \begin{macro}{\toupper}
196 % That's the difficult stuff done. Uppercasing is a matter of picking out
197 % the first letter and passing it to \TeX's |\uppercase| primitive.
198 % \begin{macrocode}
199 \def\toupper#1{\toupper@#1}
200 \def\toupper@#1{\uppercase{#1}}
201 % \end{macrocode}
202 % \end{macro}
203 %
204 % \begin{macro}{\Xref}
205 % As promised, |\Xref| is very easy.
206 % \begin{macrocode}
207 \def\Xref{\xref[\toupper]}
208 % \end{macrocode}
209 % \end{macro}
210 %
211 % Now all that remains is to initialize the table of prefix strings.
212 % \begin{macrocode}
213 \defxref{ch}{chapter}
214 \defxref{app}{appendix}
215 \defxref{sec}{section}
216 \defxref{def}{definition}
217 \defxref{th}{theorem}
218 \defxref{lem}{lemma}
219 \defxref{prop}{proposition}
220 \defxref{cor}{corollary}
221 \defxref{fig}{figure}
222 \defxref{tab}{table}
223 \defxref{eq}{equation}
224 \defxref{i}{item}
225 \defxref{ex}{exercise}
226 % \end{macrocode}
227 % And we're done!
228 % \begin{macrocode}
229 %</package>
230 % \end{macrocode}
231 % \nopagebreak
232 %
233 % \hfill Mark Wooding, \today
234 %
235 % \Finale
236 %
237 \endinput