[Tex/LaTex] Proper way to use \ensuremath to define a macro useable in and out of math mode

macrosmath-mode

Based on this solution related to defining a macro I came up with this macro to help me define a macro that I can use either in or outside of math mode.

The example as is functions as I want. However, this solution requires me to NOT put $$ around the second parameter to to the \DefineNamedFunction macro. I would like to be able to include the $$, or not include it.

One solution is to modify \DefineNamedFunction to strip out the $$ if it is included in the macro call using the xstring pacakge, but this to me feels like a hack, and am thinking that there is probably a cleaner TeX way to do this.

So to summarize: How do I change \DefineNamedFunction such that I can use both the commented and uncommented calls to this macro, and still be able to use the definition inside and outside of math mode?

\documentclass{article}

\usepackage{amsmath}
\usepackage{xcolor}

\newcommand{\DefineNamedFunction}[2]{% {FunctionName}{FunctionExpression}
    \expandafter\providecommand\expandafter{\csname#1\endcsname}{\textcolor{red}{\ensuremath{#2}}}%
}

\begin{document}

\DefineNamedFunction{FunctionF}{y = 2 \sin x}
%\DefineNamedFunction{FunctionF}{$y = 2 \sin x$}

I can use FunctionF inside math mode as $\FunctionF$,
but can also use this outside of math mode as \FunctionF.

\end{document}

Best Answer

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

Sample

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.