[Tex/LaTex] Correct usage of \ifmmode

alignamsmathmath-mode

Seems that there is some subtlety in using \ifmmode that I am not aware of. For some reason, using:

\newcommand{\hlcodeA}[1]{\ifmmode\else\small\fi\texttt{\hilight{#1}}}%

is not quite identical to:

\newcommand{\hlcodeB}[1]{\texttt{\hilight{\ifmmode\else\small\fi#1}}}%

where I moved the \ifmmode test to the inner level of the macro from the outer.

Both are ok, except in an alignenvironment where \hlcodeB has no problems, but \hlcodeA yields a warning:

LaTeX Font Warning: Command \small invalid in math mode on input line 26

Notes:

  • No problems are reported when used in an equation environment.

  • The MWE below yields a warning, but replacing \hlcodeA{y2} with \hlcodeB{y2} in the align environment, no warnings are reported.

  • This example is not really intended to produce proper output in math mode, but it seems that I am abusing the align environment in my real example. This is old code for my internal documentation where I now know that I should have used tabular instead — this was not obvious to me in early 2011 when I started this document 🙂 , and am just now trying to clean up some of the warnings.

Code:

\documentclass{article}
\usepackage{xcolor}
\usepackage{amsmath}

\newcommand{\hilight}[1]{\colorbox{yellow}{#1}}%


\newcommand{\hlcodeA}[1]{%
    \ifmmode\else\small\fi\texttt{\hilight{#1}}%
}%

\newcommand{\hlcodeB}[1]{%
    \texttt{\hilight{\ifmmode\else\small\fi#1}}%
}%


\begin{document}
\hspace*{5.0cm}\hlcodeA{y} = \hlcodeA{x}%   This is ok (no warnings)

\begin{equation*}%         This is ok (no warnings)
\hlcodeA{y1} = \hlcodeA{x1}
\end{equation*}

\begin{align*}%         This is NOT ok (warnings but only from \hlcodeA)
\hlcodeA{y2} = \hlcodeB{x2}
\end{align*}
\end{document}

Best Answer

At the start of an alignment cell TeX expands macros looking for \omit (\multicolumn) the math start in the cell template has not been added at this point so \ifmmode is always false.

You need to put \relax in front of it to kill the pre-scan for \omit or make the command containing this construct be robust so it doesn't expand in this context (using LaTeX \DeclareRobustCommand or eTeX \protected)


To show the various approaches, this plain eTeX file

\def\foo{\ifmmode \phi\else fi\fi}
\protected\def\pfoo{\ifmmode \phi\else fi\fi}
\def\rfoo{\relax\ifmmode \phi\else fi\fi}

\halign{#)&$#$\hfill&\quad dif#cult\cr
0&\omit $\phi$\hfill&\omit \quad dif{f}icult\cr
1&\omit $\phi$\hfill&\omit \quad difficult\cr
2&\foo&\foo\cr
3&\pfoo&\pfoo\cr
4&\rfoo&\rfoo\cr
}


\bye

produces

enter image description here

(1) is what you want.

(0) loses the ffi ligature.

(2) the non robust unprotected command gets the ffi ligature but messes up the if math test.

(3) the etex \protected macro does the same as (1).

(4) using \relax (which would be the same as using \DeclareRobustCommand in LaTeX in this context) gets the math test correct but loses the ffi ligature.