% \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} %% %% 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>\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 % % % \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" % \[ "[" "]" \] % "{" "}" % \]] % \end{grammar} % The optional \ 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{"{table}"}. % The most obvious application of this is the |\Xref| command, which uses a % helper |\toupper|. % \DescribeMacro\toupper % The call \syntax{"\\toupper{""}"} typesets \ 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} % ::= \[[ % "\\defxref" % "{" "}" % "{" "}" % \]] % \end{grammar} % The \ is what you put on the front of your labels; the \ 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$"}. 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{":"}. % \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} % % \end{macrocode} % \nopagebreak % % \hfill Mark Wooding, \today % % \Finale % \endinput