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