# Adapt labelling facilities of listings package

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}


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}.

• Welcome to TeX.SX! You don't have to sign with your name since it automatically appears in the lower right corner of your post. – jub0bs Dec 9 '13 at 10:18
• Thanks for the tip. I can see the box of course, I just thought it's good etiquette (but while my "Dear StackExchange" was gobbled automatically, my signature was "only" auto-formatted, thus appearing allowable ;-)). – Axel Dec 9 '13 at 13:10
• You might be interested in the matlab-prettifier package; see this answer. – jub0bs Apr 28 '14 at 15:34
• @Jubobs: Thanks, looks very nice! I didn't go through the documentation - do you also provide a possibility to change counters/labels/etc.? – Axel May 5 '14 at 13:47
• No, but I'm confident that the accepted answer here is compatible with matlab-prettifier. – jub0bs May 5 '14 at 14:06

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.

• 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