          The showlabels package

Norman Gray

                 norman@astro.gla.ac.uk

Version 1.3e, 2001/05/31

This package introduces no new commands, it just helps you keep track of all the labels by putting the name of the new label into the margin whenever either the \label command is used, or an equation is automatically numbered. There are therefore no usage instructions. You invoke this package with the command \usepackage{showlabels} in the preamble, and you may give the options inner or outer (the default) to have the labels placed in the inner or outer margin of the text. If you don’t use the twoside option, then all pages are ‘right-hand’ pages, and the ‘outer margin’ is the right hand one.

The package will also work in the presence of the twocolumn option. In this case, the options inner and outer will be ignored, and the label will be placed in the nearer margin.

If you want to change the font the labels appear in, redefine the \showlabelfont command. For example, to have labels in a slanted font, you could include the

definition \renewcommand{\showlabelsfont}{\small\slfamily} in the pream-

ble of your document.

Compatibility with other packages

The {showlabels} package works by redefining the \label command, along with

the internal L^{A}TEX commands \@eqnnum, \@makecaption and \maketag@@@ (for

{amsmath}). All the other commands it defines are ‘hidden’ by prefixing them with ‘SL@’, with the exception of the user command \showlabelsfont. Each of the three redefined commands carefully includes its previous definition. The {showlabels} package should therefore come last of the packages you include using

\usepackage.

In version 1.1, the package was modified to conform to the slightly different mechanism that amsmath uses to produce equation numbers. I don’t habitually use amsmath, so I won’t discover any bugs or weaknesses with its support here, and I’d consequently be glad to be informed of any that appear. Do note that the \usepackage{showlabels} command must appear after the \usepackage{amsmath} if it is to detect that you are using the {amsmath} package. Note also that, since these additions appeared, AMS-L^{A}TEX and the amstex package seem to have been declared ‘obsolete’ in favour of the amsmath package. This package now claims conformance with the amsmath package alone, though it will probably work with older versions in fact.

In version 1.3e, the program became compatible with the {hyperref} package in particular, and in general with other packages which themselves modify the \label command. This will work, however, only if the {showlabels} package is loaded after other packages which do this. Notwithstanding Sebastian Rahtz’s excellent general advice on this, {showlabels} should be loaded after {hyperref}.

For reasonably obvious reasons, this package will not work at all well with the {multicol} package, and for possibly less obvious reasons, it won’t work with the leqno option either (at some point it should be modified to at least recognise and warn of the conflict in either case, though it’s not obvious to me how to do that).

The package might still work with L^{A}TEX2.09, but that’s neither supported, nor even still tested.

This software is copyright, 1999, 2001, Norman Gray. It is released under the terms of the GNU General Public Licence. See the copyright declaration at the top of file showlabels.dtx, and the file LICENCE for the licence conditions. You can

find an online copy of the GPL at <http://www.gnu.org/copyleft/gpl.html>.

History and Credits

For version 1.3, I received comments and bug reports from:

         David R. Leal Valmana <david@quijote.uc3m.es>
                 Sungmo Park <smp@dingo.etri.re.kr>
                 Olivier Michel <Olivier.Michel@lri.fr>
                    Jiri Vesely <jvesely@karlin.mff.cuni.cz>
                 Patrick Sibille <sibille@amoco.saclay.cea.fr>
                Hagen Kleinert <kleinert@physik.fu-berlin.de>
           Francis M. C. Ching <fmcching@kingcong.uwaterloo.ca>
              Michael Friendly <friendly@hotspur.psych.yorku.ca>
                 lester l. helms <l-helms@math.uiuc.edu>

Many thanks to all.

Back in 29-Jan-92, Darrel Hankerson <hank@ducvax.auburn.edu>, made the update to NFSS, and changed the name to ‘showlabel.sty’.

The package was originally released by me on 21-Sep-91, under the name

labels.sty.

1 Implementation

1 ⟨∗package⟩

Before we do anything else, find out if we’re using {amsmath}…. Note that, since these additions appeared, AMS-L^{A}TEX and the amstex package seem to have been declared ‘obsolete’. This package now claims conformance with the amsmath package.

 2 \newif\ifSL@AMS
 3 \expandafter\ifx\csname maketag@@@\endcsname\relax
 4 \SL@AMSfalse
 5 \else
 6 \SL@AMStrue
 7 \typeout{with amsmath equation tags}
 8 \fi

\@eqnnum This replacement for \@eqnnum will produce a note, sticking into the margin beside the equation number, showing the equation’s label. \SL@labeln@me is initialised to \relax, redefined within the \label macro, and reset to \relax here. If it’s already equal to \relax here, the equation number hasn’t been labelled, and so ‘???’ is put in the margin. Don’t do this for the {amsmath} case as it artfully incorporates the \maketag@@@ mechanism into a redefined \@eqnnum.

 9 \ifSL@AMS

