2

In a document I am tracking a list of tasks. Lets call them A (Task 1), B (Task 2), and C (Task 3). I'm trying to create a command \mytask that will let me add the task based on a label, and other arguments that will be added to the document command as this evolves.

As I add tasks, I want to be able to reference them and determine their status as either New, or Continuing. Right now, I'm trying to distinguish between their states with \@ifundefined{r@#1} and the labels Defined and Undefined.

I'm surprised to see, that when I include \refstepcounter{task}\label{#1}% in the command, that I get really weird numbering, and the iflabelexists logic doesn't seem to be sensitive to the placement of the \label command.

My output is:

1 Tests

1.1 Defined A task 4

1.2 Defined B task 3

1.3 Defined B task 3

1.4 Defined A task 4

1.5 Defined C task 5

While I somewhat expected the numbers to be a little staggered because IO but the \refstepcounter after the titles that show what the task number is, I wasn't expecting the A to be a larger number than the B. Additionally, I expcet the Status (Defined or undefined) to be:

1 Tests

1.1 Undefined A

1.2 Undefined B

1.3 Defined B

1.4 Defined A

1.5 Defined C

I can't explain the why any use of refstepcounter toggles the ifundefined flag, but I'm guessing that logic of

if Exists(A) == false
   Show title demonstrating the proof that the label hasn't been created yet
   create label and counter
   % NOTE:  this logic is proof of concept only, real situation, this can not be worked around by starting from a lower counter number
else
   % label already exists
   Show title demonstrating the proof that the label has been created yet
   Don't increase counter

failing has something to do with the multiple runs of the compiler that Tex needs... Originally I thought my TOC was toggling the first use of the labels, but I think I've got a bigger problem.

Is there a dynamic way to work with custom counters like this?

MWE:

\documentclass{article}

\usepackage{xparse}
\usepackage{hyperref}
\usepackage{cleveref}

\makeatletter
    \newcommand{\iflabelexists}[3]{\@ifundefined{r@#1}{#3}{#2}}
\makeatother

\newcounter{task}
\renewcommand{\thetask}{\arabic{task}}
\crefname{task}{task}{task}

\NewDocumentCommand{\mytask}{ m }
{
    %   #1 - Task label

    \iflabelexists{#1}%
    {%
        \subsection{Defined $#1$ \cref{#1}}%
    }{%
        \subsection{Undefined $#1$ \cref{#1}}%
        \refstepcounter{task}\label{#1}%
    }%  
}

\begin{document}

    \section{Tests}

    \setcounter{task}{0}% Start value

    \mytask{A}

    \mytask{B}

    \mytask{B}

    \mytask{A}

    \mytask{C}

\end{document}
1
  • The test whether \r@<label> exists is reliable only for labels defined in the previous LaTeX run, not in the current one.
    – egreg
    May 29, 2017 at 21:30

1 Answer 1

2

Consider the following example:

\documentclass{article}

\begin{document}

\section{Test}\label{test}

\makeatletter
\@ifundefined{r@test}{undefined}{defined}
\makeatother

\end{document}

At the first LaTeX run it will print “undefined”, at the next run it will print “defined”.

When \label{test} is processed, LaTeX writes \newlabel{test}{{1}{1}} in the .aux file, but it doesn't define \r@test. It is \newlabel{test}{{1}{1}} that does, so the test

\@ifundefined{r@#1}

you're using will not do what you aim for.

You have to define your own macro for this.

\documentclass{article}

\usepackage{xparse}
\usepackage{hyperref}
\usepackage{cleveref}

\makeatletter
\newcommand{\iflabelexists}[3]{\@ifundefined{engbirdr@#1}{#3}{#2}}
\makeatother

\newcounter{task}
\renewcommand{\thetask}{\arabic{task}}
\crefname{task}{task}{task}

\makeatletter
\NewDocumentCommand{\mytask}{ m }
{
    %   #1 - Task label
    \iflabelexists{#1}%
    {%
        \subsection{Defined $#1$ \cref{#1}}%
    }{%
        \subsection{Undefined $#1$ \cref{#1}}%
        \global\expandafter\let\csname engbirdr@#1\endcsname\@empty
        \refstepcounter{task}\label{#1}%
    }%  
}
\makeatother

\begin{document}

    \section{Tests}

    \setcounter{task}{0}% Start value

    \mytask{A}

    \mytask{B}

    \mytask{B}

    \mytask{A}

    \mytask{C}

\end{document}

enter image description here

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.