# How to detect whether a command enters math mode behind the scene?

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?

-
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

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.

-
@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.

-
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