数学模式中是否有针对不同风格的测试?

数学模式中是否有针对不同风格的测试?

数学模式中是否有针对不同风格的测试?我真的想要保存当前样式以便稍后重新调用它,但是\if类似的方法\ifmmode也同样有效。

在具体例子中,我想测量某个东西在数学模式下显示时会有多大,所以我这样做:

\settoheight{\mathheight}{some bit of maths}

但它会抱怨,因为它some bit of maths被放进一个盒子里并被测量,而盒子不知道它是数学。所以我改用:

\settoheight{\mathheight}{\(some bit of maths\)}

但如果将其用于显示的数学,我会得到错误的答案。所以理想情况下,我想要:

\ifdisplaystyle
 \let\currentstyle\displaystyle
\else
 \iftextstyle
  \let\currentstyle\textstyle
 ...
 \fi
\fi
\settoheight{\mathheight}{\(\currentstyle some bit of maths\)}

那我就会很高兴。

有这样的测试吗?


好的,这\mathchoice显然是可行的方法(感谢 Martin!),但它的行为有点奇怪,因为我想用它来根据我所处的模式定义宏,所以这个奇怪之处非常重要。以下是代码:

\newcommand{\mathtest}{%
\gdef\name{a}%
\mathchoice{%
\name
\gdef\name{b}%
}{%
\name
\gdef\name{c}%
}{%
\name
\gdef\name{d}%
}{%
\name
\gdef\name{e}%
}%
\name}

\[
\mathtest
\]

如果\mathchoice表现得像\if,这应该打印ab。但它打印了ae全部要处理的选项\mathchoice(这让我有点好奇它是如何工作的,但那是顺便说一下)。

那么,有没有一种明显的方法可以让其\mathchoice行为更像一点\if

答案1

我们将这样的宏称为 mathsettoheight。我将尽量简单,只定义 mathsettoheight(而不是 mathsettowidth 和 mathsettodepth)。

IIUC,你希望这个宏表现得像

\mathsettoheight{\dimen}{content}

首先,让我们考虑一下 \settoheight 的简化版本