{amsmath} uses \maketag@@@, to form tags in equations. All we have to do is hook into the \maketag@@@ macro, and use \df@label, which is pre-defined with the current label name.

10 \let\SL@maketag@@@=\maketag@@@
11 \def\maketag@@@#1{\SL@maketag@@@{#1}%
12 \ifx\df@label\@empty
13 %    \SL@eqnlrtext{???}%
14 \else
15  \SL@eqnlrtext{\df@label}%
16 \fi}
17 \else

The ‘normal’ case, without {amsmath}.

18 \let\SL@eqnnum=\@eqnnum
19 \def\@eqnnum{\SL@eqnnum
20 \expandafter\ifx\SL@labeln@me\relax
21 %    \SL@eqnlrtext{???}%
22 \else
23  \SL@eqnlrtext{\SL@labeln@me}%
24  \global\def\SL@labeln@me{\relax}%
25 \fi}

And initialise the value of \labeln@me to \relax, so that \@eqnnum starts off behaving the right way.

26 \global\def\SL@labeln@me{\relax}
27 \fi

Labels are printed with the font specified by \showlabelfont, which can be overridden within the document:

28 \def\showlabelfont{\small\tt}

Leave this as \small\tt, to avoid a pointless incompatibility with L^{A}TEX2.09.

For the benefit of \SL@prlabelname, define \SL@gobblethree to do nothing other than eat three tokens.

29 \def\SL@gobblethree#1#2#3{}

\SL@prlabelname Expansion is label name with all catcodes ‘other’ (Appendix D trickery abounds!). Use \r@#1, rather then just \#1 to avoid defining any new control sequences.

30 \def\SL@prlabelname#1{%
31 \expandafter\expandafter\expandafter\SL@gobblethree
32  \expandafter\string\csname r@#1\endcsname}

\@makecaption Simple replacement for the \@makecaption command. This simply issues the original \@makecaption command after redefining \label. This does not put the label name in the margin (that’s too complicated for the moment), but instead inserts it as part of the caption.

