# Making an “auto-counter” command - test whether a reference marker already exists?

I'd like to be able to number arbitrary objects (in my case, chemical compounds) within a document. Ideally this would involve a command a bit like \ref, but where you don't need a \label. The label would be created, and counter incremented, the first time \ref is called for a particular marker name, subsequent calls return the appropriate number.

The reason for this is that there's no specific "definition", just that they should be numbered in order of first appearance within the text.

\cref{one} -> 1
\cref{two} -> 2
...
\cref{one} -> 1


I think the way to do this is as following (disclaimer: I haven't ever made new command before!)

\newcounter{cref}
\newcommand{\cref}[1]{
IF MARKER #1 DOESN'T EXIST:
\refstepcounter{cref}\thecref\label{#1}
\ref{#1}
}


Questions:

1. Has this been done before? I can't find a package...
2. Is this a sensible way to do it?
3. Is it possible to check whether a particular marker hasn't been defined yet?
-

\newcounter{chrefcnt}
\newcommand{\chref}[1]{%
\ifcsname chref@#1\endcsname
% do nothing, the command is already defined
\else
\stepcounter{chrefcnt}%
\expandafter\xdef\csname chref@#1\endcsname{\thechrefcnt}%
\fi
% now print the number
\csname chref@#1\endcsname}


With \chref{one} \chref{two} \chref{one} you would get the output 1 2 1.

It's better to use prefixes, so as not to conflict with existing macros, I've used chref@. Some more checks might be needed. There's no need to use the \label-\ref system, in this case. We simply define the command corresponding to the label to expand to the assigned number.

(Thanks to lockstep for having pointed out a name conflict.)

# New implementation

Following the suggestion by Richard, here is a new implementation with an optional argument for "subcoumpounds"

\documentclass{article}
\makeatletter
\newcounter{chref@cnt}
\def\chrefstyle{\textbf}
\newcommand{\chref}[2][]{%
\ifcsname chref@#2\endcsname
% do nothing, the compound is already defined
\else
\stepcounter{chref@cnt}%
\expandafter\xdef\csname chref@#2\endcsname{\arabic{chref@cnt}}%
\expandafter\gdef\csname chrefsub@#2\endcsname{0}%
\fi
% now print the number
\chrefstyle{\csname chref@#2\endcsname}%
\if\relax\detokenize{#1}\relax
% do nothing, there's no optional argument
\else
\ifcsname chref@#2@#1\endcsname
% do nothing, the subcompound is already defined
\else
\@tempcnta=\csname chrefsub@#2\endcsname
\expandafter\xdef\csname chref@#2@#1\endcsname{\@alph\@tempcnta}%
\expandafter\xdef\csname chrefsub@#2\endcsname{\number\@tempcnta}%
\fi
% now print the letter
\chrefstyle{\csname chref@#2@#1\endcsname}
\fi}
\makeatother

\begin{document}

\chref[X]{one} $\to$ 1a

\chref[Y]{one} $\to$ 1b

\chref{two} $\to$ 2

\chref[Z]{one} $\to$ 1c

\chref{one} $\to$ 1

\chref[A]{two} $\to$ 2a

\end{document}


For each main compound we remember the number of subcompounds already defined, initializing it to 0; for \chref{one} we define \chrefsub@one to be 0. If a subcompound is requested and not yet defined, we set to the remembered number so far of subcompounds the temporary count register \@tempcnta and advance it by one. We define the corresponding control sequence (for \chref[X]{one} it would be \chref@one@X) to expand to the alphabetic representation of the value of \@tempcnta and remember the value of the "subcompounds-so-far".

-
Note: @cref is used as a prefix by the cleveref package (and \cref as well as its most important command name). –  lockstep Jun 4 '11 at 18:18
@caramdir: thanks for your eagle eye. –  egreg Jun 4 '11 at 19:52
Great, thanks! I can double this up to allow sub-compounds as well - see edited question. What would be really cool is \chref[A,B,C,F]{one} -> 1a-c,f but I expect that's not so trivial ;-) –  Richard Ingham Jun 5 '11 at 12:03

Have you looked at the chemcompounds package? The \compound macro seems to cover pretty much what you want.

-
I hadn't seen that one, no - thanks for pointing it out! (Also see my comment on the previous answer + edited question). –  Richard Ingham Jun 5 '11 at 12:12

Starting from egreg's answer, I've come up with the following:

\makeatletter
\newcounter{chref@cnt}
\def\chrefstyle{\textbf}
\newcommand{\chref}[2][]{%
\ifcsname chref@#2\endcsname
% do nothing, the compound is already defined
\else
\stepcounter{chref@cnt}%
\expandafter\xdef\csname chref@#2\endcsname{\arabic{chref@cnt}}%
\newcounter{chref@#2@cnt}%
\fi
% now print the number
\chrefstyle{\csname chref@#2\endcsname}%
\ifthenelse{\equal{#1}{}}{}{%
\ifcsname chref@#2@#1\endcsname
% do nothing, the subcompound is already defined
\else
\stepcounter{chref@#2@cnt}%
\expandafter\xdef\csname chref@#2@#1\endcsname{\alph{chref@#2@cnt}}%
\fi
% now print the letter
\chrefstyle{\csname chref@#2@#1\endcsname}}}
\makeatother


Then:

\chref[X]{one} -> 1a
\chref[Y]{one} -> 1b
\chref[X]{one} -> 1a
\chref{one}    -> 1

-
I've moved the second \newcounter outside the definition; it's sufficient to have a second counter linked to the first one so that an increment to the first counter will reset to zero the second one. –  egreg Jun 5 '11 at 17:50
@egreg would that still work if you have 1a, 1b, 2a, 1c, etc? i.e. you may need to increment the counter for 1 after you've started the counter for 2. –  Richard Ingham Jun 5 '11 at 20:00
No, it wouldn't work with that sequence. In that case a quite different approach is needed, but defining a new counter for each \chref with optional argument is out of the question. –  egreg Jun 5 '11 at 20:17
See the new implementation; I've reverted your answer to the original one (but it should be remarked that defining new counters in such a definition is bad programming style, as it wastes resources). –  egreg Jun 5 '11 at 20:46

1. chemnum \cmpd{main.sub} => 1a
2. chemcompounds \declarecompound[1a]{label}\compound{label} => 1a
3. bpchem \CNlabelsub{main}{sub} => 1a
4. chemcono (I cannot recommend this one in good conscience :( )