Fix dates and version numbers in the package files.
[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
MW
5%%
6%% This program is free software; you can redistribute it and/or modify
7%% it under the terms of the GNU General Public License as published by
8%% the Free Software Foundation; either version 2 of the License, or
9%% (at your option) any later version.
10%%
11%% This program is distributed in the hope that it will be useful,
12%% but WITHOUT ANY WARRANTY; without even the implied warranty of
13%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14%% GNU General Public License for more details.
15%%
16%% You should have received a copy of the GNU General Public License
17%% along with this program; if not, write to the Free Software
18%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19%%
20% \end{meta-comment}
21%
22% \begin{meta-comment} <Package preambles>
23%<+package>\NeedsTeXFormat{LaTeX2e}
24%<+package>\ProvidesPackage{mdwref}
af8af7eb 25%<+package> [2020/09/06 1.14.0 Cross-referencing]
e8f3554e
MW
26% \end{meta-comment}
27%
28% ^^A\CheckSum{96}
29%% \CharacterTable
30%% {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
31%% 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
32%% Digits \0\1\2\3\4\5\6\7\8\9
33%% Exclamation \! Double quote \" Hash (number) \#
34%% Dollar \$ Percent \% Ampersand \&
35%% Acute accent \' Left paren \( Right paren \)
36%% Asterisk \* Plus \+ Comma \,
37%% Minus \- Point \. Solidus \/
38%% Colon \: Semicolon \; Less than \<
39%% Equals \= Greater than \> Question mark \?
40%% Commercial at \@ Left bracket \[ Backslash \\
41%% Right bracket \] Circumflex \^ Underscore \_
42%% Grave accent \` Left brace \{ Vertical bar \|
43%% Right brace \} Tilde \~}
44%%
45%
46% \begin{meta-comment}
47%
48%<*driver>
49\input{mdwtools}
50\describespackage{mdwref}
51\usepackage{mdwtab}
52\mdwdoc
53%</driver>
54%
55% \end{meta-comment}
56%
57%^^A-------------------------------------------------------------------------
58%
59% \section{User guide}
60%
61% I always name my cross-reference labels with a prefix telling me what kind
62% of thing they are. A figure might be |fig:foo| or a table |tab:bar|. When
63% I refer to the thing, then, I basically have to repeat myself:
64% `|see table~\ref{tab:bar}|'. Kinda silly.
65%
66% \DescribeMacro\xref
67% The |\xref| command understands my prefixing system. I can say
68% `|\xref{tab:bar}|' and it inserts a reference to `table~4', for example.
69% This is, of course, useless if you want to put the reference at the
70% beginning of a sentence: `Table~4 shows\dots'.
71% \DescribeMacro\Xref
72% The |\Xref| command (note the initial capital) handles this properly, so
73% you just type `|\Xref{tab:bar} shows|\dots'.
74%
75% The full syntax of the |\xref| command is like this.
76% \begin{grammar}
77% <xref-command> ::= \[[
78% "\\xref"
79% \[ "[" <mangle> "]" \]
80% "{" <reference> "}"
81% \]]
82% \end{grammar}
83% The optional \<mangle> argument is a command to be applied to the generated
84% text: it \emph{must} be a single token. Rather than printing `table', or
85% whatever, it prints \syntax{<mangle>"{table}"}.
86% The most obvious application of this is the |\Xref| command, which uses a
87% helper |\toupper|.
88% \DescribeMacro\toupper
89% The call \syntax{"\\toupper{"<stuff>"}"} typesets \<stuff> with the first
90% character in uppercase. So |\Xref| is defined simply as\footnote{Modulo
91% the fact that the author is a dreadful \TeX\ hacker.}
92% \begin{listing}
93%\newcommand{\Xref}[1]{\xref[\toupper]{#1}}
94% \end{listing}
95%
e0464890
MW
96% \DescribeMacro\formatxref
97% The reference itself is typeset by calling
98% \syntax{"\\formatxref{"<mangle>"}{"<string>"}{"<label>"}"}, which can do as
99% it pleases: the \<mangle> token is from the |\xref| invocation; the
100% \<string> is category of thing being referred to (as established by
101% |\defxref| below); and \<label> is the label, again from |\xref| . The
102% default behaviour is to print
103% \syntax{<mangle>"{"<string>"}~\\ref{"<label>"}"}, but this can be
104% overridden.
105% (Not quite true: in fact, the default does something better if
106% \package{hyperref} is detected, but the idea is basically the same.)
107%
e8f3554e
MW
108% All that remains is to define the strings to be typeset for various kinds
109% of labels.
110% \DescribeMacro\defxref
111% For this, we use the |\defxref| command:
112% \begin{grammar}
113% <definition> ::= \[[
114% "\\defxref"
115% "{" <prefix> "}"
116% "{" <string> "}"
117% \]]
118% \end{grammar}
119% The \<prefix> is what you put on the front of your labels; the \<string> is
120% the string to be typeset by |\xref|.
121%
122% A number of useful prefixes are already defined, following my usual
123% preferences; they're shown in \xref{tab:defs}.
124% \begin{table}
125% \def\i#1#2{\texttt{#1}&\texttt{#2}\\}
126% \begin{tabular}[C]{ll} \hlx*{hv}
127% \textbf{Prefix} & \textbf{Text} \\ \hlx{vhv}
128% \csname xref@defs\endcsname
129% \hlx*{vh}\end{tabular}
130% \caption{Predefined reference prefixes}
131% \label{tab:defs}
132% \end{table}
133%
134% \implementation
135% \section{Implementation}
136%
137% \begin{macrocode}
138%<*package>
139% \end{macrocode}
140%
141% The following quark will be useful.
142% \begin{macrocode}
143\def\q@delim{\q@delim}
144% \end{macrocode}
145%
146% \begin{macro}{\defxref}
147% Defining prefixes is easy. We store the text for each prefix in a macro
148% called \syntax{"\\xref$"<prefix>}. The only catch is that, for the
149% purposes of generating \xref{tab:defs}, we maintain a list of the prefixes
150% which have been defined so far, but this is fairly easy.
151% \begin{macrocode}
152\def\defxref#1#2{%
153 \toks@\expandafter{\xref@defs\i{#1}{#2}}\xdef\xref@defs{\the\toks@}%
154 \expandafter\def\csname xref$#1\endcsname{#2}%
155}
156% \end{macrocode}
157% The list is obviously empty initially.
158% \begin{macrocode}
159\gdef\xref@defs{}
160% \end{macrocode}
161% \end{macro}
162%
e0464890
MW
163% \begin{macro}{\formatxref}
164% Output a cross-reference in the right way.
165% \begin{macrocode}
166\def\formatxref#1#2#3{%
167 \ifx\hyperref\@@undefined #1{#2}~\ref{#3}%
168 \else \hyperref[#3]{#1{#2}~\ref*{#3}}\fi%
169}
170% \end{macrocode}
171% \end{macro}
172%
e8f3554e
MW
173% \begin{macro}{\xref}
174% We're meant to typeset a reference. The first job is to see whether
175% there's an optional argument. If so, grab it; otherwise |\relax| will do.
176% \begin{macrocode}
177\def\xref{\@ifnextchar[\xref@{\xref@[\relax]}}
178\def\xref@[#1]#2{\xref@@{#1}#2:\q@delim:\q@delim:\q@delim\q@delim}
179% \end{macrocode}
180% Right; now we abuse \TeX's argument parser to pick apart the reference
181% label, which ought to have the form \syntax{<prefix>":"<suffix>}.
182% \begin{macrocode}
183\def\xref@@#1#2:#3:\q@delim#4\q@delim\q@delim{%
184% \end{macrocode}
185% So, |#1| is the optional command, or |\relax|. |#2| should be the
186% prefix, and |#3| the suffix. However, if the string doesn't have any
187% colons in, then |#3| will be |\q@delim|. This is easy to check for using
188% |\ifx|.
189% \begin{macrocode}
190 \def\@tempa{#2}\def\@tempb{#3}%
191 \ifx\@tempb\q@delim%
192 \PackageError{xref}{Bad ref syntax}%
193 \else%
194 \expandafter\let\expandafter\@tempa\csname xref$#2\endcsname%
195 \ifx\@tempa\relax%
196 \PackageError{xref}{Unknown ref kind `#2'}%
197 \else%
e0464890
MW
198 \toks@\expandafter{\@tempa}%
199 \edef\next@##1{##1{\the\toks@}}%
200 \next@{\formatxref{#1}}{#2:#3}%
e8f3554e
MW
201 \fi%
202 \fi%
203}
204% \end{macrocode}
205% \end{macro}
206%
207% \begin{macro}{\toupper}
208% That's the difficult stuff done. Uppercasing is a matter of picking out
209% the first letter and passing it to \TeX's |\uppercase| primitive.
210% \begin{macrocode}
211\def\toupper#1{\toupper@#1}
212\def\toupper@#1{\uppercase{#1}}
213% \end{macrocode}
214% \end{macro}
215%
216% \begin{macro}{\Xref}
217% As promised, |\Xref| is very easy.
218% \begin{macrocode}
219\def\Xref{\xref[\toupper]}
220% \end{macrocode}
221% \end{macro}
222%
223% Now all that remains is to initialize the table of prefix strings.
224% \begin{macrocode}
225\defxref{ch}{chapter}
226\defxref{app}{appendix}
227\defxref{sec}{section}
228\defxref{def}{definition}
229\defxref{th}{theorem}
230\defxref{lem}{lemma}
231\defxref{prop}{proposition}
232\defxref{cor}{corollary}
233\defxref{fig}{figure}
234\defxref{tab}{table}
235\defxref{eq}{equation}
236\defxref{i}{item}
237\defxref{ex}{exercise}
238% \end{macrocode}
239% And we're done!
240% \begin{macrocode}
241%</package>
242% \end{macrocode}
243% \nopagebreak
244%
245% \hfill Mark Wooding, \today
246%
247% \Finale
248%
249\endinput