能做到吗?

能做到吗?

在 中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

相关内容