5

I compiled a catalogue from past exercises for a lecture (running to several hundred pages), which makes consistent labelling a bit of an issue.

My solution is to use labels of the form prb:problemname:locallabel, where locallabel is something of the form eq:ODE or fig:convergence. To be able to use this in practice (and not have to type huge labels every time), I came up with a function that generates local functions to deal with this (this was almost a year ago, and I certainly had help from StackExchange, but don't remember all the questions that I should reference now - apologies):

\AtBeginDocument{% hyperref changes the commands \AtBeginDocument, so this must come afterwards
\let\prblabel\label % define commands so that \prb... can be continually overwritten
\let\prbref\ref
\let\prbeqref\eqref
\let\prbautoref\autoref
\newcommand\locallabels[1]{%
  \renewcommand\prblabel[1]{\label{#1:##1}}%
  \renewcommand\prbref[1]{\ref{#1:##1}}%
  \renewcommand\prbeqref[1]{\eqref{#1:##1}}%
  \renewcommand\prbautoref[1]{\autoref{#1:##1}}%
}}

which is called at the beginning of a problem as \locallabels{prb:problemname}. All labels within the problem can then be used as if the file were stand-alone, as long as all labelling/referencing commands are used in their prb-version.

What I couldn't get to work is that this behaviour extends into the listings-environment (\usepackage{listings}), which provides its own labelling facilities. Therefore, these have to be called like

\lstinputlisting[label={prb:problemname:code:sample}]{matlab/sample.m}

which adds a further source of potential errors if the people writing new examples in this framework forget to use this correctly, or even just have a typo in the first part of the label (referencing with \prbref{code:sample} works of course, once the label is created correctly).

My question is thus how I can extend my \locallabels-command such that this also takes care of the listings-package, i.e. that I can call

\lstinputlisting[label={code:sample}]{matlab/sample.m}

instead of the above.

I've experimented with changing the \label-command directly, but with strange results. If a possible solution is in this vein, I have to add the further restriction (in the interest of cross-referencing between examples), that it still has to be possible to call e.g. \eqref{prb:otherproblemname:eq:PDE}.

Axel
  • 791

1 Answers1

1

I've burrowed a bit through listings.sty and came up with the following solution. Please be aware that I found this through the "bull-in-the-chinashop"-method, and would very much appreciate if someone who knows what he/she's doing could check/improve this.

The only addition (aside from dealing with @) is the third-to-last line.

\makeatletter
\AtBeginDocument{% hyperref changes the commands \AtBeginDocument, so this must come afterwards
\let\prblabel\label % define commands so that \prb... can be continually overwritten
\let\prbref\ref
\let\prbeqref\eqref
\let\prbautoref\autoref
\newcommand\locallabels[1]{%
  \renewcommand\prblabel[1]{\label{#1:##1}}%
  \renewcommand\prbref[1]{\ref{#1:##1}}%
  \renewcommand\prbeqref[1]{\eqref{#1:##1}}%
  \renewcommand\prbautoref[1]{\autoref{#1:##1}}%
  \lst@Key{label}\relax{\def\lst@label{#1:##1}} %
}}
\makeatother

I should maybe add that a construction similar to the other commands (with \let\oldlst@label\lst@label and then redefining \lst@label) didn't work, at least in the variants I tried.

Also, the change is permanent (which doesn't bother me, since the whole pdf consists of problems, each of which defines its local labels) - but could of course be set back to normal with

\lst@Key{label}\relax{\def\lst@label{#1}}

Just to make sure, I feel I should reiterate that I can't explain why this works - use it at your own risk.

Ps. It's very interesting to see the psychological effects of posting a question on StackExchange. I was perfectly happy to not have this solution for the better part of a year, but after I had posted it and no-one answered within 24 hours (the horror!), I just had to go look for it myself.

Axel
  • 791
  • Since it seems that there is nothing more forthcoming (for the moment at least), I'm accepting my own answer. – Axel Dec 18 '13 at 18:11