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 have a long document which includes several files. In some cases I may want to include those files in different orders. In some cases, I may want to adapt the text depending on whether a specific \label has or has not been passed in the document.

The interface I was thinking of is a macro \iflabelexists{label}{foo}{bar}, which decides if \label{foo} has occurred already. If so, the macro expands foo; if not, bar.

The method I am currently trying is to patch \newlabel (a command written to the aux file when \label is expanded), to provide a toggle for each label. Then \label switches that toggle on.

\documentclass{article}
\usepackage{etoolbox}

\makeatletter
\patchcmd{\@newl@bel}{\global\@namedef{#1@#2}{#3}}{%
  \global\@namedef{#1@#2}{#3}%
  \global\providetoggle{l#1@#2}%
}
{\message{patching of \string\@newl@bel\space succeeded.}}
{\message{patching of \string\@newl@bel\space failed}}

\patchcmd{\label}{\@esphack}{%
  \pastlabel{#1}%
  \@esphack%
}
{\message{patching of \string\label\space succeeded}}
{\message{patching of \string\label\space failed}}

% each label ``foo'' results in a toggle ``lr@foo'' (label reference), 
% and \label{foo} sets \toggletrue{lr@foo}
\newcommand{\pastlabel}[1]{%
  \providetoggle{lr@#1}%
  \toggletrue{lr@#1}%
}

\newcommand{\iftoggleexists}[1]{%
    \ifcsdef{etb@tgl@#1}%
}
\newcommand{\gobble@two}[2]{\relax}

\newcommand{\ifpastlabel}[1]{%
  \iftoggleexists{lr@#1}{%
    \iftoggle{lr@#1}%
  }
  {% toggle does not exist so ambiguous
    \message{Warning: label reference toggle `#1' unknown.  Rerun to get toggles right.}%
    \textbf{??}%
    \gobble@two%
  }%
}
\makeatother

\begin{document}

\section{Bar}
\label{sec:bar}
Section \ref{sec:foo} \ifpastlabel{sec:foo}{has}{has NOT} been covered.

\section{Foo}
\label{sec:foo}
Section \ref{sec:bar} \ifpastlabel{sec:bar}{has}{has NOT} been covered.

\end{document}

If you rearrange the two document sections and compile (twice), the conditionals update correctly.

Before I adapt my whole document to this, I thought I'd ask the community: Is there a smarter way to do this, or a package I could use instead?

share|improve this question
    
You might want to look at varioref which gives different texts depending on the relative position (same page, previous page, next page, befpre after,...) –  David Carlisle Nov 20 '12 at 13:16
    
@DavidCarlisle: Thanks for the pointer. I need to look at varioref for another question anyway. –  Matthew Leingang Nov 20 '12 at 13:18
    
I guess it all depends on what you are labelling. For example, if the end purpose is "label only the equations I refer to", the package mathtools and his option showonlyrefs is an out-of-the-box solution. –  T. Verron Nov 20 '12 at 13:32
2  
If you don't want to distinguish between undefined labels and ones that haven't been set yet something like this should suffice: \patchcmd\label{\@bsphack}{\@bsphack\csdef{labelset@#1}{}}{}{} \newcommand*\ifpastlabel[1]{\ifcsdef{labelset@#1}} (still using etoolbox) –  cgnieder Nov 20 '12 at 13:41
1  
(Testing for existance also is easy: test if \r@<labelname> is defined: \newcommand*\iflabelexists[1]{\ifcsdef{r@#1}}) –  cgnieder Nov 20 '12 at 13:48
add comment

1 Answer

I do not see the point in hacking \newlabel to insert a "toggle". A macro marker defined by \label is all that is needed:

\documentclass{article}
\usepackage{etoolbox}

\makeatletter
\patchcmd{\label}{\@esphack}{%
  \pastlabel{#1}%
  \@esphack%
}
{\message{patching of \string\label\space succeeded}}
{\message{patching of \string\label\space failed}}

% each label ``foo'' results in a toggle ``lr@foo'' (label reference),
% and \label{foo} sets \toggletrue{lr@foo}
\newcommand{\pastlabel}[1]{%
  \global\expandafter\let\csname lr@#1\endcsname\@empty
}

\newcommand{\ifpastlabel}[1]{%
  \@ifundefined{lr@#1}{%
    \@ifundefined{r@#1}{%
      % toggle does not exist so ambiguous
      \message{Warning: label reference toggle `#1' unknown. %
        Rerun to get toggles right.}%
      \textbf{??}%
      \@gobbletwo
    }\@secondoftwo
  }\@firstoftwo
}
\makeatother

\begin{document}

\section{Bar}
\label{sec:bar}
Section \ref{sec:foo} \ifpastlabel{sec:foo}{has}{has NOT} been covered.

\section{Foo}
\label{sec:foo}
Section \ref{sec:bar} \ifpastlabel{sec:bar}{has}{has NOT} been covered.

\end{document}
share|improve this answer
add comment

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.