views:

1041

answers:

2

I edited the question after David Hanak's answer (thanks btw!). He helped with the syntax, but it appears that I wasn't using the right function to begin with.

Basically what I want is to let the compiler ignore multiple definitions of a certain label and just use the first. In order to do that, I thought I'd just do something like this:

    \makeatletter
    \newcommand{\mylabel}[1]{
        \@ifundefined{#1}{\label{#1}}{X}
    }
    \makeatother

This does not work though, because the first option is always chosen (it doesn't matter if the label is defined or not). I think the \@ifundefined (and the suggested \ifundefined) only work for commands and not for labels, but I don't really know much about LaTeX. Any help with this would be great! Thanks!

Much later update: I marked David Hanak's response as the correct answer to my question, but it isn't a complete solution, although it really helped me. The problem is, I think but I'm no specialist, that even though David's code checks to see if a label is defined, it only works when the label was defined in a previous run (i.e. is in the .aux file). If two \mylabels with the same name are defined in the same run, the second will still be defined. Also, even if you manage to work around this, it will make LaTeX use the first label that you defined chronologically, and not necessarily the first in the text. Anyway, below is my quick and dirty solution. It uses the fact that counters do seem to be defined right away.

\newcommand{\mylabel}[1]{%
    \@ifundefined{c@#1}{%
     \newcounter{#1}%
     \setcounter{#1}{0}%
    }{}%
    \ifthenelse{\value{#1} > 0}{}{%
     \label{#1}%
     \addtocounter{#1}{1}%
    }%
}

I'm not sure if it is necessary to initialize the counter to 0, as it seems like a likely default, but I couldn't find if that was the case, so I'm just being safe. Also, this uses the 'ifthen' package, which I'm not sure is necessary.

+1  A: 

@ is a special character in LaTeX. To make your declaration syntactically correct, you'll have to add two more lines:

\makeatletter
\newcommand{\mylabel}[1]{
    \@ifundefined{#1}{\label{#1}}{X}
}
\makeatother

The first line turns @ into a normal letter, the last line reverses its effect.

Update: You might also want to take a look at the "plain" \ifundefined LaTeX macro.

Update 2

Okay, I did some research to figure out the answer to the real problem. The thing is that defining a label does not create a macro by that name; it prepends a "r@" to it. So try the following:

\makeatletter
\newcommand{\mylabel}[1]{
    \@ifundefined{r@#1}{\label{#1}}{X}
}
\makeatother

For more technical details, refer to line 3863 of latex.ltx in your LaTeX distribution (where it says \def\newlabel{\@newl@bel r}).

David Hanak
\ifundefined isn't defined in LaTeX, I'm afraid.
Will Robertson
You're missing the '@'. It should say \@ifundefined.
Jordi
A: 

When I run the followng test I get errors:

\documentclass {book}

\usepackage{ifthen} \newcommand{\mylabel}[1]{% \@ifundefined{c@#1}{% \newcounter{#1}% \setcounter{#1}{0}% }{}% \ifthenelse{\value{#1} > 0}{}{% \label{#1}% \addtocounter{#1}{1}% }% }

\begin{document}

\chapter{Lorem Ipsum} \mylabel{abc}

\end{document}

Chapter 1. ! You can't use `\spacefactor' in vertical mode. \@->\spacefactor \@m l.21 \mylabel{abc}

Sorry, but I'm not programmed to handle this case; I'll just pretend that you didn't ask for it. If you're in the wrong mode, you might be able to return to the right one by typing I}' or I$' or `I\par'.

! Missing $ inserted. $ l.21 \mylabel{abc}

I've inserted a begin-math/end-math symbol since I think you left one out. Proceed, with fingers crossed.

LaTeX Font Info: External font cmex10' loaded for size (Font) <7> on input line 21. LaTeX Font Info: External font cmex10' loaded for size (Font) <5> on input line 21. \c@abc=\count88 ! Missing $ inserted. $ l.22

I've inserted a begin-math/end-math symbol since I think you left one out. Proceed, with fingers crossed.

Missing character: There is no č in font cmex10! [1