哪些地方需要添加 % 来删除不需要的空格?

哪些地方需要添加 % 来删除不需要的空格?

我曾遇到过空格导致不良影响的情况。很难追踪这些不良影响的原因。为了消除任何疑问,我经常过度使用 %,如下所示。

\usepackage%
[%
left=3cm,
right=3cm%
]%
{geometry}

或者

\newcommand{\mycommand}%
{%
This is my command.%
}

我有一个极端的例子可以打破Leo Liu所说的

事实上,只需要通过注释删除输出的空格。

下面的代码不产生输出,但是我们不能删除%并在下面列表的两个元素之间留下一个空行。

\newpsstyle{gridstyle}
{
gridwidth=0.4pt,
%
griddots=0
}

简而言之,哪些地方需要添加 % 来删除不需要的空格?

答案1

事实上,只有输出的空格才需要通过注释删除。请记住,全字母控制序列(也称为控制字,而不是控制符号)后的空格将被忽略。

您可以使用:

\usepackage
[
  left  = 3cm,
  right = 3cm
]
{geometry}

没关系,不会输出空格。

但你必须使用:

\newcommand\foo
{% the space in \foo will be output when you use it in the text
  foo.%
}

这就是为什么在 TeX 中,包编写者经常使用:

\newcommand\foo{%
  foo.}

在 LaTeX3 宏语法中,所有空格(甚至单词之间的空格)都会被忽略,以方便宏编写。例如,

\RequirePackage{expl3,xparse}
\ExplSyntaxOn
\DeclareDocumentCommand \hello { m }
{
  hello~#1.
}
\ExplSyntaxOff

此处的波浪号~是普通的空格字符。


在一些包中,比如CJK,作者使用

\endlinechar \m@ne

忽略换行符引入的额外空格。然后你可以使用:

\newcommand\foo{
  foo.
}

在所有宏之后,

\endlinechar `\^^M

答案2

我想对 Leo Liu 的回答做些补充。让我们从一个包中取出一行(知道哪一个并不重要)

\newcommand{\period@active}[1]{\begingroup\mathcode`\.="8000\ensuremath{#1}\endgroup}

这表明了一个常见的错误,在目前的例子中,它实际上是无害的,但只是偶然的,因为\ensuremath扩展为\protect\ensuremath 并且通常\protect是不可扩展的(或者它的扩展给出一些不以数字开头的东西)。

该命令\mathcode需要两个数字(中间有一个可选的等号);第二个数字更重要:因为后面"8000跟着一个控制序列,TeX 希望扩展它以查看其扩展是否以(十六进制)数字开头。如果不\ensuremath进行强化,它的扩展将是

\ifmmode ... \else ... \fi

并且可能会在错误的时间评估条件。

这句话的寓意是:常量后总是留一个空格(即 TeX 语法所要求的明确数字)。此空间将被忽略,并且在分配之前不会扩展以下控制序列。

这个定义的正确写法是

\newcommand{\period@active}[1]{\begingroup\mathcode`\.="8000
  \ensuremath{#1}\endgroup}

(在这种情况下,行尾算作空格)。

在某些情况下,一定不能后面跟着一个空格,例如当我们想要利用\romannumeral\number扩展后面的所有内容直到找到不能解释为数字的内容时。然而,这些都是高级的 LaTeX 编程技术(Ulrich Diez 是这个领域的大师)。

在示例中\relax数字后面的 a 已经足够了,它通常用于终止赋值。在 a 之后肯定需要它胶水分配不完整

\myskip=1pt plus 3pt\relax

它真正相当于 LaTeX 的\setlength{\myskip}{1pt plus 3pt}

然而有些情况下\relax必须避免:当比较数字或长度时,我们经常会完全扩展上下文并\relax会保留,因为它是不可扩展的:假设我们有一个宏,它必须根据参数的当前值调用不同的宏\X

\def\xyz{\csname do\ifnum\X=10\relax a\else b\fi\endcsname}

\X当保存值 10时会抛出错误。当然,这可能通过许多不同的方式解决,但是

\def\xyz{\csname do\ifnum\X=10 a\else b\fi\endcsname}

无论如何都是正确的。

回到主要问题,有些情况有时无法考虑。TeX 在查找未分隔的参数时总是忽略空格。所有用 定义的宏都\newcommand使用未分隔的参数,因此

\parbox {3cm} {text}
\parbox
  {3cm}
  {text}

完全等价。此外

\newcommand{\foo}
  {something}

没有问题。例如,我通常建议设置环境定义,如

\newenvironment{foo}[1]
  {begin}
  {end}

当然,如果beginend必须分成多行,则同样的有关保护行尾字符的规则也适用。

一个潜在的令人费解的来源不是定义中的虚假空格,而是 TeX 读取规则。每当begin环境中的文本排版某些内容或更一般地开始一个段落时,文本begin必须以 结束\ignorespaces。示例:假设我们想在引文前面添加一个“标题”;我们可以将其传递给新环境,xquotation如下所示

\newenvironment{xquotation}[1]
  {\begin{quotation}\noindent\textbf{#1} --- \ignorespaces}
  {\end{quotation}

没有\ignorespaces输入

\begin{xquotation}{Murphy}
If something can fail, it will.
\end{xquotation}

将有破折号和“If”之间的空格。这个空格正好是参数后的行尾,如果\ignorespaces有效,则不考虑。如果环境结束在其begin部分中创建一个段落,但并不开始一个段落,因为在垂直模式下空格会被忽略。

答案3

Leo Liu 所说的大体上是正确的。通常,换行符相当于空格。但空行则不然。空行通常被解释为与 相同\par

如果不\long包含\def,就会\par中断。这就是为什么如果添加 ,空行会中断许多代码的原因%。这不是关于空格,而是关于\par

我建议你阅读 TeXbook 的第 20 章,了解宏定义的一般知识。如果没有,TeXLive 附带的 TeX by Topic 一书也很好地介绍了 TeX 如何读取你的输入。

总而言之,TeX 是一种自由格式的语言,就像 C/C++ 一样。唯一的主要区别是 TeX 根据上下文解释特殊字符(换行符等)(有时它们是空格,有时它们是\par,有时它们可​​以通过分配 catcode 来成为任何字符)。了解所有这些将帮助您清楚地了解何时应该使用 来%注释掉换行符。

相关内容