6

I want to define a command \myfrac that takes 2 arguments and returns #1 / #2 if it is in text style (e.g. $\myfrac 1 2$), and returns \frac{#1}{#2} if it is in display style (e.g. \[ \myfrac 1 2 \]).

Are there any commands like \ifinline checking the style, or are there any alternatives for \myfrac?

3 Answers 3

3

Please try with the below tag:

\documentclass{book}
\usepackage{amsmath}
\begin{document}

\newcommand{\myfrac}[2]{#1/#2}
\everydisplay{\let\myfrac\frac}

$\myfrac1 2$

\[
\myfrac1 2
\]
\end{document}
3
  • notwisthstanding comment of @DavidCarlisle, it should be something like \everydisplay\expandafter{\the\everydisplay\let\myfrac\frac} to not overwrite possible stuff in \everydisplay. Although it is rare that packages use it (mathastext does).
    – user4686
    Commented Sep 2, 2017 at 10:06
  • @jfbu yes (although it's somewhat accidental as the actual entries are all set in inline math with \displaystyle) but I'll delete and post a better comment, thanks. Commented Sep 2, 2017 at 10:13
  • 1
    This only works if (after expanding macros) the math is entered by $$ not by $\displaystyle... $ also it forces the display style mode in all nested contests such as array cells (which are set in texstyle and in superscripts etc. Commented Sep 2, 2017 at 10:15
10

You can use \mathchoice for that. It takes four arguments (for all four math modes) and typesets the first one in display mode, the second one in text mode, and the rest in script and scriptscript modes. The following code can illustrate that:

\documentclass{article}
\newcommand{\myfrac}[2]{\mathchoice{\frac{#1}{#2}}{#1/#2}{#1/#2}{#1/#2}}
\newcommand{\myfraca}[2]{\mathchoice{\frac{#1}{#2}}{(#1)/(#2)}{(#1)/(#2)}{(#1)/(#2)}}
\begin{document}
Text mode \(\myfrac12\). Display mode \[\myfrac12.\]

This is fine: \[\myfrac{x+y}{z+1},\] but this isn't: \(\myfrac{x+y}{z+1}\).

Both are fine: \[\myfraca{x+y}{z+1},\] \(\myfraca{x+y}{z+1}\).

But in this case parentheses are awful: \[\myfraca{x}{z},\] \(\myfraca{x}{z}\).
\end{document}

But as you can see, using \mathchoice isn't very suitable for fractions you want, since they sometimes need parentheses and sometimes don't. The result of the above code is the following:

enter image description here

1
  • Just to clarify, the second argument specifies inline math, not text.
    – Paul Wintz
    Commented Mar 29, 2023 at 22:49
7

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}

enter image description here


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}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .