5

I would like to build a macro that correctly identifies the context within which it is being called and appropriately set modes and font size according to context.

Yesterday I started building a macro to draw an arc symbol over the names of points. But then I realized it wasn't aware of whether it was being called from within math mode or not. So I decided to add such features.

Of course I had to try to figure out how to break it. So the examples here are just a few where I'm finding contexts in which macro seems unaware of its proper context.

Here's the MWE:

\documentclass{article}
\usepackage{amsmath,amssymb}
\usepackage{tikz}

\makeatletter

\newsavebox\ae@frown@box
\begin{lrbox}{\ae@frown@box}
  \begin{tikzpicture}
    %% to not have unwanted white space being added to the height
    \begin{pgfinterruptboundingbox}
      \path[fill] (0,0) to [out=50,in=130] 
                  (2,0) to [out=150,in=30] 
                  cycle;
    \end{pgfinterruptboundingbox}
    %% to give my "box" some kind of width and height.
    \path (0,0) -- (2,0.45);
  %%  \draw[red] (current bounding box.north east) rectangle (current bounding box.south west);
  \end{tikzpicture}
\end{lrbox}

\def\ae@frown{\usebox{\ae@frown@box}}
\let\aefrown\ae@frown
\newsavebox\ae@tmp@box
\newcommand\arc[1]{%
  \begingroup
  \ifmmode
    \ifinner
      \sbox\ae@tmp@box{$#1$}%%
    \else
      \sbox\ae@tmp@box{$\displaystyle#1$}%%
    \fi
  \else\sbox\ae@tmp@box{#1}%%
  \fi
  \ooalign{%%
    \raisebox{\ht\ae@tmp@box}{%%
      \resizebox{\wd\ae@tmp@box}{!}{%%
        \ae@frown}}%%
    \cr
    \usebox{\ae@tmp@box}}%%
  \endgroup
    }

\makeatother

\pagestyle{empty}
\setlength{\parskip}{2ex}
\setlength{\parindent}{0pt}
\begin{document}

Gallia est omnis divisa in partes tres, quarum unam incolunt Belgae,
aliam Aquitani, tertiam qui ipsorum lingua Celtae, nostra Galli
appellantur. Hi omnes lingua, institutis, legibus inter se differunt.

In-line style: $ \int_0^2 x^2\mathrm{d}x   \text{  vs  }   \arc{\int_0^2 x^2\mathrm{d}x} $

Displaystyle I:
\[
  \int_0^2 x^2\mathrm{d}x
  \text{  vs  }
  \arc{\int_0^2 x^2\mathrm{d}x}
\]

Displaystyle invoked from within in-line style:
$\displaystyle 
  \int_0^2 x^2\mathrm{d}x
  \text{  vs  }
  \arc{\int_0^2 x^2\mathrm{d}x}
$

Displaystyle within \verb=align=
\begin{align*}
  y &=\int_0^2 x^2      \mathrm{d}x
  \intertext{  vs  }
  y &=\arc{\int_0^2 x^2 \mathrm{d}x}
\end{align*}

\end{document}

enter image description here

I was not expecting my macro no ignore the \displaystyle switch. That prompted me to test it out in an align* environment. Other contexts I'm aware of are numerator/denominators of fractions and super/subscripts where font sizes are scaled: I don't know how to test for any of these.

So I've got a bundle of questions which seem very closely related:

  • How do I get my macro to know when to use \displaystyle? For example, when I've used the switch \displaystyle I would like my macro to recognize that, but currently it doesn't.
  • Once I've tested for modes, am I setting the mode correctly? In other words, if I discover that I'm no longer in in-line math mode, do I use \displaystyle to switch mode styles, or is there a better approach?
  • How do I test whether I'm in a fraction or a super/subscript?

I know it's generally frowned upon to post multiple questions in single posting, but these questions seemed to be so closely aligned that putting them together made more sense to me than separating them. However, if the community would like me to post them separately, I will certainly edit my question and do so.

Finally, I'm not really concerned with the visual aesthetic of this particular macro. This is a purely educational exercise. I'm not planning on arcing my integrals!

  • The \ifinner test is not reliable: it returns true between \left and \right, for instance, independently on whether the formula started in display mode or not. – egreg Apr 30 '14 at 21:23
  • @egreg Regarding your edit: I can never remember which are the 1st or 3rd conjugation verbs and get my a's and i's all wrong. :*( – A.Ellett Apr 30 '14 at 21:51
  • Sentio, sensi, sensum, sentire (fourth conjugation in Latin). It means “to discern by the senses; to feel, hear, see”; from it sensitivus, which is medieval Latin. It's easier for me, because in Italian it is sentire. ;-) – egreg Apr 30 '14 at 22:02
3

The answer to all the questions is basically: you can't. It is all to support the primitive \over syntax which means TeX does not know at the point the commands are executed what mode it will end up in.

this is why there is \mathchoice that sets the command 4 times into 4 internal boxes, using all 4 styles display text script and scriptscript and later TeX choses one of the boxes depending on which style is required.

In addition \ifmmode does not reliably tell you that you are in math mode unless you use \DeclareRobustCommand or etex \protected\def otherwise at the start of an alignment cell in an environment such such as align or array it will expand to false while Tex is looking for \omit even though if \omit is not there and the cell starts math mode will be started by a $ inserted by the alignment template.

  • So perhaps the solution would then be to build four different versions of my \arc command and then create a macro like \def\arc{\mathchoices{\arc@d}{\arc@t}{\arc@s}{\arc@ss}}? And then I would just have to be happy thinking of my command as one to be called within a math context. – A.Ellett Apr 30 '14 at 21:52
  • @A.Ellett that's what all constructed math operations like \sqrt or \phantom etc do – David Carlisle Apr 30 '14 at 22:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.