在 中LaTeX2e
,是否可以重新定义命令,但重新定义的范围仅在数学模式之外应用?例如,我想重新定义\sec
为\section
,但不幸的是,\sec
它在数学模式中具有特殊含义(即看起来不是特别有用,但仍然存在),我希望在进入该模式时保留它。
答案1
能做到吗?
只要小心一点,你所要求的事情从技术上来说是可以做到的。
首先,您必须定义一个与当前 等同的宏\sec
;在这种特殊情况下,\let\latexsec=\sec
这是好的(前提是它是在amsmath
加载之后发出的)。
第二,你可以重新定义\sec
。第一次尝试,
\renewcommand{\sec}{\relax\ifmmode\latexsec\else\expandafter\section\fi}
一旦\sec
出现在章节标题中,例如\chapter
,等等,就会失效\section
。\subsection
\section{Definition of $\sec$}
这是因为 LaTeX 尝试在文件中写出标题.aux
,但是当写入操作发生时,TeX 处于无模式,因此\ifmmode
为假\sec
然后扩展为\section
,这不是人们愿意尝试的。
第二次尝试:
\DeclareRobustCommand{\sec}{%
\ifmmode\latexsec\else\expandafter\section\fi
}
这似乎有效,因为\sec
在写入操作期间不会扩展标题,因为它已经变得很强大。然而,我们很快发现hyperref
加载时失败的另一个原因。发生这种情况是因为包试图将标题用于书签。
可以通过添加
\pdfstringdefDisableCommands{\def\sec{sec }}
因此,在生成书签时,此局部重新定义将覆盖标准重新定义。
最终代码(在所有包加载完成后添加到序言中):
\let\latexsec\sec
\DeclareRobustCommand{\sec}{%
\ifmmode\latexsec\else\expandafter\section\fi
}
\makeatletter
\@ifpackageloaded{hyperref}
{\pdfstringdefDisableCommands{\def\sec{sec }}}
{}
\makeatother
为什么不应该这么做?
有几个理由不这样做。一个是一般性的:一致的用户界面不会使用相同的命令名称来执行非常不同的事情。
其实就连 Knuth 在这方面也犯过错误,因为原语\span
在不同的语境中有不同的含义(这样做是有理由的,而且原语无论如何都要小心使用,通常隐藏在其他宏中)。
另一个原因是针对特殊情况。缩写\section
为 into\sec
有很多缺点,除了节省一些击键次数外,没有明显的优势。
聪明的编辑器知道\section
这一点,并且大多数编辑器会用特殊颜色对其进行着色,以提高源代码的可读性。但其中一些编辑器还具有代码折叠功能:只需按一下按钮,与我们正在处理的部分不同的所有文本都会被隐藏,只留下部分标题和一些标记来表示折叠的文本。
如果您使用\sec
,您将放弃这些有用的功能。
另一个原因是:如果你与其他人合作,他们可能不会\sec
像他们习惯的那样使用\section
。结果将是一份不一致的文档和关于“他妈的在\sec
干什么?”的电子邮件交流。
保持简单,不要试图节省按键次数。好的文本编辑器会有代码完成功能:输入后\sec
,系统会显示可能的完成项,包括括号和括号之间的光标(如果您选择)\section
。