%<+package> [2020/09/06 1.14.0 Cross-referencing]
% \end{meta-comment}
%
-% ^^A\CheckSum{96}
+% \CheckSum{131}
%% \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
%\newcommand{\Xref}[1]{\xref[\toupper]{#1}}
% \end{listing}
%
-% \DescribeMacro\formatxref
-% The reference itself is 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.)
-%
% All that remains is to define the strings to be typeset for various kinds
% of labels.
% \DescribeMacro\defxref
% \]]
% \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}
%
% \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}
-\gdef\xref@defs{}
+\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}
-\def\formatxref#1#2#3{%
- \ifx\hyperref\@@undefined #1{#2}~\ref{#3}%
- \else \hyperref[#3]{#1{#2}~\ref*{#3}}\fi%
-}
+\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}
{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%
- \toks@\expandafter{\@tempa}%
- \edef\next@##1{##1{\the\toks@}}%
- \next@{\formatxref{#1}}{#2:#3}%
+ \else \@tempa{#1}{#2:#3}%
\fi%
\fi%
}
\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}