Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to be able to do something like the following:

\incmycounter{abc}  %% counter value initialized to 0; associated with label 'abc'
\incmycounter{def}  %% counter value initialized to 0; associated with label 'def'
... various text (including some calls to \incmycounter) ...
\incmycounter{abc}  %% counter value == 2; associated with label 'abc'
\incmycounter{def}  %% counter value == 100;  associated with label 'def'
... some text (possibly defining new sections, labels, etc.) ...
\myref{abc} %% generate '2'
... more text ...
\myref{abc} %% generate '2'
\incmycounter{abc}  %% counter value == 3; associated with label 'abc'
... more text ...
\myref{abc} %% generate '3'
\myref{def} %% generate '100'

The \incmycounter command should either initialize a new counter (associated with the provided label name), or increment a currently defined one. A given \myref command should always refer to / generate the value that the associated counter had after the preceding \incmycounter command was executed. Is this possible, and if so, how?

share|improve this question
    
Are the references always after the setting of the values? –  egreg Dec 24 '12 at 18:28
    
@egreg: yes they are always after the setting of the values. I'm not clear on whether this is standard LaTeX behavior (didn't see any documentation explaining it anywhere), or if I need to do something special to ensure that multiple runs of (pdf)latex don't just substitute the last counter value in all of the refs. –  Mark Dec 24 '12 at 18:37

2 Answers 2

up vote 3 down vote accepted

You could just define a macro to store and change the values as necessary, without using a \label-\ref:

enter image description here

