![哪些地方需要添加 % 来删除不需要的空格?](https://linux22.com/image/237685/%E5%93%AA%E4%BA%9B%E5%9C%B0%E6%96%B9%E9%9C%80%E8%A6%81%E6%B7%BB%E5%8A%A0%20%25%20%E6%9D%A5%E5%88%A0%E9%99%A4%E4%B8%8D%E9%9C%80%E8%A6%81%E7%9A%84%E7%A9%BA%E6%A0%BC%EF%BC%9F.png)
我曾遇到过空格导致不良影响的情况。很难追踪这些不良影响的原因。为了消除任何疑问,我经常过度使用 %,如下所示。
\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}
当然,如果begin
或end
必须分成多行,则同样的有关保护行尾字符的规则也适用。
一个潜在的令人费解的来源不是定义中的虚假空格,而是 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 来成为任何字符)。了解所有这些将帮助您清楚地了解何时应该使用 来%
注释掉换行符。