Based on @SergeiGolovan's answer.
New answer
This version checks for a single token, but ignores one set of super- and subscripts, thus this should give better results than the version below. Also, additional to the starred variant, which will never use parenthesis, an optional argument for the unstarred variant can be used to control which argument should be put in parenthesis (none
or n
, first
or 1
, second
or 2
, both
or b
-- so \myfrac*
is the same as \myfrac[n]
).
Note: Since I always have a hard time remembering the correct LaTeX2e interface to \protected
macros, the following uses plain syntax \protected\def
...
\documentclass{article}
\usepackage{expkv-def}
\makeatletter
% key=val interface (no =val here, so key interface?)
\ekvdefinekeys{myfrac}
{
nmeta none = n
,protected noval n =
\let\myfrac@dividend\@firstoftwo
\let\myfrac@divisor \@firstoftwo
,nmeta first = 1
,protected noval 1 =
\let\myfrac@dividend\@secondoftwo
\let\myfrac@divisor \@firstoftwo
,nmeta second = 2
,protected noval 2 =
\let\myfrac@dividend\@firstoftwo
\let\myfrac@divisor \@secondoftwo
,nmeta both = b
,protected noval b =
\let\myfrac@dividend\@secondoftwo
\let\myfrac@divisor \@secondoftwo
}
% shortcut for \ekvset{myfrac}
\protected\ekvsetdef\myfrac@kv{myfrac}
% borrow a robust test from expl3
\ExplSyntaxOn
\cs_generate_variant:Nn \tl_if_single:nTF { o }
\cs_new_eq:NN \myfrac@ifsingle \tl_if_single:oTF
\ExplSyntaxOff
% macro implementation
\protected\def\myfrac{\begingroup\@ifstar{\myfrac@kv{n}\myfrac@do}\myfrac@}
\protected\def\myfrac@{\ekvoptargTF\myfrac@manual\myfrac@auto}
% optional argument given, should specify the rules for parenthesis
\protected\def\myfrac@manual#1%
{%
\myfrac@kv{#1}%
% error detection
\unless\ifdefined\myfrac@dividend
\GenericError
{}{myfrac Error: Missing specification in optional argument}{}{}%
\expandafter\@firstoftwo\expandafter\myfrac@auto
\fi
\myfrac@do
}
% no optional argument given, so we need to test and decide
\protected\def\myfrac@auto#1#2%
{%
\myfrac@decide\myfrac@dividend{#1}%
\myfrac@decide\myfrac@divisor {#2}%
\myfrac@do{#1}{#2}%
}
% everything determined, so output
\protected\def\myfrac@do#1#2%
{%
\mathchoice
{\frac{#1}{#2}}
{\myfrac@enquote{#1}{#2}}
{\myfrac@enquote{#1}{#2}}
{\myfrac@enquote{#1}{#2}}%
\endgroup
}
% output helper
\def\myfrac@enquote#1#2{\myfrac@dividend{#1}{(#1)}/\myfrac@divisor{#2}{(#2)}}
% set things up for strip
\protected\def\myfrac@decide#1#2%
{\myfrac@strip\@empty#2\myfrac@mark ^{}_{}\myfrac@stop#1}
% remove first superscript
\protected\def\myfrac@strip#1^#2{\myfrac@strip@#1}
% remove first subscript
\protected\def\myfrac@strip@#1_#2{\myfrac@decide@#1}
% check if now only a single token/group is left
\protected\def\myfrac@decide@#1\myfrac@mark#2\myfrac@stop#3%
{\myfrac@ifsingle{#1}{\let#3\@firstoftwo}{\let#3\@secondoftwo}}
\makeatother
% test command so that I don't need to type as much in the document body.
\newcommand\mytest[3][]
{%
% not-so-robust empty-arg test (fine for the input below)
\ifx\relax#1\relax
Text mode \(\myfrac{#2}{#3}\). Display mode \[\myfrac{#2}{#3}.\]%
\else
\texttt{#1}:
Text mode \(\myfrac[#1]{#2}{#3}\). Display mode \[\myfrac[#1]{#2}{#3}.\]%
\fi
}
\begin{document}
\section{automatic}
\mytest{x+y}{z+1}
\mytest{x_y}{z_1}
\mytest{x_y^2}{z_1+2}
\section{manual}
Starred: \(\myfrac*{x_y}{z_1},\) \[\myfrac*{x_y}{z_1}.\]
\mytest[first]{x}{z}
\mytest[second]{x}{z}
\mytest[both]{x}{z}
\mytest[none]{x+y}{z+1}
\end{document}

Old answer
This one tests how many tokens are inside one argument of \myfrac
and if there are more than one, encloses them in parentheses. The starred version doesn't use the check.
\documentclass{article}
\makeatletter
\def\my@enparen#1#2;{%
\ifx\relax#2\relax%
#1%
\else%
(#1#2)%
\fi}
\newcommand{\myfrac}{\@ifstar{\@myfrac}{\@@myfrac}}
\newcommand{\@myfrac}[2]{\mathchoice{\frac{#1}{#2}}{#1/#2}{#1/#2}{#1/#2}}
\newcommand{\@@myfrac}[2]{\mathchoice{\frac{#1}{#2}}{\my@enparen#1;/\my@enparen#2;}{\my@enparen#1;/\my@enparen#2;}{\my@enparen#1;/\my@enparen#2;}}
\begin{document}
Text mode \(\myfrac{x+y}{z+1}\). Display mode \[\myfrac{x+y}{z+1}.\]
This is fine: \[\myfrac{x_y}{z_1},\] but this isn't: \(\myfrac{x_y}{z_1}\).
Both are fine: \[\myfrac*{x_y}{z_1},\] \(\myfrac*{x_y}{z_1}\).
\end{document}
