31

I would like to define a new command which should determine (within a tikz plot) whether its argument is in math mode or not. If so, it should wrap the argument with $ $. I found \ifmode to do this, but it's not working. Here is my minimal example:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[american,ngerman]{babel}
\usepackage{tikz}

\newcommand*{\yellowemph}[1]{%
  \tikz[baseline=(text.base)]\node(text)[rectangle, fill=yellow, rounded
corners, inner sep=0.3mm]{\ifmmode $#1$\else #1\fi};%
}

\begin{document}
\yellowemph{word}% works
\yellowemph{$\frac{1}{2}$}% works
$\yellowemph{\frac{1}{2}}$% does not work
\end{document}

I am aware of \ensuremath, however, this always switches to math mode. I would like to keep text as is if not in math mode (see \yellowemph{word} for example).

SOLUTION

As posted below, this is a solution:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[american,ngerman]{babel}
\usepackage{tikz}

\newif\ifstartedinmathmode
\newcommand*{\yellowemph}[1]{%
  \relax\ifmmode\startedinmathmodetrue\else\startedinmathmodefalse\fi
  \tikz[baseline=(text.base)]\node(text)[rectangle, fill=yellow, rounded
corners, inner sep=0.3mm]
  {\ifstartedinmathmode$#1$\else#1\fi};%
}

\begin{document}
\yellowemph{word}
$\int_0^\infty f(\yellowemph{x})\,dx$
\yellowemph{$\displaystyle\frac{1}{2}$}
\end{document}

3 Answers3

26

The argument to a \node command is always processed in text mode, independently of whether the tikzpicture has been started in text or in math mode. So the best way out is to put the $ symbols in the argument.

\newcommand*{\yellowemph}[1]{%
  \tikz[baseline=(text.base)]\node(text)[rectangle, fill=yellow, rounded
corners, inner sep=0.3mm]{#1};%
}

\begin{document}
\yellowemph{word}
\yellowemph{$\frac{1}{2}$}

You might try a more complicated approach with a conditional:

\newif\ifstartedinmathmode
\newcommand*{\yellowemph}[1]{%
  \relax\ifmmode\startedinmathmodetrue\else\startedinmathmodefalse\fi
  \tikz[baseline=(text.base)]\node(text)[rectangle, fill=yellow, rounded
corners, inner sep=0.3mm]
  {\ifstartedinmathmode$#1$\else#1\fi};%
}
egreg
  • 1,121,712
  • Thanks for your help. I am aware of this. I was just wondering if it is possible to let LaTeX include the $ $ if necessary (so if the argument #1 is something in math mode) – Marius Hofert Mar 02 '12 at 12:02
  • @MariusHofert That's what the second of egreg's solutions does (I was about to post exactly the same code ..., only I forgot the \relax at the start). Incidentally, I've given you a solution to the highlighter question which avoids this problem. – Andrew Stacey Mar 02 '12 at 12:11
  • 1
    @egreg This will of course will still give an error if you use \frac in text leaving us with the first simpler solution;) – yannisl Mar 02 '12 at 12:37
10

You need to use \ensuremath or fix the error in your conditional:

\relax\ifmmode#1\else $#1$\fi
yannisl
  • 117,160
  • You might want to put a \relax before \ifmmode to ensure that it isn't expanded prematurely in some cases, like at the beginning of a tabular cell. – Martin Scharrer Mar 02 '12 at 11:46
  • Thanks for helping, Yiannis. This does not work as expected. I want $ $ if I am in math mode, and just the argument otherwise. Your solution does it the other way around. The problem is that if I put the $ $ in the first part of the conditional, it does not work anymore. Also note that \ensuremath always switches to math mode, however, I would like to not do this for words (see the first line of my example after \begin{document}. – Marius Hofert Mar 02 '12 at 11:48
  • @MariusHofert Hm.. I see problem is you want to have more than two conditions. If you are sending text and you are in mathmode, you need to include it in a \text{#1}, problem will fail if you do send a\frac. Not too sure if it is feasible. Suggest define two commands\hltextand\hlmath`. – yannisl Mar 02 '12 at 12:12
  • @MartinScharrer --Thanks. Normally I would do this type of macro in a \DeclareRobustCommand omitting the relax. But your sugestion is good. – yannisl Mar 02 '12 at 12:13
  • @Marius: what you describe does not make sense; you are trying to get into math mode when you are in math mode (if in math mode, start math mode. See what I mean?), which ends up trying to start a display math mode as a result. ($$) – morbusg Mar 02 '12 at 12:15
  • @morbusg It's more like "if in math mode, make a note of that, now do something that forces us out of math mode if we were in it, but using the fact that we noted it, start math mode again". – Andrew Stacey Mar 02 '12 at 13:23
  • @AndrewStacey: I can see that from egreg's answer. I was commenting on Marius' comment on this here Yiannis' answer. I wanted to emphasize that $ means: start math mode. – morbusg Mar 02 '12 at 13:34
  • @morbusg Ah, I see. – Andrew Stacey Mar 02 '12 at 15:15
1

Try this:

\newcommand*{\textyellowemph}[1]{\tikz[baseline=(text.base)]\node(text)[rectangle, fill=yellow, rounded, inner sep=0.3mm]{#1};}
\newcommand*{\mathyellowemph}[1]{\tikz[baseline=(text.base)]\node(text)[rectangle, fill=yellow, rounded, inner sep=0.3mm]{\ensuremath{#1}};}
\newcommand*{\yellowemph}[1]{\ifmmode\mathyellowemph{#1}\else\textyellowemph{#1}\fi}
Speravir
  • 19,491