Re: How to make custom linked cross-references?



The previous "improvement" introduced a bug.
Shame on me. Sorry.

Ulrich

=========================<start of file `custref.sty'>=========================
%
% Manual/macro-description can be found after \endinput so that it
% won't be read when loading the package. Also you don't need
% these '%'-characters all the time...
%
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\ProvidesPackage{custref}
[2006/05/03 v0.04 customize the appearance of ref-erenced counters]
\@ifdefinable\if@extractnum{%
\newif\if@extractnum
\global\@extractnumfalse
}%
\@ifdefinable\extractnum{%
\long\gdef
\extractnum\setrefphrases\refleadphrase#1\reftrailphrase{#1}%
}%
\newcommand*\nolinkref[1]{%
{%
\@ifundefined{@refstar}%
{{\resetrefphrases\ref{#1}}}%
{{\resetrefphrases\ref*{#1}}}%
}%
}%
\newcommand*\nolinkpageref[1]{%
{%
\@ifundefined{@pagerefstar}%
{{\resetrefphrases\pageref{#1}}}%
{{\resetrefphrases\pageref*{#1}}}%
}%
}%
\@ifdefinable\@innerextractpagerefnum{%
\def\@innerextractpagerefnum#1#2#3#4\@nil{%
\@expandtwoargs\@tempa{\noexpand#1}{#3}%
}%
}%
\newcommand*\extractpagerefnum[3][\newcommand*]{%
\begingroup
\expandafter\ifx\csname r@#3\endcsname\relax
\protect\G@refundefinedtrue
\@latex@warning{Reference `#3' on page \thepage\space
undefined}%
\endgroup
#1#2{0}%
\else
\def\@tempa{%
\def\@tempa####1{%
\endgroup#1####1%
}%
\@innerextractpagerefnum{#2}%
}%
\@extractnumtrue
\expandafter\expandafter
\expandafter\@tempa
\csname r@#3\endcsname\empty\empty\empty\empty\@nil
\fi
}%
\@ifdefinable\@innerextractrefnum{%
\def\@innerextractrefnum#1#2#3#4\@nil{%
\@expandtwoargs\@tempa{\noexpand#1}{#2}%
}%
}%
\newcommand*\extractrefnum[3][\newcommand*]{%
\begingroup
\expandafter\ifx\csname r@#3\endcsname\relax
\protect\G@refundefinedtrue
\@latex@warning{Reference `#3' on page \thepage\space
undefined}%
\endgroup
#1#2{0}%
\else
\def\@tempa{%
\def\@tempa####1{%
\endgroup#1####1%
}%
\@innerextractrefnum{#2}%
}%
\@extractnumtrue
\expandafter\expandafter
\expandafter\@tempa
\csname r@#3\endcsname\empty\empty\empty\empty\@nil
\fi
}%
\newcommand*\nolinkcustomizeref[3]{%
{%
\@ifundefined{@pagerefstar}%
{{\resetrefphrases\customizeref{#1}{#2}{#3}}}%
{{\resetrefphrases\customizeref*{#1}{#2}{#3}}}%
}%
}%
\newcommand*\refleadphrase{}%
\newcommand*\reftrailphrase{}%
\newcommand*\setrefphrases{}%
\newcommand*\resetrefphrases{%
\def\setrefphrases{}%
}%
\newcommand*\makerefcustomizeable[3]{%
\AtBeginDocument{%
\expandafter\renewcommand\expandafter*\csname p@#1\endcsname{%
\csname innerp@#1\expandafter\endcsname
}%
\expandafter\newcommand\expandafter*\csname innerp@#1\endcsname[1]{%
\expandafter\protect\csname setstandardphrases@#1\endcsname
\protect\setrefphrases
\protect\refleadphrase##1\protect\reftrailphrase
}%
\expandafter\newcommand
\expandafter*%
\csname setstandardphrases@#1\endcsname{%
\if@extractnum
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\extractnum}%
{%
\toks@{#2}\edef\refleadphrase{\the\toks@}%
\toks@{#3}\edef\reftrailphrase{\the\toks@}%
}%
}%
}%
}%
\@onlypreamble\makerefcustomizeable
\newcommand*\customizerefatnostar[3]{%
{%
\renewcommand*\setrefphrases{%
\toks@{#2}\edef\refleadphrase{\the\toks@}%
\toks@{#3}\edef\reftrailphrase{\the\toks@}%
}%
\ref{#1}%
}%
}%
\newcommand*\customizerefatstar[3]{%
{%
\renewcommand*\setrefphrases{%
\toks@{#2}\edef\refleadphrase{\the\toks@}%
\toks@{#3}\edef\reftrailphrase{\the\toks@}%
}%
\ref*{#1}%
}%
}%
\newcommand*\customizeref{\@ifstar\customizerefatstar\customizerefatnostar}%
\endinput
%%
%%
!!!! Here's the promised manual'n stuff !!!!

1. Legal stuff
==============
What is it?: A .sty-file for LaTeX2e, loadable via \usepackage
in the preamble.
Copyright: custref.sty [2006/05/03 v0.04] (C) Ulrich Diez
Author: Ulrich Diez (ulrich.diez@xxxxxxxxxxxxxxxxxxxxxxx)
Licence: LPPL
Submitted to CTAN: No. If somebody wants the package on CTAN,
please contact the author/current maintainer
via e-mail.
Maintenance-status: At may 03, 2006 this sty-file was maintained by
Ulrich Diez.
If somebody wants to overtake maintenance of
the file custref.sty, please contact the author/
current maintainer via e-mail.
Warranties: None. Usage is atyour own risk. If something breaks,
you may keep the pieces.

This file came into being due to a "feature-request" of Ted Pavlic
at comp.text.tex (usenet). For more details google the initial-message's
ID: <1146244592.766091.42210@xxxxxxxxxxxxxxxxxxxxxxxxxxxx> .

2. Changes to LaTeX-internals
=============================
Each <counter> defined by LaTeX2e's \newcounter-macro provides
a macro \p@<counter> which is intended for providing some
referencing-prefix. Usually it is empty. This package provides
means for redefining these \p@-macros and thus might break when
being used together with other packages which do the same.

3. Compatibility to other packages
==================================
I assume that this package will break some features of e.g. the
ifthen-package. The reason is: You cannot extract plain
"hyperlinkless" reference- or pagenumbers from the labels
with common methods any more as done e.g. by the ifthen-package
when it comes to comparing e.g. page-number-values of references/
labels.
In order to work around this restriction, this package provides
the macros \extractrefnum and \extractpagerefnum. Usage of these
macros is described in the "Usage"-section.

4. Change-History
=================
2006/05/01 v0.01 - Initial release
2006/05/02 v0.02 - Package: Support for extracting plain numerical values
------- from labels for numerical comparing / Added
macros \extractrefnum and \extractpagerefnum.
Documentation: Fixed some typo and added some
------------- \extract(page)refnum-examples.
2006/05/03 v0.03 - Package: Removed and changed some unnecessary grouping
------- in order to better preserve implicite kerning.
Also removed unnecessary \reset...-macros.
2006/05/03 v0.04 - Package: Restored erroneously removed \reset...-macros.
-------

5. Usage
========

Intro
-----

People often wish to customize the way in which counters appear when
referencing takes place. E.g., when referencing a section-counter,
\ref{sec-bla} should deliver something like "section~23", but when
referencing figures, \ref{fig} should deliver something like
"Fig.~(7)".
When looking at these examples, you can find that actually the
reference-text is made of three parts:
1. Some leading phrase, e.g. "Fig.~("
2. The reference-number as "spit out" by \the<counter>
3. Some trailing-phrase, e.g. ")"

package-loading
---------------
in the preamble via \usepackage{custref}

preamble-macro \makerefcustomizable
-----------------------------------

This package provides a preamble-macro
\makerefcustomizable{<counter>}
{<standard-leading-phrase>}
{<standard-trailing-phrase>}
by means of which you can specify the appearance for single counters
when they get referred by means of the \ref-macro.
That means:
You can -after package-loading- write in the preamble e.g.,
...
\makerefcustomizable{section}
{section~(}
{) of this book}
...

When writing in the document

...
% fifth-section
\section{some section}\label{thissection}
...
A reference to \ref{thissection}

, you will get:

A reference to section~(5) of this book

and in case of using hyperref, the hyperlinked phrase is
"section~(5) of this book"

macro \customizeref
-------------------

There is another macro \customizeref for usage within the document.
\customizeref takes 3 arguments:
\customizeref{<label>}
{<this time's-leading-phrase>}
{<this time's-trailing-phrase>}

When applying \customizeref to a label instead of \ref, the leading- and
trailing-phrase of the reference will be formed from \customizeref's
second and third argument _instead_ of what was provided to
\makerefcustomizeable as second and third argument.

You can -after package-loading- write in the preamble e.g.,
...
\makerefcustomizeable{section}
{section~(}
{) of this book}
...

When writing in the document

...
% fifth-section
\section{some section}\label{thissection}
...
A reference to \ref{thissection}

A reference to \customizeref{thissection}{A}{B}

, you will get:

A reference to section~(5) of this book

A reference to A5B

and in case of using hyperref, the first hyperlinked phrase
is "section~(5) of this book", the second is "A5B".

\nolinkref, \nolinkpageref, \nolinkcustomizeref
-----------------------------------------------
A weird but nonetheless existing problem/case is:
You might wish to take reference to yet another label within
\customizeref's second argument (<this time's-leading-phrase>)
or tird argument (<this time's-trailing-phrase>),
e.g. in order to create a hyperlink to only the fifth section of
your book from a phrase like
"chapter 7, section~(5), page 11 of this book".
Simply nesting \ref, \pageref or \customizeref won't work as this
would mean to create hyperlinks in hyperlinks which is not
supported by any driver/viewer yet. Therefore the macros
\nolinkref, \nolinkpageref, \nolinkcustomizeref are provided.
You can use them within the arguments of \customizeref.

\extractrefnum and \extractpagerefnum
-------------------------------------
Sometimes you might wish to extract the plain page- or reference-
number which is associated to a label. Just the numerical
value, no hyperlink or the like. The macros
\extractrefnum and \extractpagerefnum are intended for
facilitating this task.

[In the intro was said that a reference is made of 3 parts:
1. Some leading phrase (e.g. "Fig.~(")
2. The reference-number as "spit out" by \the<counter>
3. Some trailing-phrase (e.g. ")")
So the phrase "just the numerical value" means the second part
"The reference-number as spit out by \the<counter>." Thus
if \the<counter> was not defined to "spit out" a plain
arabic number, the "numerical value" won't be a plain number
either and you cannot use it sucessfully for e.g.
\ifnum-comparison!]

\extractrefnum[<defining-command>]{<macro>}{<label>}
\extractpagerefnum[<defining-command>]{<macro>}{<label>}

The macro \extractrefnum takes one optional and two mandatory
arguments: The first mandatory argument is the name of a newly
to be defined <macro>. The second mandatory argument is the name
of an existing <label>.
The <macro> will be defined to expand to the specified <label>'s
"reference-number as spit out by \the<counter>."
\extractpagerefnum works in the same way but delivers the
page-number-value instead.
Usually defining the <macro> will take place in terms of
\newcommand* . Within the optional argument you can specify
otherwise (e.g., [\def], [\global\def], [\providecommand],
[\DeclareRobustCommand],...) Useful when applying
\extract(page)refnum in a loop where always the same temporary
<macro> is to be (re)defined and thus \newcommand* cannot be
applied as that would lead to an unwanted 'already-defined-error'.

If numerical comparison to references , e.g. , via the
ifthen-package fails, you can try to work around this by first
putting the reference-numbers via \extract(page)refnum into
temporary macros and afterwards performing numerical comparison
to them. If you don't want to have temporary macros defined
permanently, you can write something like e.g.,

{% <-open group
\extractrefnum{\tempa}{<labelA>}%
\extractrefnum{\tempb}{<labelB>}
\expandafter}% closing the group and thus destroying the
% temporary macros will due to \expandafter happen
% right after evaluating the expression, before
% acting on one of the branches.
\ifnum\tempa<\tempb\relax
bla bla
\else
blu blu
\fi

IN CASE THAT LABEL IS UNDEFINED, A WARNING-MESSAGE OCCURS AND
<macro> WILL BE DEFINED TO EXPAND TO "0". During the very first
LaTeX-run no label is defined as labels get defined when reading
the aux-file which is not available yet during that run.

Another issue is:
-----------------
If you did not apply the macro \makerefcustomizeable to a
counter in the preamble, but take reference to it via
\customizeref{<label>}
{<this time's-leading-phrase>}
{<this time's-trailing-phrase>}
, the effect will be the same as if you had just written
\ref{<label>} into your source-code instead.

This is because \customizeref heavily uses and relies on
the p@-macros associated to the counters being (re)defined by
\makerefcustomizable in a special way.

6. hyperlinks across long lines
===============================
You can create very long link-phrases by means of this package.
If you do so, make sure that your viewer/driver supports hyper-
links with linebreaks. pdf(e)(La)TeX does. Most DVI-viewers do
not.

7. Usage-example
================

You can copy-paste the following example to some separate-file,
run it through (pdf)LaTeX and see how the package works:

\documentclass{article}

\usepackage{hyperref} % Actually hyperref is not a requirement
% but we want to see the hyperlinks.
\usepackage{custref}

\makerefcustomizeable{subsection}
{std-lead-phrase-for-sub-section~}
{~std-trail-phrase-for-sub-section}
\makerefcustomizeable{figure}
{std-lead-phrase-for-figure~}
{~std-trail-phrase-for-figure}

\begin{document}

\setcounter{page}{20}%
\parskip=\medskipamount\relax
\parindent=0pt\relax

\section{first section}
\label{firstsection}
This is first section.

\begin{figure}
This is a figure in first section.
\caption{figure's caption}
\label{fig}
\end{figure}

\subsection{first sub-section}
\label{firstsubsection}
This is first sub-section.

\newpage
\section{referencing}

subsection and figure are made ``customizeable''.
section is not.

This is reference to first sub-section:
\ref{firstsubsection}

This is customize-reference to first sub-section:
\customizeref{firstsubsection}
{customize~}
{~customize}

This is reference to first section:
\ref{firstsection}

This is (effectless) customize-reference to first section:
\customizeref{firstsection}
{customize~}
{~customize}

This is reference to figure:
\ref{fig}

This is customize-reference to figure:
\customizeref{fig}
{customize~}
{~customize}

This is customize-reference to figure with other references
in the arguments:
\customizeref{fig}%
{see page~\nolinkpageref{fig} for figure~}%
{ of the \nolinkcustomizeref{firstsection}{}{}$^{st}$ section}%


Plain reference-number of the label \emph{fig} is now in
\texttt{%
\string\tempa~=
\extractrefnum{\tempa}{fig}%
\meaning\tempa
}%

% Now \tempa is defined.
% We now have to use "\def" or something like
% "\let\tempa\relax\newcommand*" in order to prevent
% "already-defined-errors":

Plain reference-number of the label \emph{firstsubsection} is now in
\texttt{%
\string\tempa~=
\extractrefnum[\def]{\tempa}{firstsubsection}%
\meaning\tempa
}%

Plain reference-number of the label \emph{firstsection} is now in
\texttt{%
\string\tempa~=
\extractrefnum[\let\tempa\relax\newcommand]{\tempa}{firstsection}%
\meaning\tempa
}%

Plain page-number of the label \emph{fig} is now in protected
\def\spacereplace#1 #2 #3\nil{#1 #2\char`\ #3}%
\texttt{%
\extractpagerefnum[\DeclareRobustCommand]{\tempa}{fig}%
\string\tempa~=
\expandafter\spacereplace\meaning\tempa;\nil
\spacereplace{} \string\tempa{} ~=~\nil
\expandafter\meaning\csname tempa \endcsname
}%

Plain page-number of the label \emph{firstsubsection} is now in
\texttt{%
\string\tempa~=
\extractpagerefnum[\def]{\tempa}{firstsubsection}%
\meaning\tempa
}%

Plain page-number of the label \emph{firstsection} is now in
\texttt{%
\string\tempa~=
\extractpagerefnum[\def]{\tempa}{firstsection}%
\meaning\tempa
}%

\end{document}
%%
%% End of file `custref.sty'.
==========================<end of file `custref.sty'>==========================


.



Relevant Pages

  • Re: How to make custom linked cross-references?
    ... two macros \extractrefnum and \extractpagerefnum. ... If somebody wants the package on CTAN, ... A reference to section~of this book ... You might wish to take reference to yet another label within ...
    (comp.text.tex)
  • Re: How to make custom linked cross-references?
    ... If somebody wants the package on CTAN, ... a macro \p@which is intended for providing some ... A reference to section~of this book ... You might wish to take reference to yet another label within ...
    (comp.text.tex)
  • Bug with cross-references in VBA?
    ... But I need a caption with the option "Exclude label from caption". ... a cross reference manually, everything is still fine, but if I'm ... executing the same command as a macro Word 2003 is inserting nothing ...
    (microsoft.public.office.developer.vba)
  • Re: smart references of chapters in a book
    ... chapter followed by a dot appears, ... place) as argument to that other macro. ... That other macro will, when reference is called, check if the ... (which was the current chapter number at the time when the label ...
    (comp.text.tex)
  • Re: smart references of chapters in a book
    ... chapter followed by a dot appears, ... whenever the reference is inside the current chapter, ... place) as argument to that other macro. ... (which was the current chapter number at the time when the label ...
    (comp.text.tex)