\documentclass{article}
\makeatletter
\newcommand{\mycounter}[2]{\global\@namedef{@cnt-#1}{#2}}
\newcommand{\myref}[1]{\@nameuse{@cnt-#1}}
\makeatother
\begin{document}
\mycounter{abc}{2}    %% new counter value == 2
\mycounter{def}{100}  %% new counter value == 100
\par \ldots some text (possibly defining new sections, labels, etc.) \ldots \par
\myref{abc} %% generate '2'
\par \ldots more text \ldots \par
\myref{abc} %% generate '2'
\mycounter{abc}{3}  %% new counter value == 3
\par \ldots more text \ldots \par
\myref{abc} %% generate '3'
\myref{def} %% generate '100'
\end{document}

\@namedef{<name>}{<stuff>} stores <stuff> in \<name>, while \@nameuse retrieves it. I've preceded the names with @cnt-, since \def (as in your example) is "already taken", while \@cnt-def is not. \global makes the change global, otherwise it could be trapped within an environment based on its scope. The use of \@namedef-\@nameuse (from the LaTeX kernel) also allows you (as in my example) to define names using characters that are usually not allowed.

The above example does not use counters, but it could be modified to allow for this. It didn't seem necessary from the code snippet.


Here is a modified version that uses counters, creating them if they don't already exist counter:

enter image description here

\documentclass{article}
\makeatletter
\newcommand{\incmycounter}[1]{%
  \@ifundefined{c@#1}
    {\newcounter{#1}}
    {\stepcounter{#1}}}
\newcommand{\myref}[1]{\@nameuse{the#1}}
\makeatother
\begin{document}
\incmycounter{abc}  %% counter value initialized to 0; associated with label 'abc'
\incmycounter{def}  %% counter value initialized to 0; associated with label 'def'
\par \ldots various text (including some calls to macros\incmycounter{abc}\incmycounter{def}) \ldots \par
\myref{abc} %% generate '1'
\par \ldots more text \ldots \par
\incmycounter{def}\myref{def} %% generate '2'
\incmycounter{abc}  %% counter value == 2
\par \ldots more text \ldots \par
\incmycounter{abc}\myref{abc} %% generate '3'
\myref{def} %% generate '100'
\end{document}

The first step in \incmycounter{<name>} is to check whether the counter <name> already exists. This is done using \@ifundefined{c@#1}, since all counters defined by \newcounter references a macro prepended with c@. So, the counter <name> is actually stored in \c@<name>. If it doesn't exist, then issue \newcounter{<name>}, otherwise \stepcounter{<name>}.

Another version using counters that could be used to set/step/arbitrarily increment the counters you use:

enter image description here

\documentclass{article}
\usepackage{xparse}% http://ctan.org/pkg/xparse
\makeatletter
\NewDocumentCommand{\mycounter}{s O{1} m}{%
  \@ifundefined{c@#3}
    {\newcounter{#3}}
    {\IfBooleanTF{#1}
       {\setcounter{#3}{#2}}
       {\addtocounter{#3}{#2}}}}
\newcommand{\myref}[1]{\@nameuse{the#1}}
\makeatother
\begin{document}
\mycounter{abc}  %% counter value initialized to 0; associated with label 'abc'
\mycounter{def}  %% counter value initialized to 0; associated with label 'def'
\par \ldots various text (including some calls to macros\mycounter{abc}\mycounter{def}) \ldots \par
\myref{abc} %% generate '1'
\par \ldots more text \ldots \par
\mycounter{def}\myref{def} %% generate '2'
\mycounter{abc}  %% counter value == 2
\par \ldots more text \ldots \par
\mycounter{abc}\myref{abc} %% generate '3'
\mycounter*[100]{def}%% counter value == 100
\myref{def} %% generate '100'
\end{document}

This uses xparse to provide the command interface. Now \mycounter[<value>]{<cntr>} increments <cntr> by <value> or sets <cntr> to <value> in the optional starred version (\mycounter*[<value>]{<cntr>}).

share|improve this answer
    
In my solution I switched the order of the arguments and used different macro names. :-) But I'd use \global\@namedef –  egreg Dec 24 '12 at 18:48
    
@egreg. I understand \global (or at least think I do). But what purpose does it serve here? In other words, what could go wrong if it's not used? –  A.Ellett Dec 24 '12 at 18:56
    
@A.Ellett If the variable is set in an environment, its set value would not be available outside the environment. If it's set as you do with \setcounter, \global is already provided by LaTeX. But Werner's method is much more economic. –  egreg Dec 24 '12 at 18:59
    
OMG, Now I feel stupid for not thinking of that. –  A.Ellett Dec 24 '12 at 19:01
    
@werner, I really like your solution, very economical (as @egreg says). Also, I was not familiar with the xparse package. Nevertheless, there are aspects of your code that I don't understand and for which I can't find the relevant reference material (either in source2e or xparse documentation): maybe I haven't looked hard enough. But, could you explain a bit what's going on with \@ifundefined{c@#3}: in particular, I'm not familiar with c@. –  A.Ellett Dec 24 '12 at 21:59

As I understand what you're saying, you could write:

\newcounter{myabc}
\newcounter{mydef}
\setcounter{myabc}{2}
\setcounter{mydef}{100}

.... some text ....

\themyabc %% geenerate '2'
\stepcounter{myabc}

.... more text ....

\themyabc %% generates '3'
\themydef %% generate '100'

If you could provide a bit more context, I could probably give you an answer that better meets your needs.

Here's how to get \myref to work with the approach I've outlined above:

\documentclass{article}
\newcounter{abc}
\makeatletter
\newcommand{\myref}[1]{\@nameuse{the#1}}
\makeatother
\begin{document}
\setcounter{abc}{3}
\theabc\ compared to \myref{abc}
\end{document}

which is really werner and not me.

enter image description here

Here's why I think @werner's solution is better:

  1. It's very user friendly: you don't have to remember how to set things up. With my approach, you have to remember that there's a counter to be define, that the counter needs to be stepped, etc. etc.

  2. In six months or a year from now you might think, "What was that really cool trick I did?" As I've written it, there's very little to remind you of all the steps you need to take to recreate the effect. Werner's solution is compact and---provided you're comfortable reading TeX and LaTeX code---is relatively self-explanatory (with or without comments).

  3. Werner's approach is extremely malleable. Maybe in a week from now or a month later you'll realize that you want something more dynamic or you want these counters tied in with some other structure in your document such as chapters, theorem, etc. (I know your original posting seems to indicate that this is not your desire, but we often change our minds.) With this regard, my approach is extremely clunky and rife for mistakes.

share|improve this answer
    
I think this comes closest to what I'm looking for (the ability to increment is important) -- but I'm not clear to me how to define a command \myref with \the#1 in its definition. Can you modify your answer to include a \newcommand\myref definiton? Also, I updated my original question for clarity -- having a single command that both creates and increments the counter would be preferable. –  Mark Dec 24 '12 at 19:26
    
I would be happy to rewrite this. But now that I've seen @werner's answer, I can't help thinking that it's really the better answer (particularly now that he's shown how to implement a counter). Any answer I would give at this point would really just be a reworking of werner's. –  A.Ellett Dec 24 '12 at 21:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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