I have defined a macro that I would like to be used exclusively in math mode. In order to enforce this, I would like the macro to throw an error message whenever it is used outside of math mode. What is the easiest way of making a macro math-mode-only?
[Tex/LaTex] How to make a macro require math mode
macrosmath-mode
Related Solutions
Probably
\ensuremath{\textcolor{red}{#2}}
is what you need, since \textcolor
can be used in text and in math. The complete definition is
\newcommand{\DefineNamedFunction}[2]{% {FunctionName}{FunctionExpression}
\expandafter\providecommand\csname#1\endcsname
{\ensuremath{\textcolor{red}{#2}}}%
}
...
\DefineNamedFunction{FunctionF}{y=2\sin x}
$\FunctionF$ and \FunctionF
I've also deleted the braces that require another \expandafter
, but that's not the problem.
Of course, you can't call
\DefinedNamedFunction{FunctionFF}{$y=x$}
and I wouldn't know why you'd want it. But in any case there's a simple solution
\newcommand{\DefineNamedFunction}[2]{%
\expandafter\providecommand\csname#1\endcsname
{\ensuremath{\begingroup\color{red}\DNFnorm#2\endgroup}}}
\makeatletter
\def\DNFnorm{\@ifnextchar$\DNFnormi{}}
\def\DNFnormi$#1${#1}
\makeatother
The input is "normalized" by removing the $
tokens before and after, if present.
With \begingroup\color{red}...\endgroup
the spaces in the subformula participate to the stretching and shrinking of the spaces in the line.
Two objections come to mind:
- If you don't know you will be entering math mode, then you may write something "semantically" correct that breaks.
For example:
\documentclass{article}
\newcommand\mathmacro[1][A]{\ensuremath{{#1}_1}}
\begin{document}
\mathmacro[$x^2$] % The dollar signs *leave* math mode
\end{document}
What's going on here is that \mathmacro[$x^2$]
expands to
\ensuremath{{$x^2$}_1}
which expands to (effectively)
\ifmmode
{$x^2$}_1
\else
${$x^2$}_1$
\fi
and you can see that if you write it outside of math mode, the second branch is taken, so the first dollar sign brings you into math mode and the one at the front of $x^2$
takes you out of it, with the reverse operation happening afterwards. This gives an error.
Of course, you aren't supposed to do that, since \mathmacro
is actually a "math macro usable in text mode", so you should think of the thing between the brackets of its argument as being in math mode. Alas, this confuses both the author and the text editor's syntax highlighting, since it is a nonstandard assumption.
Edit: I would define this macro as:
\newcommand\mathmacro[1][A]{{#1}_1}
and use it as:
$x^2$ sub one: $\mathmacro[x^2]$.
This way, the parts that are math are clearly math.
- In the unlikely event that you or some package sets
\everymath
, you will be very surprised when your apparently text-mode macros start to look different.
On the subject of semantics, though, the issue is clear: \ensuremath
breaks the separation between math and text, which are two very different things. TeX even has the distinction built in: different fonts, different spacing rules, different parsing rules. You can probably construct a lot more counterexamples by exploiting these.
What I mean by this is that in the following situation:
\documentclass{article}
\newcommand\mathmacro[1][A]{\ensuremath{{#1}_1}}
\begin{document}
A sub one: \mathmacro
\bfseries A sub one: \mathmacro
\end{document}
you may be surprised that the bold text does not extend to the contents of the apparently text-mode \mathmacro
.
What I'm saying is not so much that \ensuremath
actually breaks anything as that it violates your expectations to the point that it makes things harder rather than easier.
Best Answer
You can use
\ifmmode
to check if you are in math mode, and trigger an error if not. An attempt to use it outside of math mode yields:Notes:
As David Carlisle pointed out, need to use
\DeclareRobustCommand
instead of\newcommand
to avoid premature expansion. See \ifmmode doesn't seem to work correctly inside an array environment.If you want to allow the macro to be used in or outside of math mode, you can use
\ensuremath
to typeset the content in math mode. But you should refer to When not to use \ensuremath for math macro? before doing this.Code: