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

  • 1
    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
  • 1
    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
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.

| improve this answer | |
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.