From e8f3554e4772f35bf1a7df96839bc2aeb3f0e028 Mon Sep 17 00:00:00 2001
From: Mark Wooding <mdw@distorted.org.uk>
Date: Mon, 9 Apr 2007 18:57:59 +0100
Subject: [PATCH] mdwref: New package for typesetting cross-references
 automagically.

---
 Makefile.m4  |   3 +-
 mdwref.dtx   | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mdwtools.ins |   1 +
 3 files changed, 240 insertions(+), 1 deletion(-)
 create mode 100644 mdwref.dtx

diff --git a/Makefile.m4 b/Makefile.m4
index fd88bc8..f52c85c 100644
--- a/Makefile.m4
+++ b/Makefile.m4
@@ -34,7 +34,7 @@ pkgdocdir = ${texmfdir}/doc/latex/${PACKAGE}
 define(`addsuffix', `patsubst(`$1', `\>', `$2')')
 define(`BASE', `\
 	at centre cmtt colour crypto doafter exercise footnote mdwkey \
-	mdwlist mdwmath mdwtab mdwthm poetry slowbox sverb syntax')
+	mdwlist mdwmath mdwref mdwtab mdwthm poetry slowbox sverb syntax')
 
 AUX = mdwtools.tex gpl.tex
 SRC = addsuffix(BASE, `.dtx')
@@ -52,6 +52,7 @@ OBJ = \
 	mdwkey.sty \
 	mdwlist.sty \
 	mdwmath.sty \
+	mdwref.sty \
 	mdwtab.sty mathenv.sty mtcolour.sty mtcolor.sty \
 	mdwthm.sty mdwmargin.thm \
 	poetry.sty \
diff --git a/mdwref.dtx b/mdwref.dtx
new file mode 100644
index 0000000..f1da45c
--- /dev/null
+++ b/mdwref.dtx
@@ -0,0 +1,237 @@
+% \begin{meta-comment}
+%
+% $Id: mdwref.dtx,v 1.3 2003/11/10 14:43:48 mdw Exp $
+%
+% Slightly fancy cross-referencing stuff
+%
+% (c) 2007 Mark Wooding
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwref package -- slightly fancy cross-referencing stuff
+%% Copyright (c) 2007 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{mdwref}
+%<+package>                [2007/04/09 1.01 Cross-referencing]
+% \end{meta-comment}
+%
+% ^^A\CheckSum{96}
+%% \CharacterTable
+%%  {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
+%%   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
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{mdwref}
+\usepackage{mdwtab}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+%
+% \section{User guide}
+%
+% I always name my cross-reference labels with a prefix telling me what kind
+% of thing they are.  A figure might be |fig:foo| or a table |tab:bar|.  When
+% I refer to the thing, then, I basically have to repeat myself:
+% `|see table~\ref{tab:bar}|'.  Kinda silly.
+%
+% \DescribeMacro\xref
+% The |\xref| command understands my prefixing system.  I can say
+% `|\xref{tab:bar}|' and it inserts a reference to `table~4', for example.
+% This is, of course, useless if you want to put the reference at the
+% beginning of a sentence: `Table~4 shows\dots'.
+% \DescribeMacro\Xref
+% The |\Xref| command (note the initial capital) handles this properly, so
+% you just type `|\Xref{tab:bar} shows|\dots'.
+%
+% The full syntax of the |\xref| command is like this.
+% \begin{grammar}
+% <xref-command> ::= \[[
+% "\\xref"
+% \[ "[" <mangle> "]" \]
+% "{" <reference> "}"
+% \]]
+% \end{grammar}
+% The optional \<mangle> argument is a command to be applied to the generated
+% text: it \emph{must} be a single token.  Rather than printing `table', or
+% whatever, it prints \syntax{<mangle>"{table}"}.
+% The most obvious application of this is the |\Xref| command, which uses a
+% helper |\toupper|.
+% \DescribeMacro\toupper
+% The call \syntax{"\\toupper{"<stuff>"}"} typesets \<stuff> with the first
+% character in uppercase.  So |\Xref| is defined simply as\footnote{Modulo
+%   the fact that the author is a dreadful \TeX\ hacker.}
+% \begin{listing}
+%\newcommand{\Xref}[1]{\xref[\toupper]{#1}}
+% \end{listing}
+%
+% All that remains is to define the strings to be typeset for various kinds
+% of labels.
+% \DescribeMacro\defxref
+% For this, we use the |\defxref| command:
+% \begin{grammar}
+% <definition> ::= \[[
+% "\\defxref"
+% "{" <prefix> "}"
+% "{" <string> "}"
+% \]]
+% \end{grammar}
+% The \<prefix> is what you put on the front of your labels; the \<string> is
+% the string to be typeset by |\xref|.
+%
+% A number of useful prefixes are already defined, following my usual
+% preferences; they're shown in \xref{tab:defs}.
+% \begin{table}
+%   \def\i#1#2{\texttt{#1}&\texttt{#2}\\}
+%   \begin{tabular}[C]{ll} \hlx*{hv}
+%   \textbf{Prefix} & \textbf{Text} \\ \hlx{vhv}
+%   \csname xref@defs\endcsname
+%   \hlx*{vh}\end{tabular}
+%   \caption{Predefined reference prefixes}
+%   \label{tab:defs}
+% \end{table}
+%
+% \implementation
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% The following quark will be useful.
+%    \begin{macrocode}
+\def\q@delim{\q@delim}
+%    \end{macrocode}
+%
+% \begin{macro}{\defxref}
+% Defining prefixes is easy.  We store the text for each prefix in a macro
+% called \syntax{"\\xref$"<prefix>}.  The only catch is that, for the
+% purposes of generating \xref{tab:defs}, we maintain a list of the prefixes
+% which have been defined so far, but this is fairly easy.
+%    \begin{macrocode}
+\def\defxref#1#2{%
+  \toks@\expandafter{\xref@defs\i{#1}{#2}}\xdef\xref@defs{\the\toks@}%
+  \expandafter\def\csname xref$#1\endcsname{#2}%
+}
+%    \end{macrocode}
+% The list is obviously empty initially.
+%    \begin{macrocode}
+\gdef\xref@defs{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\xref}
+% We're meant to typeset a reference.  The first job is to see whether
+% there's an optional argument.  If so, grab it; otherwise |\relax| will do.
+%    \begin{macrocode}
+\def\xref{\@ifnextchar[\xref@{\xref@[\relax]}}
+\def\xref@[#1]#2{\xref@@{#1}#2:\q@delim:\q@delim:\q@delim\q@delim}
+%    \end{macrocode}
+% Right; now we abuse \TeX's argument parser to pick apart the reference
+% label, which ought to have the form \syntax{<prefix>":"<suffix>}.
+%    \begin{macrocode}
+\def\xref@@#1#2:#3:\q@delim#4\q@delim\q@delim{%
+%    \end{macrocode}
+% So, |#1| is the optional command, or |\relax|.  |#2| should be the
+% prefix, and |#3| the suffix.  However, if the string doesn't have any
+% colons in, then |#3| will be |\q@delim|.  This is easy to check for using
+% |\ifx|.
+%    \begin{macrocode}
+  \def\@tempa{#2}\def\@tempb{#3}%
+  \ifx\@tempb\q@delim%
+    \PackageError{xref}{Bad ref syntax}%
+  \else%
+    \expandafter\let\expandafter\@tempa\csname xref$#2\endcsname%
+    \ifx\@tempa\relax%
+      \PackageError{xref}{Unknown ref kind `#2'}%
+    \else%
+      \toks@{#1}\toks\tw@\expandafter{\@tempa}%
+      \edef\next@{\the\toks@{\the\toks\tw@}}%
+      \next@~\ref{#2:#3}%
+    \fi%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\toupper}
+% That's the difficult stuff done.  Uppercasing is a matter of picking out
+% the first letter and passing it to \TeX's |\uppercase| primitive.
+%    \begin{macrocode}
+\def\toupper#1{\toupper@#1}
+\def\toupper@#1{\uppercase{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\Xref}
+% As promised, |\Xref| is very easy.
+%    \begin{macrocode}
+\def\Xref{\xref[\toupper]}
+%    \end{macrocode}
+% \end{macro}
+%
+% Now all that remains is to initialize the table of prefix strings.
+%    \begin{macrocode}
+\defxref{ch}{chapter}
+\defxref{app}{appendix}
+\defxref{sec}{section}
+\defxref{def}{definition}
+\defxref{th}{theorem}
+\defxref{lem}{lemma}
+\defxref{prop}{proposition}
+\defxref{cor}{corollary}
+\defxref{fig}{figure}
+\defxref{tab}{table}
+\defxref{eq}{equation}
+\defxref{i}{item}
+\defxref{ex}{exercise}
+%    \end{macrocode}
+% And we're done!
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+% \nopagebreak
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/mdwtools.ins b/mdwtools.ins
index 0ad6ac2..e842fca 100644
--- a/mdwtools.ins
+++ b/mdwtools.ins
@@ -81,6 +81,7 @@ IMPORTANT NOTICE
 	\mdwf {exercise.sty}	{\from {exercise.dtx} {package}}
 	\mdwf {slowbox.sty}	{\from {slowbox.dtx}  {package}}
 	\mdwf {mdwmargin.thm}	{\from {mdwthm.dtx}   {thmstyle}}
+	\mdwf {mdwref.sty}	{\from {mdwref.dtx}   {package}}
 	\mdwf {poetry.sty}	{\from {poetry.dtx}   {package}}
 }
 
-- 
2.11.0

