Makefile: Include some custom LaTeX setup.
[mdwtools] / mdwref.dtx
1 % \begin{meta-comment} <general public licence>
2 %%
3 %% mdwref package -- slightly fancy cross-referencing stuff
4 %% Copyright (c) 2007, 2019 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 preambles>
25 %<+package>\NeedsTeXFormat{LaTeX2e}
26 %<+package>\ProvidesPackage{mdwref}
27 %<+package> [2020/09/06 1.14.0 Cross-referencing]
28 % \end{meta-comment}
29 %
30 % \CheckSum{131}
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 %
98 % All that remains is to define the strings to be typeset for various kinds
99 % of labels.
100 % \DescribeMacro\defxref
101 % For this, we use the |\defxref| command:
102 % \begin{grammar}
103 % <definition> ::= \[[
104 % "\\defxref"
105 % "{" <prefix> "}"
106 % "{" <string> "}"
107 % \]]
108 % \end{grammar}
109 % The \<prefix> is what you put on the front of your labels; the \<string> is
110 % the string to be typeset by |\xref|. Such references are typeset using
111 % |\formatxref|, described below.
112 %
113 % For references that don't fit into this pattern, there's a more complex
114 % definition syntax using |\defxref*|:
115 % \begin{grammar}
116 % <definition> ::= \[[
117 % "\\defxref*"
118 % "{" <prefix> "}"
119 % "{" <expansion> "}"
120 % \]]
121 % \end{grammar}
122 % The \<expansion> is given four arguments.
123 % \begin{itemize}
124 % \item |#1| is the name of a macro which should be given two arguments,
125 % respectively the reference name and the body of the hyperlink to
126 % generate.
127 % \item |#2| is the name of a macro to apply to the reference name to typeset
128 % the actual reference.
129 % \item |#3| is the \<mangle> token, or |\relax|.
130 % \item |#4| is the reference name itself.
131 % \end{itemize}
132 %
133 % \DescribeMacro\formatxref
134 % Simple references are typeset by calling
135 % \syntax{"\\formatxref{"<mangle>"}{"<string>"}{"<label>"}"}, which can do as
136 % it pleases: the \<mangle> token is from the |\xref| invocation; the
137 % \<string> is category of thing being referred to (as established by
138 % |\defxref| below); and \<label> is the label, again from |\xref| . The
139 % default behaviour is to print
140 % \syntax{<mangle>"{"<string>"}~\\ref{"<label>"}"}, but this can be
141 % overridden.
142 % (Not quite true: in fact, the default does something better if
143 % \package{hyperref} is detected, but the idea is basically the same.)
144 %
145 % A number of useful prefixes are already defined, following my usual
146 % preferences; they're shown in \xref{tab:defs}.
147 % \begin{table}
148 % \begin{tabular}[C]{ll} \hlx*{hv}
149 % \textbf{Prefix} & \textbf{Text} \\ \hlx{vhv}
150 % \texttt{ch} & chapter $n$ \\
151 % \texttt{app} & appendix $n$ \\
152 % \texttt{sec} & section $n$ \\
153 % \texttt{def} & definition $n$ \\
154 % \texttt{th} & theorem $n$ \\
155 % \texttt{lem} & lemma $n$ \\
156 % \texttt{prop} & proposition $n$ \\
157 % \texttt{cor} & corollary $n$ \\
158 % \texttt{fig} & figure $n$ \\
159 % \texttt{tab} & table $n$ \\
160 % \texttt{eq} & ($n$) \\
161 % \texttt{i} & item $n$ \\
162 % \texttt{ex} & exercise $n$ \\
163 % \hlx*{vh}\end{tabular}
164 % \caption{Predefined reference prefixes}
165 % \label{tab:defs}
166 % \end{table}
167 %
168 % \implementation
169 % \section{Implementation}
170 %
171 % \begin{macrocode}
172 %<*package>
173 % \end{macrocode}
174 %
175 % The following quark will be useful.
176 % \begin{macrocode}
177 \def\q@delim{\q@delim}
178 % \end{macrocode}
179 %
180 % \begin{macro}{\defxref}
181 % Defining prefixes is easy. We store the text for each prefix in a macro
182 % called \syntax{"\\xref$"<prefix>}, which takes two arguments: a \<mangle>
183 % token (or |\relax|), and the reference name.
184 % \begin{macrocode}
185 \def\defxref{\@ifstar\defxref@raw\defxref@cooked}
186 \def\defxref@cooked#1#2%
187 {\expandafter\def\csname xref$#1\endcsname##1##2{\formatxref{##1}{#2}{##2}}}
188 \def\defxref@raw#1#2{%
189 \expandafter\edef\csname xref$#1\endcsname
190 {\noexpand\xrefdispatch\expandafter\noexpand\csname xref$$#1\endcsname}%
191 \expandafter\def\csname xref$$#1\endcsname##1##2##3##4{#2}%
192 }
193 % \end{macrocode}
194 % \end{macro}
195 %
196 % \begin{macro}{\xrefdispatch}
197 % \begin{macrocode}
198 \def\xref@hyper#1{\hyperref[#1]}
199 \def\xrefdispatch#1{%
200 \ifx\hyperref\@@undefined \def\@tempa{#1\@gobble\ref}%
201 \else \def\@tempa{#1\xref@hyper{\ref*}}%
202 \fi \@tempa%
203 }
204 % \end{macrocode}
205 % \end{macro}
206 %
207 % \begin{macro}{\formatxref}
208 % Output a cross-reference in the right way.
209 % \begin{macrocode}
210 \def\formatxref{\xrefdispatch\xref@formatsimple}
211 \def\xref@formatsimple#1#2#3#4#5{#1{#5}{#3{#4}~#2{#5}}}
212 \def\xref@fallback#1{\formatxref\relax{?\texttt{#1}}{#1}}
213 % \end{macrocode}
214 % \end{macro}
215 %
216 % \begin{macro}{\xref}
217 % We're meant to typeset a reference. The first job is to see whether
218 % there's an optional argument. If so, grab it; otherwise |\relax| will do.
219 % \begin{macrocode}
220 \DeclareRobustCommand\xref{\@ifnextchar[\xref@{\xref@[\relax]}}
221 \def\xref@[#1]#2{\xref@@{#1}#2:\q@delim:\q@delim:\q@delim\q@delim}
222 % \end{macrocode}
223 % Right; now we abuse \TeX's argument parser to pick apart the reference
224 % label, which ought to have the form \syntax{<prefix>":"<suffix>}.
225 % \begin{macrocode}
226 \def\xref@@#1#2:#3:\q@delim#4\q@delim\q@delim{%
227 % \end{macrocode}
228 % So, |#1| is the optional command, or |\relax|. |#2| should be the
229 % prefix, and |#3| the suffix. However, if the string doesn't have any
230 % colons in, then |#3| will be |\q@delim|. This is easy to check for using
231 % |\ifx|.
232 % \begin{macrocode}
233 \def\@tempa{#2}\def\@tempb{#3}%
234 \ifx\@tempb\q@delim%
235 \PackageError{xref}{Bad ref syntax}%
236 {A reference name doesn't contain a `:'-delimited prefix. Did you %
237 mean to use plain \string\ref here?}%
238 \xref@fallback{#2}%
239 \else%
240 \expandafter\let\expandafter\@tempa\csname xref$#2\endcsname%
241 \ifx\@tempa\relax%
242 \PackageError{xref}{Unknown ref kind `#2'}%
243 {The ref name's prefix `#2' is unknown: either it's been mistyped %
244 or there's a missing \string\defxref somewhere.}%
245 \xref@fallback{#2:#3}%
246 \else \@tempa{#1}{#2:#3}%
247 \fi%
248 \fi%
249 }
250 % \end{macrocode}
251 % \end{macro}
252 %
253 % \begin{macro}{\toupper}
254 % That's the difficult stuff done. Uppercasing is a matter of picking out
255 % the first letter and passing it to \TeX's |\uppercase| primitive.
256 % \begin{macrocode}
257 \def\toupper#1{\toupper@#1}
258 \def\toupper@#1{\uppercase{#1}}
259 % \end{macrocode}
260 % \end{macro}
261 %
262 % \begin{macro}{\Xref}
263 % As promised, |\Xref| is very easy.
264 % \begin{macrocode}
265 \def\Xref{\xref[\toupper]}
266 % \end{macrocode}
267 % \end{macro}
268 %
269 % Now all that remains is to initialize the table of prefix strings.
270 % \begin{macrocode}
271 \defxref{ch}{chapter}
272 \defxref{app}{appendix}
273 \defxref{sec}{section}
274 \defxref{def}{definition}
275 \defxref{th}{theorem}
276 \defxref{lem}{lemma}
277 \defxref{prop}{proposition}
278 \defxref{cor}{corollary}
279 \defxref{fig}{figure}
280 \defxref{tab}{table}
281 \defxref*{eq}{#1{#4}{(#2{#4})}}
282 \defxref{i}{item}
283 \defxref{ex}{exercise}
284 % \end{macrocode}
285 % And we're done!
286 % \begin{macrocode}
287 %</package>
288 % \end{macrocode}
289 % \nopagebreak
290 %
291 % \hfill Mark Wooding, \today
292 %
293 % \Finale
294 %
295 \endinput