Makefile: Include some custom LaTeX setup.
[mdwtools] / mdwref.dtx
CommitLineData
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%
bf6775ed 30% \CheckSum{131}
e8f3554e
MW
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
74754fa2
MW
110% the string to be typeset by |\xref|. Such references are typeset using
111% |\formatxref|, described below.
112%
ae8b308b
MW
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%
74754fa2
MW
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.)
e8f3554e
MW
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}
e8f3554e
MW
148% \begin{tabular}[C]{ll} \hlx*{hv}
149% \textbf{Prefix} & \textbf{Text} \\ \hlx{vhv}
b2fa76c1
MW
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$ \\
ae8b308b 160% \texttt{eq} & ($n$) \\
b2fa76c1
MW
161% \texttt{i} & item $n$ \\
162% \texttt{ex} & exercise $n$ \\
e8f3554e
MW
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
74754fa2
MW
182% called \syntax{"\\xref$"<prefix>}, which takes two arguments: a \<mangle>
183% token (or |\relax|), and the reference name.
e8f3554e 184% \begin{macrocode}
ae8b308b
MW
185\def\defxref{\@ifstar\defxref@raw\defxref@cooked}
186\def\defxref@cooked#1#2%
74754fa2 187 {\expandafter\def\csname xref$#1\endcsname##1##2{\formatxref{##1}{#2}{##2}}}
ae8b308b
MW
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}
74754fa2
MW
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%
e8f3554e
MW
203}
204% \end{macrocode}
e8f3554e
MW
205% \end{macro}
206%
e0464890
MW
207% \begin{macro}{\formatxref}
208% Output a cross-reference in the right way.
209% \begin{macrocode}
74754fa2
MW
210\def\formatxref{\xrefdispatch\xref@formatsimple}
211\def\xref@formatsimple#1#2#3#4#5{#1{#5}{#3{#4}~#2{#5}}}
2028c55c 212\def\xref@fallback#1{\formatxref\relax{?\texttt{#1}}{#1}}
e0464890
MW
213% \end{macrocode}
214% \end{macro}
215%
e8f3554e
MW
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}
5893e637 220\DeclareRobustCommand\xref{\@ifnextchar[\xref@{\xref@[\relax]}}
e8f3554e
MW
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}%
2028c55c
MW
236 {A reference name doesn't contain a `:'-delimited prefix. Did you %
237 mean to use plain \string\ref here?}%
238 \xref@fallback{#2}%
e8f3554e
MW
239 \else%
240 \expandafter\let\expandafter\@tempa\csname xref$#2\endcsname%
241 \ifx\@tempa\relax%
242 \PackageError{xref}{Unknown ref kind `#2'}%
2028c55c
MW
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}%
74754fa2 246 \else \@tempa{#1}{#2:#3}%
e8f3554e
MW
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}
ae8b308b 281\defxref*{eq}{#1{#4}{(#2{#4})}}
e8f3554e
MW
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