4

I am trying to restrict refs' and labels' scopes to certain sections of a LaTeX document. Cf. this question.

I have a custom \locallabels{} command, modified from here, and a custom \eq{} command:

\documentclass{article}

\AtBeginDocument{%
  \let\origref\ref \let\origpageref\pageref \let\origlabel\label \let\origeqref\eqref \newcommand\locallabels[1]{%
    \renewcommand\label[1]{\origlabel{#1##1}}% ← notice the change here:
    \renewcommand\ref[1]{\origref{#1##1}}% ##1#1, not #1##1
    \renewcommand\pageref[1]{\origpageref{#1##1}}%
    \renewcommand\eqref[1]{\origeqref{#1##1}}%
  }}

\usepackage{amsmath}

\newcommand{\eq}[1]{\eqref{eq:#1}}

\begin{document}

\section{Section 1}
\label{sec}

\begin{equation}
  \label{eq:1}
  \int3x+4\pi\,dx
\end{equation} 

\eq{1} should give (1), but it actually gives (2).

\locallabels{:sec2}
\section{Section 2}
\label{sec2}

\begin{equation}
  \label{eq:1}
  \int6x+3y\,dx
\end{equation} 

\eq{1} should give (2), but it gives "(??)".

\end{document}

Why do I get unresolved references, "(??)" for the second \eq{1}? Why do I get "(1)" for the first \eq{1}?

UPDATE: I discovered that hyperref (not included in the above MWE) complicates things. See the comments below.

Also, how would I define a command that would turn off \locallabels{}'s effect for a certain reference. E.g., this doesn't work:

\newcommand{\refnolocallabels}[2]{\locallabels{}\ref{#1}\locallabels{#2}}

thanks

Geremia
  • 2,201

1 Answers1

10

There are two independent problems here: as mentioned in the comments amsmath internally uses its own definition of \label and assigns its meaning only inside the display environments. So the trick with changing \labelat the outside doesn't work. Instead one has to provide a redefinition for \label@in@display as well (which is the amsmath internal).

The second problem is of a different nature: in the command \locallabels there is a redefinition for \ref and one for \eqref. But there should be only one for \ref as \eqref internally calls \ref in the end. With both redefnitions the call to \eq{1} is applying :sec2 twice and of course that results in a label that was never defined.

So in summary the correct code is

\makeatletter
\AtBeginDocument{%
  \let\origlabel@in@display\label@in@display
  \let\origref\ref \let\origpageref\pageref \let\origlabel\label
%  \let\origeqref\eqref
  \newcommand\locallabels[1]{%
    \renewcommand\label[1]{\origlabel{#1##1}}% ← notice the change here:
    \renewcommand\ref[1]{\origref{#1##1}}%
    \renewcommand\pageref[1]{\origpageref{#1##1}}%
%    \renewcommand\eqref[1]{\origeqref{#1##1}}%
    \renewcommand\label@in@display[1]{\origlabel@in@display{#1##1}}%
  }}
\makeatother
  • Okay, now I get some strange problem when using your code code in my original document (not in the MWE above). \eq{1} in that document gives things like this: "(6.1Section name.6.1)." Also, mustn't #1##1 really be ##1#1 in my case because my custom \eq{} command is "postfix," since, e.g., \eq{1} = \eqref{eq:1:sec2} and not \eqref{:sec2eq:1} or something else? thanks – Geremia Oct 01 '13 at 20:05
  • I'm still getting the strange "(6.1Section name.6.1)" issue. Clearly, the references match up, but I have no clue why it displays "(6.1Section name.6.1)" and not just "(6.1)". Also, \makeatletter and \makeatother should isolate \locallabels from other packages possibly interfering with it, shouldn't it? – Geremia Oct 01 '13 at 20:33
  • Also, I get no errors or warning compiling my original (non MWE) document. – Geremia Oct 01 '13 at 20:42
  • a) \makeatother is only there to allow for using commands with @ in the name, nothing else. b) fairly sure that you are not supposed to change the order #1##1, I think you have a bit of a misunderstanding when things get applied. c) log in the aux file to see what labels are really generated. d) the "section name" in the ref sounds like you use some additional package but there is no way to guess what other packages you have that influence your label ref setup. – Frank Mittelbach Oct 01 '13 at 21:22
  • Here's what I see in my .aux file: \@writefile{toc}{\contentsline {section}{\numberline {6.1}Section name.}{81}{section.6.1}} \newlabel{part2:2.ch1.sec1}{{6.1}{81}} \newlabel{part2:eq:1}{{6.1}{82}{Section name.\relax }{equation.6.1}{}} – Geremia Oct 02 '13 at 00:19
  • I discovered hyperref is what's causing the problems! – Geremia Oct 02 '13 at 01:46
  • @Geremia: Of course, yet you never included that in your MWE! hyperref's sole purpose is to manage references - something you're trying to change. So it is integral in the analysis, debugging and solution. – Werner Oct 02 '13 at 02:04
  • @Werner: Fortunately, I can do without hyperref. – Geremia Oct 02 '13 at 02:29
  • If you load hyperref before the \AtBeginDocument then it is likely to work (it does with your original MWE) but of course there may be other factors like options to hyperref. – Frank Mittelbach Oct 02 '13 at 04:42
  • @FrankMittelbach: No, loading it before didn't help. It must be my publisher's stylesheet does something else with hyperref etc. Also, did you see my question in the OP about defining a \refnolocallabels? thanks again – Geremia Oct 02 '13 at 05:16
  • as mentioned in the answer to the original question all you have to do is to use \origref in place of \ref to get a non-local reference. However, your code should work too as far as I can tell without testing, it is only a bit too complicated to be useful. If it doesn't then it might be better to start a new question with a full MWE. – Frank Mittelbach Oct 02 '13 at 05:59
  • I get duplicates like this: part2:part2:eq:80bisb, which then end up being undefined… Is this due to running latex multiple times? – Geremia Apr 11 '14 at 03:12
  • Thanks for this very helpful answer, @FrankMittelbach! One clarification question regarding line 8 of your code: \renewcommand\ref[1]{\origref{#1##1}}% ##1#1, not #1##1. The code says #1##1 but the comment says ##1#1, not #1##1. Can you please clarify which one is correct? – CL. Sep 10 '21 at 18:27
  • 1
    @CL. ..5 year later ... I haven't written the comment, it was in the original posters code, I just corrected his code (in other places) and overlooked that the comment makes no sense. I'll remove it – Frank Mittelbach Sep 11 '21 at 07:40
  • @FrankMittelbach 5 years, yes. But still incredibly helpful ...! This seems to be exactly what many PhD students need when "combining" several papers (with identical labels) into a single thesis document. Thanks for the clarification! – CL. Sep 11 '21 at 07:45