我看到论坛里有几个用户在谈论\smash
。它显然是在基础 TeX 中定义的。
做什么\smash
?
为了将来参考,是否有我可以找到的在线文档?
答案1
顾名思义,\smash
获取其内容并将其打印出来,就好像它的高度和深度为零一样。
LaTeX 中的定义沿用了纯 TeX 中的定义,但略有不同;为了方便参考,我将使用 LaTeX 中的定义。以下内容指的是 LaTeX 2018-12-01。
% latex.ltx, line 4494:
\def\smash{%
\relax % \relax, in case this comes first in \halign
\ifmmode
\expandafter\mathpalette\expandafter\mathsm@sh
\else
\expandafter\makesm@sh
\fi}
该宏区分它是否在数学模式下调用。请注意,为了提高效率,它不会在开始时读取其参数。我假设调用是\smash{abq}
。在数学模式下,我们得到
\mathpalette\mathsm@sh{abq}
现在我们需要看看\mathsm@sh
:
% latex.ltx, line 4503:
\def\mathsm@sh#1#2{%
\setbox\z@\hbox{$\m@th#1{#2}$}\finsm@sh}
根据工作\mathpalette
,我们得到相当于
\setbox\z@\hbox{$\m@th<current style>{abq}$}\fin@smash
如果呼叫处于文本模式,则我们有\makesm@sh{abq}
。现在
% latex.ltx, line 4501:
\def\makesm@sh#1{%
\setbox\z@\hbox{\color@begingroup#1\color@endgroup}\finsm@sh}
所以我们得到
\setbox\z@\hbox{\color@begingroup abq\color@endgroup}\finsm@sh
在这两种情况下,TeX 都设置了框 0 的内容;现在\finsm@sh
开始执行它的工作
% latex.ltx, line 4505:
\def\finsm@sh{\ht\z@\z@ \dp\z@\z@ \leavevmode@ifvmode\box\z@}
这会将框 0 的高度和深度设置为 0pt,并在启动水平模式后对框进行排版。
加载时amsmath
定义基本相同,不同之处在于允许使用可选参数,可以是t
或b
。t
最后一个操作变为仅
\ht\z@\z@ \box\z@
因此深度得以保留;相反,使用b
LaTeX 只会
\dp\z@\z@ \box\z@
并且高度保持不变。这是通过重新定义实现的(参考amsmath.sty
2018-12-01 版本)
% amsmath.sty, line 903:
\ifx\leavevmode@ifvmode\@undefined
\renewcommand{\smash}[1][tb]{%
\def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
\edef\finsm@sh{\csname mb@#1\endcsname\z@\z@\box\z@}%
\ifmmode \@xp\mathpalette\@xp\mathsm@sh
\else \@xp\makesm@sh
\fi
}
\else
\renewcommand{\smash}[1][tb]{%
\def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
\edef\finsm@sh{\csname mb@#1\endcsname\z@\z@ \leavevmode@ifvmode\box\z@}%
\ifmmode \@xp\mathpalette\@xp\mathsm@sh
\else \@xp\makesm@sh
\fi
}
\fi
您会看到,\finsm@sh
每次都会重新定义为由必要的位组成。
\smash
中的条件定义amsmath.sty
是由于\leavevmode@ifvmode
从 2018-12-01 版开始,LaTeX 添加了 ,用于在垂直模式下启动水平模式。在之前的 LaTeX 版本中,这种情况不会发生,反映了与普通 TeX 相同的行为,其中 的定义与 LaTeX 内核中的相同,但没有\leavevmode@ifvmode
,它在 LaTeX 内核中定义为
% latex.ltx, line 1633:
\protected\def\leavevmode@ifvmode{\ifvmode\expandafter\indent\fi}
答案2
\smash
是一个定义为的宏
\relax \ifmmode \def \next {\mathpalette \mathsm@sh }\else \let \next \makesm@sh \fi \next
定义\mathsm@sh
为:
\setbox \z@ \hbox {$\m@th #1{#2}$}\finsm@sh
定义finsm@sh
为
ht \z@ \z@ \dp \z@ \z@ \box \z@
这个命令的简单版本让它的功能更加明显,它来自TeX 按主题分类:
\def\smash#1{{\setbox0=\hbox{#1}\dp0=0pt \ht0=0pt \box0\relax}}
它基本上是取一些内容并将其放入高度和深度均为 0 的盒子中。
它记录在 TeXbook 中,也在 TeX by Topic 中,其中包含了 TeX Live 文档的一部分(texdoc texbytopic
应该会提到它。)
LaTeX 内核中的实际宏可以在文档中找到source2e.pdf
(也可以通过 获得texdoc
)。
一些软件包,例如amsmath
重新定义它。另请参阅
答案3
这个答案试图满足@BenCrowell对 smash 如何影响输出的示例的渴望。正如评论所指出的那样,受影响的是高度和深度,而不是宽度\smash
。因此,这会影响分配给文本的垂直空间,这可能会影响前行和后行的垂直位置、上标和下标的位置(与粉碎的材料相关),以及与\smash
编辑文本一起堆叠的材料。
\documentclass{article}
\usepackage{stackengine}
\begin{document}
\noindent Affects placement of pre-\\
$\displaystyle\frac{Q}{Z}$ (vertical space widened to account)\\
and suc-ceeding material\\
$\displaystyle\smash{\frac{Q}{Z}}$ (vertical space not widened)\\
See what I mean?
\bigskip
Now let's look at super/subscript placement.
\[\left(\frac{a}{b}\right)^a_b\]
Compare if fraction is smashed:
\[\smash{\left(\frac{a}{b}\right)}^a_b\]
Now for certain types of stacks:
\Shortstack{a b fg d e} versus \Shortstack{a b \smash{fg} d e}.
\end{document}
答案4
无论如何,从amsmath 软件包用户指南:
命令 \smash 用于排版有效高度和深度为零的子公式,这有时有助于调整子公式相对于相邻符号的位置。
使用 amsmath 包 \smash 具有可选参数 [t] 和 [b],因为有时能够“粉碎”某些物体的顶部或底部,同时保留自然的深度或高度是有利的。
例如,当相邻部首符号因其内容的高度和深度不同而大小或位置不均匀时,可以使用 \smash 使它们更加一致。
他们提供了一个使用\smash[b]
平方根符号的例子:
如果没有此选项:
用它:
\sqrt{x} + \sqrt{\smash[b]{y}} + \sqrt{z}
第二个被开方数已减小了其边界框的垂直限制。