33 \let\SL@makecaption\@makecaption
34 \long\def\@makecaption#1#2{{\def\label##1{{\showlabelfont
35 \{\SL@prlabelname{##1}\}\space}\SL@label{##1}}%

… and follows it with the original, saved, \@makecaption.

36 \SL@makecaption{#1}{#2}}}

\label This is the central bit of this package. Using the \AtBeginDocument hook, we will shortly \let the \label command equal to \SL@label at the same time as we save the original \label command in \SL@origlabel.

Depending on the mode, put the current label name in the margin in one of a variety of ways. First of all, issue the saved \SL@origlabel command.

37 \def\SL@label#1{\@bsphack
38 \SL@origlabel{#1}%

In maths mode, produce a label name alongside the equation number. If we’re not using {amsmath}, then save the label name in \SL@labelname. If we are using {amsmath}, then we don’t have to worry, because it’s saved in \df@label for us.

39 \ifmmode
40  \ifSL@AMS\else
41  \xdef\SL@labeln@me{\SL@prlabelname{#1}}%
42  \fi

Otherwise, create a box with zero height and depth, and the same width as the page. Put all this in braces, to contain the setting of \box0 (which probably shouldn’t be necessary).

43 \else
44  {\setbox0=\vbox to 0pt{\vss
45  \hbox to \columnwidth{\SL@lrtext{#1}}}%
46  \dp0=0pt

and attach it below the last one, using \nointerlineskip if we’re in vertical mode, or \vadjust otherwise.

47  \ifvmode
48  \nointerlineskip\box0\nobreak
49  \else
50  \vadjust{\box0\nobreak}%
51  \fi}%

That’s it. Finish off the \ifmmode and give the partner to \@bsphack.

52 \fi
53 \@esphack

54 }

Finally, arrange for this new definition \SL@label to supplant the original definition of \label. The obvious thing to do is simply to say \let\label\SL@label here, but this will lose if there are any other packages loaded after this one, which also redefine \label (for example, {hyperref}). Therefore, use the \AtBeginDocument hook to do this at the last moment, after any subsequent redefinitions.

55 \AtBeginDocument{\let\SL@origlabel\label \let\label\SL@label}

\margintext Set the actual text of the label. Use \SL@prlabelname here: without this, a label command given outside of an equation or a \caption will appear wrongly if the label has things like underscores within it.

56 \def\SL@margintext#1{{\showlabelfont\{\SL@prlabelname{#1}\}}}

But where is the marginal text actually set? It can be in the left margin, the right one, or can alternate. \SL@lrtext, used in the \vbox above, is set, under

the control of \if@outerlabels below, to one of \SL@lefttext, \SL@righttext
or \SL@alternatetext.
\SL@righttext
\SL@lefttext
57 \def\SL@righttext#1{\hfill\rlap{\quad\SL@margintext{#1}}}
58 \def\SL@lefttext #1{\llap{\SL@margintext{#1}\quad}\hfill}

The code for \SL@alternatetext doesn’t work perfectly, as it sometimes manages to get things on the wrong side of the text near the top of a new page. This is a venial slip, however, as this package should never be used in a final version.

\SL@alternatetext
59 \def\SL@alternatetext{%
60 \if@outerlabels
61  \ifodd\c@page
62  \let\SL@next\SL@righttext\else
63  \let\SL@next\SL@lefttext\fi
64 \else
65  \ifodd\c@page
66  \let\SL@next\SL@lefttext\else
67  \let\SL@next\SL@righttext\fi
68 \fi
69 \SL@next}

The case where the twocolumn option is set is slightly different. There we have to switch between placing the note in the left and right margins, depending on whether we’re setting the first or second column. This macro, and \SL@eqntwocoltext below, uses the switch \if@firstcolumn to decide whether it’s in the first or the second column of the text (I suppose it’ll get terribly confused if we use multicol.sty along with this). This is defined and maintained in the base file ltoutput.dtx. It’s not part of the defined interface, however (there doesn’t seem to be one, grump), so I don’t suppose we should really rely on it. There isn’t an option, however.

\SL@twocoltext
70 \def\SL@twocoltext{%
71 \if@firstcolumn
72  \let\SL@next\SL@lefttext
73 \else
74  \let\SL@next\SL@righttext
75 \fi
76 \SL@next}

We have very similar things for equations, except that they are set in place, rather than within a zero depth box. This code ASSUMES that equation numbers are going to be on the right hand side of the page. It should probably check for the existence of the leqno option (how?).

\SL@eqnrighttext
\SL@eqnlefttext
77 \def\SL@eqnrighttext#1{\rlap{\quad\SL@margintext{#1}}}
78 \def\SL@eqnlefttext #1{\hbox to 0pt{\kern -\columnwidth
79 \llap{\SL@margintext{#1}\quad}\hss}}

Now do the analogues for the equation numbers, in the case of the alternate page selection…

\SL@eqnalternatetext
80 \def\SL@eqnalternatetext{%
81 \if@outerlabels
82  \ifodd\c@page
83  \let\SL@next\SL@eqnrighttext\else
84  \let\SL@next\SL@eqnlefttext\fi
85 \else
86  \ifodd\c@page
87  \let\SL@next\SL@eqnlefttext\else
88  \let\SL@next\SL@eqnrighttext\fi
89 \fi
90 \SL@next}

… and the twocolumn option

\SL@eqntwocoltext
91 \def\SL@eqntwocoltext{%
92 \if@firstcolumn
93  \let\SL@next\SL@eqnlefttext
94 \else
95  \let\SL@next\SL@eqnrighttext
96 \fi
97 \SL@next}

To keep track of things, declare the \if@outerlabels switch, and set it true by default.

98 \newif\if@outerlabels
99 \@outerlabelstrue

We select between the various possibilities using the outer and inner options and, implicitly, the twoside option.

100 \DeclareOption{outer}{\@outerlabelstrue}
101 \DeclareOption{inner}{\@outerlabelsfalse}

Process any options that have been set.

102 \ProcessOptions

and use the values of \if@outerlabels and if@twoside which may have been set by those options, to set \SL@lrtext to be the appropriate control sequence. The presence of the twocolumn option means that we ignore the inner and outer options.

103 \if@twocolumn
104 \let\SL@lrtext\SL@twocoltext
105 \let\SL@eqnlrtext\SL@eqntwocoltext
106 \else
107 \if@outerlabels
108  \if@twoside
109 \let\SL@lrtext\SL@alternatetext
110 \let\SL@eqnlrtext\SL@eqnalternatetext
111  \else
112  \let\SL@lrtext\SL@righttext
113  \let\SL@eqnlrtext\SL@eqnrighttext

114  \fi
115 \else
116  \if@twoside
117 \let\SL@lrtext\SL@alternatetext
118 \let\SL@eqnlrtext\SL@eqnalternatetext
119  \else
120  \let\SL@lrtext\SL@lefttext
121  \let\SL@eqnlrtext\SL@eqnlefttext
122  \fi
123 \fi
124 \fi

That’s us.

125 ⟨/package⟩