Post by i***@gmail.comI am trying to chain another set of macros to the end of the \label,
\ref, and \pageref macros. Basically, I want to do later referencing
analysis in perl
This issue seems to be closely related to another thread started
by you back in 2004:
| From: ***@anderson.ucla.edu (ivo welch)
| Newsgroups: comp.text.tex
| Subject: detect forward references?
| Date: 12 Jun 2004 09:34:40 -0700
| Message-ID: <***@posting.google.com>
|
| hi: how would I systematically detect forward references? that is,
| in my 600 page book, I would like to know which labels are referenced
| before they are created. There are of course includes and inputs in
| various places. I would like to have the ability to just check that
| they make sense.
|
| sincerely, /iaw
Post by i***@gmail.comsuch as what labels are used most often, where I have
useless labels, where I have forward references, etc.
"useless" label or "unused label"?
There are situations where a label within your document might
get defined but never used for referencing within your document.
E.g., due to label-import via xr/xr-hyper-package while the
"unused" label in question is used by the other document...
Post by i***@gmail.comI plan to post
this for public consumption once it works). Therefore I have written a
short style file to just write every encounter to an '.mrl' file, and
use whatever the macros were. Alas, as soon as I usepackage hyperref,
it no longer works. The file is created, but nothing is ever written
to it.I believe hyperref prevents the chaining.
I experienced similar problems when playing around with the
referencing-mechanism: Hyperref loads the nameref-package by
means of \AtBeginDocument. nameref redefines the referencing-
macros. This means there are great chances that your
redefinitions of the referencing-macros will get overridden by
the stuff that was placed into/launched by the
\AtBeginDocument-Hook.
You need to make sure that your changes take place after
loading nameref while nameref
- could be loaded in the preamble without hyperref,
- 's loading could be launched by hyperref via \AtBegindocument
- ...
The best strategy is possibly making the user read the fine
manual and follow the instruction of not loading the package
before other packages like hyperref/nameref etc.
Another strategy might be putting your changes/patches into the
\AtBeginDocument-hook while issuing a warning in case mrl.sty is
loaded _before_ the hyperref-package:
\@ifpackageloaded{hyperref}{%
\AtBeginDocument{%
<TAKE ACTION IN THE WAY WHICH IS NECESSARY WITH HYPERREF>
}%
}{%
\AtBeginDocument{%
\@ifpackageloaded{hyperref}%
{%
\PackageWarningNoLine
{mrl}%
{Load package `mrl' after package `hyperref'}%
\stop % push the panic-button
}{}%
}%
\AtBeginDocument{%
<TAKE ACTION IN THE WAY WHICH IS NECESSARY WITHOUT HYPERREF>
}%
}%
Post by i***@gmail.com% [1] squirrel away whatever the original definition is
\let\labelmrl\label
\let\refmrl\ref
\let\pagerefmrl\pageref
% [2] use the original, but also write it out to the .mrl file
\renewcommand\label[1]{\labelmrl{#1}\mrlwrite{label*#1}}
\renewcommand\ref[1]{\refmrl{#1}\mrlwrite{ref*#1}}
\renewcommand\pageref[1]{\pagerefmrl{#1}\mrlwrite{pageref*#1}}
What about
- \nameref
- \titleref
- \autoref
- ams-package(s)
- babel-package(s)
- zref-package
- varioref-package (which afaik create \labels on the fly)
- refcount-package
- xr/xr-hyper-package
[ - labelcas-package
- elidpref-package ] ;-)
- "from-scratch" user-defined referencing-macros ... ?
With LaTeX kernel-macros and hyperref, referencing-workflow is:
\label{<label>} in main tex yields
\newlabel{<label>}{{}{}{}{}{}} in aux which yields defining
\r@<label> -> {<section-number>}
{<page-number>}
{<section-name>}
{<href-anchor>}
{<external URL>}
All referencing-macros "expand" \r@<label> and "grab" the
appropriate arguments...
About two years ago, when this 2004-thread took place, there was
this "PrvRefLg"-thing and I failed when thinking about replacing
it by a mechanism where you don't need to change each single
referencing-macro:
I thought about redefining \label and \newlabel:
1) Redefine \label so that any usage of \label would be noted
within an external file.
2) Redefine \newlabel so that \r@<label> gets defined to also
note its usage within the same external file.
On the second glimpse I could not see a feasible approach for
2) as \r@<label> is supposed to be usable in expandable contexts
also (->refcount, hyperref,...) while "\write" etc is not
expandable.
I think currently you cannot get away without modifying each
referencing-macro/each user-macro which is intended for calling
instances of \r@<label>-macros.
This is fun because there are already many packages which rede-
fine the LaTeX-kernel's referencing-macros. For doing the right
patching, you may need to track down all possible combinations
of how those packages might be loaded.
Also you never know if/how the user does introduce her own
referencing-macros from scratch and thus cannot prepare for this
case at all.
A (cumbersome) strategy for making sure that your package is
loaded as the last one, could be: Nest something like the
following where the actual changes/patches go into the innermost
nesting-branches, enclosed into "\AtBeginDocument".
\newcommand\@ifpackageloadedLaterloadedwarn[3]{%
\@ifpackageloaded{#1}{%
#2%
}{%
\AtBeginDocument{%
\@ifpackageloaded{#1}%
{%
\PackageWarningNoLine
{mrl}%
{Load package `mrl' after package `#1'}%
\stop % push the panic-button
}{}%
}%
#3%
}%
}%
Could be put together to something like:
\@ifpackageloadedLaterloadedwarn{hyperref}{%
\AtBeginDocument{%
% REDEFINE REFERENCING MACROS AS NECESSARY WITH
% HYPERREF AND NAMEREF
}%
}{%
\@ifpackageloadedLaterloadedwarn{nameref}{%
\AtBeginDocument{%
% REDEFINE REFERENCING MACROS AS NECESSARY WITHOUT
% HYPERREF BUT WITH NAMEREF
}%
}{%
\AtBeginDocument{%
% REDEFINE REFERENCING MACROS AS NECESSARY WITHOUT
% BOTH HYPERREF AND NAMEREF
}%
}%
}%
You could introduce more nesting-levels, taking into account that
some packages "provide support" for other packages.
E.g., hyperref provides support for varioref in case varioref is
loaded...
If you decide for patching "\label" and all referencing-macros
in favor of a mechanism where expanding an instance of the
\label-macro or expanding an instance of a referencing-macro
(e.g., \ref, \pageref, \autoref...) leads to writing to an
external-file, I suggest making the redefined/patched variants
of these macros robust (\DeclareRobustCommand) so that instances
of these macros won't get expanded within \***@edef or
\***@write where an expandable "\write" must not occur.
Perhaps you wish to make writing the external file which is
intended for later evaluation via Perl (or possibly via some
other script which is also written in (La)TeX ) optional.
In this case you could implement a mechanism similar to
\addcontents and \@starttoc (the latter is called internally by
\tableofcontents, \listoffĂgures, listoftables etc).
The workflow with \addcontents is:
- \addcontents does write to the ".aux"-file an entry of the
pattern: \@writefile{<extension>}{<stuff>}
( e.g. \@writefile{toc}{This is a sentence.} )
- \@writefile does write <stuff> to the \write-register
"\tf@<extension>" only in case the register is defined/
allocated. Otherwise it does nothing.
- The ".aux"-file/s is (are) read at the beginning and the end
of compilation.
- When the aux-file(s) is read at the beginning of compilation,
the register \tf@<table-extension> does not yet exist, so
nothing happens when those \@writefile-entries come to be
executed.
- Maybe the register gets allocated during compilation (due to
some instance of "\@starttoc").
In this case reading the aux-file at the end of compilation
yields that the stuff in the \@writefile-entries is written
to that register/to the file which is associated to that
register.
Otherwise still nothing happens.
So when patching your macros, you can use the "\addcontents"-
macro for (indirectly) writing to your external file.
For enabling creation of your external file, you can use
something similar to "\@starttoc" (used within \tableofcontents,
\listoftables, \listoffigures) which does also allocate a new
\write-register but which does not input the external file.
[Alternatively you could just "neutralize" \@starttoc's
inputting-process by making sure that your external file
starts with "\endinput".]
Assuming that the file containing the list of defined/used
labels is called \jobname.rft, you can redefine your
referencing-commands to also do something like
\addcontents{rft}
{\string\labeldefine{<name of label>}{whatever else you need}}
respectively
\addcontents{rft}
{\string\labeluse{<name of label>}{whatever else you need}}
For enabling creation of \jobname.rft, you can define something
similar to \@starttoc:
\newcommand*\createRefUsageFile{%
\@bsphack
\begingroup
\@ifdefinable\***@rft{%
\***@filesw
\newwrite\***@rft
\immediate\openout\***@rft\jobname.rft\relax
\fi
}%
\endgroup
\@esphack
}%
[
Alternatively:
\AtBeginDocument{%
\addcontents{rft}{\string\endinput}
}%
\newcommand*\createRefUsageFile{%
\@bsphack
\@starttoc{rft}
\@esphack
}%
]
If \createRefUsageFile appears somewhere in your documents,
\jobname.rft gets created and you can use it for further
evaluation e.g., by Perl or by some other TeX-script where
"\labeldefine" and "\labeluse" are defined control-sequences.
(You could even input it into the main-tex-file while defining
\labeldefine / \labeluse to write messages to the log-file...)
For reloading into TeX a file which starts with "\endinput", you
can locally redefine \endinput:
\begingroup
\let\endinput\endgroup
\input{<file with leading "\endinput">}
Seems to work sometimes.
Good luck.
Ulrich