\DeclareOldFontCommand 和 \DeclareRobustCommand 到底起什么作用?

\DeclareOldFontCommand 和 \DeclareRobustCommand 到底起什么作用?

在文章类中出现以下与字体选择相关的代码:

\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}
\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf}
\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt}
\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf}
\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit}
\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl}
\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc}
\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal}
\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal}

代码中的命令到底起什么作用?

答案1

宣言

\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}

\DeclareRobustCommand\rm{\@fontswitch{\normalfont\rmfamily}{\mathrm}}

让我们看看当 LaTeX$\rm a$在以下最小文档中找到时会发生什么:

\documentclass{article}
\begin{document}
$\rm a$
\end{document}

开始吧:

\rm ->\protect \rm  

\rm是一个强大的命令,因此这是它的正常扩展。现在,由于\protect\relax,因此\rm展开为:

\rm  ->\@fontswitch {\normalfont \rmfamily }{\mathrm }

接下来\@fontswitch展开:

\@fontswitch #1#2->\ifmmode \let \math@bgroup \relax 
\def \math@egroup {\let \math@bgroup \@@math@bgroup
\let \math@egroup \@@math@egroup }#2\relax \else #1\fi 
#1<-\normalfont \rmfamily 
#2<-\mathrm 

我们看到了参数。由于我们处于数学模式,因此遵循“真”分支,因此执行\math@bgroup和的重新定义\math@egroup\mathrm展开:

\mathrm ->\protect \mathrm  

\mathrm  ->\relax \ifmmode \else \non@alpherr \mathrm  \fi
\use@mathgroup \M@OT1 \symoperators 

\use@mathgroup #1#2->\relax \ifmmode \math@bgroup \expandafter
\ifx \csname M@\f@encoding \endcsname #1\else #1\fi \mathgroup #2\relax   
\expandafter \math@egroup \fi 
#1<-\M@OT1 
#2<-\symoperators 

再次,我们处于数学模式(\mathrm有一些代码禁止在其外部使用);测试是使用扩展为的事实进行\f@encoding

\f@encoding ->OT1

现在还有待扩展\math@egroup

\math@egroup ->\let \math@bgroup \@@math@bgroup
\let \math@egroup \@@math@egroup 

事情就结束了。本质上,这被转化为

${\mathrm{a}}$

如果{\rm a}在文本模式下发现,那么它基本上就变成了

{\normalfont\rmfamily a}

也就是说,\rm模拟命令的旧行为。

这就是为什么{\sf\sl a}不使用倾斜的无衬线字体,而是使用倾斜的衬线字体:它相当于

{\normalfont\sffamily\normalfont\slshape a}

道德:绝不使用旧字体命令。你不会得到任何好处,而且会失去新命令的灵活性。好吧,18 年后它们不再真的新的。

答案2

深入研究source2e得到以下信息:

[ \DeclareOldFontCommand] 是用于创建声明性字体更改命令的函数,也可用于在数学模式下更改字母。

基本上,您引用的行只是使\rm\normalfont\rmfamily在文本模式下等同于 在数学模式下等同于\mathrm。这样做是为了让使用这些弃用字体命令的文档仍能与 LaTeX2e 正确配合使用。(请注意,使用声明性字体开关的正确方法是\rmfamily等。)

脆弱和稳健的命令是 LaTeX 命令中最棘手的问题之一。在排版文档时,LaTeX 会使用 TeX 的许多功能,例如算术、定义宏和设置变量。但是,这些命令至少在三种不同情况下不安全。这些命令被 LaTeX 称为“移动参数”,包括:

  • 将信息写入文件,例如索引或目录。
  • 将信息写入屏幕。
  • \edef\message\mark或其他命令中,它会充分评估其参数。

LaTeX 用来使脆弱的命令变得健壮的方法是在它们前面加上\protect

[...]

[ \DeclareRobustCommand] 是一个包编写器命令,其语法与 相同\newcommand,但声明了一个受保护的命令。

本质上,使用\DeclareRobustCommand保证当(例如)将带有的章节标题\cal写入.aux文件时不会发生任何奇怪的事情。

\DeclareOldFontCommand\DeclareRobustCommand内部使用。

相关内容