我\section
从 TeXbook 中提取了一个宏。
\outer\def\section#1{\medbreak\noindent{\bf#1}\smallskip\par\nobreak\noindent}
当我像这样使用这个宏时:
\section{\TeX nical documenation}
Blah blah blah \TeX\ blah blah\dots
在段落开头之前添加了一个不必要的空白。我怀疑这是由于\section
调用之后和段落之前的换行符造成的。Knuth 通过不将\exercise
宏单独放在一行中来规避这个问题:
\exercise After you have mastered the material in this book,
what will you be: A \TeX pert, or a \TeX nician?
\answer A \TeX nician (underpaid); sometimes also called
a \TeX acker.
我可以通过\section
在参数后吞噬空格来解决这个问题:
\outer\def\section#1 {\medbreak\noindent{\bf#1}\smallskip\par\nobreak\noindent}
这是解决问题的好办法吗?如果不是,针对这种情况,推荐的解决方案是什么?
答案1
您忘了\ignorespaces
:\noindent
您以 开始一个段落,因此空格不会被忽略,除非您告诉 TeX 这样做。
\outer\def\section#1{%
\medbreak
\noindent{\bf#1}\par
\nobreak\smallskip
\noindent\ignorespaces
}
注意\nobreak
应该去前 \smallskip
因为如果前面没有可丢弃的物品(比如惩罚),TeX 就会在粘合处断裂。
请注意,在 Knuth 的代码中,写
\exercise After you have mastered the material in this book,
what will you be: A \TeX pert, or a \TeX nician?
或者
\exercise
After you have mastered the material in this book,
what will you be: A \TeX pert, or a \TeX nician?
完全相同,因为控制序列后面的空格在输入中一开始就被丢弃了。在你的情况下,后面的空格}
不会被忽略(它来自行尾,但是一样的)。
答案2
使用\noindent
意味着您的标题命令已经开始了第一个段落。如果您知道章节总是以文本开头,那么这样做是可以的(并且本着纯文本命令的精神,其目标是简单且易于定制,而不是通常的强大)。
缺点是,如果您想用任何垂直显示材料(如列表)开始任何部分。如果您在标题后开始一个段落,那么以 开始的段落\noindent
将结束,您将得到一个虚假的“白色”段落,仅由一个填充的水平框组成\parfillskip
。
在这里,LaTeX 所做的就是设置\everypar
删除缩进框,这样\setbox0=\lastbox
您就可以在标题后处于垂直模式(并且列表等特殊环境可以检测到特殊情况\everypar
并做一些适当的事情。
处于垂直模式自然意味着空格会被忽略,从而避免问题中提到的段落开头空白的问题。
请注意,在您现有的宏中,\smallskip
启动垂直模式,但这意味着以下\par
不执行任何操作(并且为时\nobreak
已晚,更好
\par\nobreak\smallskip