\def\settoheight#1#2%
  {\setbox\@tempboxa\hbox{{#2}}%
   #1=\ht\@temboxa
   \setbox\@temboxa\box\voidb@x}

我们在 \mathsettoheight 中需要做的唯一更改是正确设置框。而不是

\hbox{#2}

使用

\hbox{$\mathpalette{}{#2}$}

\mathpalette 是为了方便而使用的快捷方式,通常由所有宏包(纯 TeX、LaTeX、ConTeXt)定义为

\def\mathpalette#1#2{%
  \mathchoice
    {#1\displaystyle{#2}}%
    {#1\textstyle{#2}}%
    {#1\scriptstyle{#2}}%
    {#1\scriptscriptstyle{#2}}}

一个小的改进是使用

\hbox{$\m@th\mathpalette{}{#2}$}

其中 \m@th 将数学环绕设置为零(如果您对内容的宽度感兴趣则很有用)。

就是这样。你举的例子的完整定义是

\documentclass{amsart}

\makeatletter

\def\mathsettoheight#1#2%
  {\setbox\@tempboxa\hbox{{#2}}%
   #1=\ht\@temboxa
   \setbox\@temboxa\box\voidb@x}

\def\mathsettoheight#1#2%
  {\setbox\@tempboxa\hbox{$\m@th\mathpalette{}{#2}$}%
   #1=\ht\@tempboxa
   \setbox\@tempboxa\box\voidb@x}

\makeatother

% Test case

\newlength\mathheight
\newcommand*\intheight{%
  \mathsettoheight{\mathheight}{\int}
  \the\mathheight
}


\begin{document}

$\intheight$

\begin{align}
\text{displaystyle}&={\displaystyle\text{\intheight}}\\
 \text{textstyle}&={\textstyle\text{\intheight}} \\
 \text{scriptstyle}&={\scriptstyle\text{\intheight}} \\
 \text{scriptscriptstyle}&={\scriptscriptstyle\text{\intheight}} 
\end{align}

{\obeylines
 \text{displaystyle}= $\displaystyle\text{\intheight}$\\
 \text{textstyle}=$\textstyle\text{\intheight}$ \\
 \text{scriptstyle}=$\scriptstyle\text{\intheight}$ \\
 \text{scriptscriptstyle}=$\scriptscriptstyle\text{\intheight}$ 
\endgraf}

\end{document}

答案2

这个答案只适用于 LuaTeX 和 LuaLaTeX,但您的问题很笼统,所以......

引擎luatex定义了一个原语,允许您查询当前的数学样式。

这个原语被称为\mathstyle,当查询值时(\ifnum例如,在之后),它返回一个介于 -1(不在数学模式)、0(显示样式)和 7(狭窄的脚本样式)之间的数字。

Luatex 还定义了四个\cramped..带前缀的新原语:\crampeddisplaystyle\crampedtextstyle\crampedscriptstyle, 。它们与不带前缀的原语( ... )\crampedscriptscriptstyle类似,只是它们明确地切换到其中一种“局促”的数学风格。\displaystyle\scriptscriptstyle

最后,还有新的原语\Ustack,它将用作\over..\atop..构造的前缀(这是命令所喜欢\frac\binom最终扩展为的),如下所示

\Ustack {a \over b}

如果不这样做,\mathstyle将会在的初始部分返回错误的值{... \over ...},正如 Aditya 所解释的那样。

所有这些原语结合在一起,允许如下代码:

\ifnum\mathstyle=\textstyle
   \message{normal text style}
\else \ifnum\mathstyle=\crampedtextstyle
   \message{cramped text style}
\fi \fi

和这个:

\def\cramped#1% switch the argument to a cramped math style
  {{\ifcase\mathstyle
    \crampeddisplaystyle      \or \or % 0 -> 1
    \crampedtextstyle         \or \or % 2 -> 3
    \crampedscriptstyle       \or \or % 4 -> 5
    \crampedscriptscriptstyle \fi     % 6 -> 7
    #1}}

甚至允许您定义一个\mathchoice不会将所有内容排版四次的版本:

\def\mathchoice#1#2#3#4%
  {{\ifcase\mathstyle
    #1\or #1\or
    #2\or #2\or
    #3\or #2\or
    #4\or #4\else #2\fi}}

目前,只有当您的底层引擎是时才能使用所有这些luatex,但希望最终也能支持此扩展xetex

答案3

是的,您有 \mathchoice

\documentclass{article}

\newcommand\mathtest{%
  \mathchoice
  {displaystyle}
  {text style}
  {scriptstyle}
  {scriptscriptstyle}
}

\begin{document}
\[
 \mathtest x^{\mathtest^{\mathtest}}
\]

\(
  \mathtest
\)

\end{document}

答案4

这是一个迟来的解决方案,顺便说一句,它还没有经过彻底的测试,但是在 OP 想要做的事情的情况下是有效的。

它是半可扩展的,即宏\def\mathcase{\getmsty\mstycase}有两个部分\getmsty,一个不可扩展,\mstycase另一个确实可扩展。类似于\pgfmathparse{..}\pgfmathresult。例如,如果您想在 csname 中放入某些内容,则需要\getmsty\csname\mstycase{cdot}{times}{div}{cdots}\endcsname

欢迎任何评论,因为这可能不会按预期工作,至少不像我预期的那样。

\documentclass{scrartcl}

\usepackage{mathtools}


\usepackage{zref-savepos}
\newcount\mmstynum
\newcount\tmpnum
\protected\def\getmsty
 {\global\advance\mmstynum1 %
  \expandafter\getstyA\expandafter{\number\mmstynum}}
\protected\def\getstyA#1%
 {\zsaveposx{mmsty-#1-a}%
  \mathchoice{\kern4sp}{\kern3sp}{\kern2sp}{\kern1sp}%
  \zsaveposx{mmsty-#1-b}
  \tmpnum=\numexpr
            \zposx{mmsty-#1-b} - \zposx{mmsty-#1-a}
          \relax
   \ifcase\tmpnum\or\kern-1sp \or\kern-2sp \or\kern-3sp \or\kern-4sp \fi}
\protected\def\mstycase
 {\ifcase\tmpnum\expandafter\gobblefour\or\expandafter\usefourth\or
   \expandafter\usethird\or\expandafter\usesecond\or
   \expandafter\usefirst\else\expandafter\gobblefour\fi}
\protected\def\mathcase{\getmsty\mstycase}

\long\def\gobblefour#1#2#3#4{}
\long\def\usefourth#1#2#3#4{#4}
\long\def\usethird#1#2#3#4{#3}
\long\def\usesecond#1#2#3#4{#2}
\long\def\usefirst#1#2#3#4{#1}


\def\tmpa{If this prints it means it doesn't work}
\newcommand*\foo
 {\mathcase % compare with \mathchoice
   {\def\tmpa{displaystyle}}
   {\def\tmpa{textstyle}}
   {\def\tmpa{scriptstyle}}
   {\def\tmpa{scriptscriptstyle}}
  \text\tmpa}

\begin{document}

\begin{align}
 \text{displaystyle} &= {\displaystyle\foo}\\
 \text{textstyle} &= {\textstyle\foo} \\
 \text{scriptstyle} &= {\scriptstyle\foo} \\
 \text{scriptscriptstyle} &= {\scriptscriptstyle\foo} 
\end{align}

\end{document}

或者......可能是这个解决方案不起作用,因为它计算当前样式的方式,它可能不够健壮(这是通过添加一个小空间,然后检查\pdfsavepos已插入的空间来完成的)。

相关内容