X-Git-Url: https://git.distorted.org.uk/~mdw/mdwtools/blobdiff_plain/e8f3554e4772f35bf1a7df96839bc2aeb3f0e028..ae8b308b845cb0f6ed748ceac7f9c49964788abf:/mdwref.dtx

diff --git a/mdwref.dtx b/mdwref.dtx
index f1da45c..0075487 100644
--- a/mdwref.dtx
+++ b/mdwref.dtx
@@ -1,38 +1,30 @@
-% \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
+%% Copyright (c) 2007, 2019 Mark Wooding
+%%
+%% This file is part of the `mdwtools' LaTeX package collection.
 %%
-%% 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.
+%% `mdwtools' 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.
+%% `mdwtools' 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.
+%% along with `mdwtools'.  If not, write to the Free Software Foundation,
+%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 %%
 % \end{meta-comment}
 %
 % \begin{meta-comment} <Package preambles>
 %<+package>\NeedsTeXFormat{LaTeX2e}
 %<+package>\ProvidesPackage{mdwref}
-%<+package>                [2007/04/09 1.01 Cross-referencing]
+%<+package>                [2020/09/06 1.14.0 Cross-referencing]
 % \end{meta-comment}
 %
 % ^^A\CheckSum{96}
@@ -115,15 +107,59 @@
 % \]]
 % \end{grammar}
 % The \<prefix> is what you put on the front of your labels; the \<string> is
-% the string to be typeset by |\xref|.
+% the string to be typeset by |\xref|.  Such references are typeset using
+% |\formatxref|, described below.
+%
+% For references that don't fit into this pattern, there's a more complex
+% definition syntax using |\defxref*|:
+% \begin{grammar}
+% <definition> ::= \[[
+% "\\defxref*"
+% "{" <prefix> "}"
+% "{" <expansion> "}"
+% \]]
+% \end{grammar}
+% The \<expansion> is given four arguments.
+% \begin{itemize}
+% \item |#1| is the name of a macro which should be given two arguments,
+%   respectively the reference name and the body of the hyperlink to
+%   generate.
+% \item |#2| is the name of a macro to apply to the reference name to typeset
+%   the actual reference.
+% \item |#3| is the \<mangle> token, or |\relax|.
+% \item |#4| is the reference name itself.
+% \end{itemize}
+%
+% \DescribeMacro\formatxref
+% Simple references are typeset by calling
+% \syntax{"\\formatxref{"<mangle>"}{"<string>"}{"<label>"}"}, which can do as
+% it pleases: the \<mangle> token is from the |\xref| invocation; the
+% \<string> is category of thing being referred to (as established by
+% |\defxref| below); and \<label> is the label, again from |\xref| .  The
+% default behaviour is to print
+% \syntax{<mangle>"{"<string>"}~\\ref{"<label>"}"}, but this can be
+% overridden.
+% (Not quite true: in fact, the default does something better if
+% \package{hyperref} is detected, but the idea is basically the same.)
 %
 % 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
+%     \texttt{ch}       & chapter $n$                                   \\
+%     \texttt{app}      & appendix $n$                                  \\
+%     \texttt{sec}      & section $n$                                   \\
+%     \texttt{def}      & definition $n$                                \\
+%     \texttt{th}       & theorem $n$                                   \\
+%     \texttt{lem}      & lemma $n$                                     \\
+%     \texttt{prop}     & proposition $n$                               \\
+%     \texttt{cor}      & corollary $n$                                 \\
+%     \texttt{fig}      & figure $n$                                    \\
+%     \texttt{tab}      & table $n$                                     \\
+%     \texttt{eq}       & ($n$)                                         \\
+%     \texttt{i}        & item $n$                                      \\
+%     \texttt{ex}       & exercise $n$                                  \\
 %   \hlx*{vh}\end{tabular}
 %   \caption{Predefined reference prefixes}
 %   \label{tab:defs}
@@ -143,18 +179,37 @@
 %
 % \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.
+% called \syntax{"\\xref$"<prefix>}, which takes two arguments: a \<mangle>
+% token (or |\relax|), and the reference name.
 %    \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}%
+\def\defxref{\@ifstar\defxref@raw\defxref@cooked}
+\def\defxref@cooked#1#2%
+  {\expandafter\def\csname xref$#1\endcsname##1##2{\formatxref{##1}{#2}{##2}}}
+\def\defxref@raw#1#2{%
+  \expandafter\edef\csname xref$#1\endcsname
+    {\noexpand\xrefdispatch\expandafter\noexpand\csname xref$$#1\endcsname}%
+  \expandafter\def\csname xref$$#1\endcsname##1##2##3##4{#2}%
 }
 %    \end{macrocode}
-% The list is obviously empty initially.
+% \end{macro}
+%
+% \begin{macro}{\xrefdispatch}
+%    \begin{macrocode}
+\def\xref@hyper#1{\hyperref[#1]}
+\def\xrefdispatch#1{%
+  \ifx\hyperref\@@undefined \def\@tempa{#1\@gobble\ref}%
+  \else \def\@tempa{#1\xref@hyper{\ref*}}%
+  \fi \@tempa%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\formatxref}
+% Output a cross-reference in the right way.
 %    \begin{macrocode}
-\gdef\xref@defs{}
+\def\formatxref{\xrefdispatch\xref@formatsimple}
+\def\xref@formatsimple#1#2#3#4#5{#1{#5}{#3{#4}~#2{#5}}}
+\def\xref@fallback#1{\formatxref\relax{?\texttt{#1}}{#1}}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -178,14 +233,17 @@
   \def\@tempa{#2}\def\@tempb{#3}%
   \ifx\@tempb\q@delim%
     \PackageError{xref}{Bad ref syntax}%
+      {A reference name doesn't contain a `:'-delimited prefix.  Did you %
+       mean to use plain \string\ref here?}%
+     \xref@fallback{#2}%
   \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}%
+        {The ref name's prefix `#2' is unknown: either it's been mistyped %
+         or there's a missing \string\defxref somewhere.}%
+     \xref@fallback{#2:#3}%
+    \else \@tempa{#1}{#2:#3}%
     \fi%
   \fi%
 }
@@ -220,7 +278,7 @@
 \defxref{cor}{corollary}
 \defxref{fig}{figure}
 \defxref{tab}{table}
-\defxref{eq}{equation}
+\defxref*{eq}{#1{#4}{(#2{#4})}}
 \defxref{i}{item}
 \defxref{ex}{exercise}
 %    \end{macrocode}
