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.

Commenting out the %\usepackage{hyperref} in the following code snippet will produce some warnings.

Using \usepackage{hyperref} and \section{} to detect whether a command enters math mode may not be applicable for branching logic, such as \ifthenelse{}{}.

\documentclass{article}
%\usepackage{hyperref}
\newcommand{\blackbox}{Do you know there is H$_2$O in this black box?}
\begin{document}
\section{\blackbox}
\end{document}

Is there a command, namely \ContainsMathMode{args}, to output a boolean value that represent whether or not the argument args enters math mode internally?

share|improve this question
    
do you need it for bookmarks? –  Herbert Jun 8 '11 at 18:27
    
@Herbert: It is for general purpose and I already know that \texorpdfstring can do for bookmarks. –  xport Jun 8 '11 at 18:30

2 Answers 2

up vote 11 down vote accepted

Math mode is used in many places behind the scenes, for example in tabular. I would say something like

\newcommand{\ContainsMathMode}[1]{\begingroup\MMusedfalse
  \everymath=\expandafter{\the\everymath\MMusedtrue}%
  \sbox0{#1}\endgroup}
\let\ifMMused\iffalse
\def\MMusedtrue{\global\let\ifMMused\iftrue}
\def\MMusedfalse{\global\let\ifMMused\iffalse}

Of course this is not expandable, so one has to first say \ContainsMathMode{arg} and then use \ifMMused to branch or, with ifthen, the test \boolean{MMused}.

With the input

\ContainsMathMode{H$_2$O}
\ifMMused Yes\else No\fi

\ContainsMathMode{abc}
\ifMMused Yes\else No\fi

\ContainsMathMode{\begin{tabular}{c}a\end{tabular}}
\ifMMused Yes\else No\fi

we get

Yes
No
Yes

The contents of the token list \everymath is inserted each time TeX enters in-line math mode. We add (locally) to it the command that sets the boolean to true. This boolean must be set globally, so we also need to set it to false at each call of \ContainsMathMode.

A more LaTeX way consists in adding to the above

\makeatletter
\newcommand{\IfContainsMathMode}[1]{%
  \ContainsMathMode{#1}%
  \ifMMused
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}
\makeatother

\IfContainsMathMode{H$_2$O}{Yes}{No}

\IfContainsMathMode{abc}{Yes}{No}

\IfContainsMathMode{\begin{tabular}{c}a\end{tabular}}{Yes}{No}

This would give the same output as before.

share|improve this answer
    
@xport: thanks, fixed. –  egreg Jun 8 '11 at 20:04

The \everymath facility is perfect for this: it is a token list that is read at the beginning of every math group (of course). You can do the following:

\documentclass{article}
\begin{document}
 \newif\ifmathinside
 \def\IfContainsMathMode#1{%
  \mathinsidefalse
  \begingroup
   \everymath={\global\mathinsidetrue}%
   \setbox0=\hbox{#1}%
  \endgroup
  \ifmathinside
 }
 \def\blackbox{There is H$_2$O in here}
 \IfContainsMathMode{\blackbox}  There was math inside
 \else                           There was no math
 \fi
\end{document}

I hope this doesn't have some awful side effect with the \if being unmatched inside \IfContainsMathMode. I guess a more LaTeXy way of doing it is

\documentclass{article}
\begin{document}
 \newif\ifmathinside
 \def\IfContainsMathMode#1#2#3{%
  \mathinsidefalse
  \begingroup
   \everymath={\global\mathinsidetrue}%
   \setbox0=\hbox{#1}%
  \endgroup
  \ifmathinside#1\else#2\fi
 }
 \def\blackbox{There is H$_2$O in here}
 \IfContainsMathMode{\blackbox}{There was math inside}{There was no math}
\end{document}

which doesn't have that potential problem.

share|improve this answer
2  
mixing global and local assignments of the same variable (in this case the meaning of \ifmathinside should be avoided. –  egreg Jun 8 '11 at 19:42

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.