Emacs 编辑环境,第 2 部分: 学习 Emacs 的基本模式和编辑特性

本教程是系列文章中的第二部分,展示了如何使用文本编辑中的一些重要特性,并引入了模式的概念,向您介绍了它们的用途、如何调用它们、以及在您的日常编辑工作中可能用到的常见模式。此外还描述了一个用于定义缩写的特殊模式,而这些缩写可用于进行速记,并且解释了如何使用与具体模式无关的一些文本编辑特性——包括重要的文本操作命令、搜索和替换方法、以及内置拼写检查器。

本教程主要面向那些已经熟悉 Emacs 编辑器基础(如键盘输入方式、缓冲区范例)的用户,并说明了 Emacs 编辑器中一些关键的但属于中等难度的特性,包括编辑模式、增量搜索和其他重要的 Emacs 文本操作命令和工具。

完成本教程后,您将熟练掌握 Emacs 的编辑模式以及如何在 Emacs 中使用这些文本操作特性。

学习本教程的唯一前提就是您已经对 Emacs 有基本的了解,而本系列文章的第一个教程中提供了这些内容。

尽管本教程适用于各种级别 UNIX 专家,但是如果您对 UNIX 文件系统有基本的了解,那么将会很有帮助:

文件
目录
权限
文件系统层次结构

2.编辑模式

Emacs 被划分为无模式 的编辑器,这意味着它与其他的编辑器(如 vi)有所不同,对于运行编辑器命令或者向缓冲区插入文本的插入模式,没有特殊的命令模式——正如您在本系列前面的教程中所看到的,可以在任何时候完成命令和文本插入。

然而,Emacs 也有它自己的编辑模式,这就是扩展它的能力或者改变一些特性工作方式的函数。这些模式通常用于编辑某种类型或类别的数据,如常规文档(使用任何印欧语言编写)、用特定的计算机编程语言(C、Fortran、Lisp 等等)编写的源代码、采用某种方式进行格式化(大纲、电子邮件消息、Usenet 文章、基于字符的示例等等)或使用标记语言(超文本标记语言 (HTML)、Nroff、TeX 和可扩展标记语言 (XML))的文本。甚至专门有一种模式用于编辑非文本(二进制)的数据。另外,Emacs 还提供了许多特殊的模式,可用于其他数据类型和系统处理,包括网络连接和网际中继交谈 (IRC)、Shell 会话和 UNIX 文件系统自身。

这些模式可以划分为主要模式和次要模式。主要 模式规定了主要的编辑行为,并且仅应用于当前编辑会话中的缓冲区。在任何时刻,每个缓冲区都有且仅有一个活动的主要模式。

尽管在任何时刻,一个缓冲区仅有一个活动的主要模式,但您可以根据需要在主要模式之间进行切换。一些专门的主要模式还提供了额外的功能和辅助(如上下文突出显示和颜色设置),当您在编辑某些类型的文档时,这是很有帮助的,但是您无需为编辑某种类型的文件或文档选择特定的模式——可在任何模式中编辑一个 C 程序源代码文件,正如它可在编辑 C 程序语言的特殊模式中完成。

次要 模式通常提供了一些与任何特定的主要模式无关的特性或功能。可以把它们看作用于控制这些特性的切换:使用其函数名来调用一个次要模式可以开启或关闭该模式,任何时候您都可以开启多个次要模式。

次要模式包括 Overwrite 模式(本系列文章的第一部分教程对其进行了描述)、用于管理签入版本控制系统 (RCS) 的文件的 RCS 模式、以及处理自动文字回绕的 Auto Fill 模式。可以在任何时候同时激活所有这些次要模式以及许多其他类似的模式。

本教程的这一部分向您介绍成功地使用 Emacs 模式所需要了解的内容:

如何知道哪些模式是活动的
如何获取当前模式及其功能的描述
如何调用一个模式
您应该了解哪些模式

如本系列文章的第一个教程中所述,靠近 Emacs 窗口底部的突出显示栏,被称为模式行,可以告诉您当前缓冲区的所有情况——包括哪种模式当前是活动的。在模式行右边的括号里注明了当前的模式。最先列出主要模式的缩写名称,后面是任何次要模式的缩写名称。

当您启动 Emacs 编辑器而不打开任何文件时,则处于暂存缓冲区。在缺省情况下,这个缓冲区以 Lisp Interaction 模式打开,这是一个用于计算 Lisp 代码的特殊模式。

您可以用通常的方式启动 Emacs,观察模式行里写了些什么。

当您改变这些模式的时候,将在模式行里看到其反映出来了模式的改变。现在,请尝试下面的操作:按 Ins 键以打开 Overwrite 模式,并注意模式行的变化。(Ins 键与 overwrite-mode 函数进行了绑定)。

再次按 Ins 以关闭 Overwrite 模式。

当启用一个次要模式时,通常在括号里会有显示,紧接在主要模式的后面。然而,并非所有的次要模式都有这种指示器——有些次要模式是非常明了的(如 Tool Bar 模式),它在 Emacs 框架的顶部显示了图形工具栏。较新版本的 Emacs 中其他的次要模式都非常简单(并且始终处于开启状态),以至于如果要把它们全部显示出来,只会使显示变得非常混乱;例如,次要模式 Unify 8859 On Encoding 的目的是为各种 ISO 8859 字符集提供统一的编码方式,这样有助于进行国际化。

另外,一些模式提供了额外的指示器,这些指示器也会在模式行里显示出来。例如 Line Number 模式,通过在 L 后面跟上行号来表示,该行号是光标在缓冲区中的当前位置。

可以使用 describe-mode 函数,该函数与 C-h m 进行了绑定,用于获得当前模式的描述。当您运行这个函数时,将打开一个新的帮助缓冲区,其中列出了所有的键绑定,这些键绑定是您进行输入的缓冲区的当前主要模式所特有的,后面跟的是应用于任何处于打开状态的次要模式的绑定。

现在输入 C-h m,如图 1 所示。

列出适用的当前 Emacs 模式的键绑定

正如您所看见的,用于 Lisp Interaction 模式的特殊绑定之一是 Tab 键。在这个模式中,Tab 并不会像您希望的那样在打字机或文字处理应用程序中将光标移动到下一个制表位处,而是按照模式描述所说的,它会对当前 Lisp 代码行进行缩进。因为您没有在这个缓冲区中编写任何 Lisp 代码,所以 Tab 什么都不做——您可以试试看。

尽管暂存缓冲区通常设置为 Lisp Interaction 模式,但它并不是缺省 Emacs 模式。要找出缺省模式是什么,可以切换到一个新的缓冲区:输入 C-x b 并指定 lamb.txt 作为缓冲区的名称。输入 C-x 1 关闭帮助缓冲区。

您将看到这个新的 lamb.txt 缓冲区有了新的主要模式,即 Fundamental 模式。这就是 Emacs 缓冲区的缺省模式。在所有 Emacs 模式中,这种模式是最简单明了的,拥有最少的特殊键绑定和设置。在这种模式中,Tab 键将按照您所希望的方式进行工作。

再次键入 C-h m 继续工作并获取这些模式的描述。

您将看到下面对 Fundamental 模式的描述:

                Fundamental mode:

Major mode not specialized for anything in particular.
Other major modes are defined by comparison with this one.

再次键入 C-x 1 以关闭帮助窗口。

当您在新的缓冲区中打开现有文件中的内容时,Emacs 将基于该文件类型为您选择一种模式。如果您打开的文件包含 C 程序源代码,那么 C 模式将成为主要模式;同样,如果您打开的文件包含口语(如英语)文本,那么 Emacs 会将 Text 模式设置为主要模式。

您可以不断地改变模式,并且您还可以对所有这些设置进行配置,这样一来,就始终能够以特定的模式打开某种文件或者某种类型的缓冲区。表 1 描述了常用的 Emacs 模式,并给出了它们的函数名。

模式 函数 类型 描述
Fundamental fundamental-mode 主要模式 这一模式是缺省的 Emacs 模式,拥有最少设置和绑定。
Text text-mode 主要模式 这一模式是编辑文本的基本模式。
Abbrev abbrev-mode 次要模式 这一模式用于生成和使用缩写(请参见 3.Abbrev 模式)。
Auto Fill auto-fill-mode 次要模式 这一模式用于自动文字回绕、填充较长的行和段落。
Overwrite overwrite-mode 次要模式 这一模式用于覆盖缓冲区中任何现有的文本,而不是在当前位置插入文本。在缺省情况下,它与 Ins 键绑定。
C c-mode 主要模式 这一模式用于编辑 C 程序源代码。
Line Number line-number-mode 次要模式 这一模式用于显示当前行号。
Lisp Interaction lisp-interaction 主要模式 这一模式用于编辑和编译 Lisp 代码。
Paragraph-Indent Text paragraph-indent-text-mode 主要模式 这一模式是 Text 模式的一种特殊变体,其中的段落移动命令可用于首行缩进的段落,而不仅仅是由空行隔开的段落。
TeX tex-mode 主要模式 这一模式用于编辑 TeX 文档。
WordStar wordstar-mode 主要模式 这一特殊模式提供了 WordStar 编辑器的键绑定。

Emacs 模式是一些函数。要调用其中某个函数,您需要输入 M-x,然后给出模式名。

现在可以尝试在新的缓冲区中调用 Text 模式:输入 M-x text-mode 并按 Enter。您马上可以看到模式行中的变化,其中用 Text 替换了 Fundamental。

Text 模式是一种基本的模式,与 Fundamental 模式相比仅有很少的改变,所以它的优势并不明显;但它是对口语(如英语)文本进行编辑的一个很好的基础。从 TeX 模式到 Outline 模式,许多用于编辑某类文本或文档的特殊模式都是基于 Text 模式的。

尝试在新的缓冲区中输入一些文本,继续上一个教程中 William Blake 的主题:

Little lamb, who made thee?
Dost thou know who made thee?

Text 模式下,Tab 键被定义为相对于先前段落的缩进以缩进段落,如果先前的段落没有缩进,按 Tab 插入一个逐字制表符,移动光标到下一个制表符止。

要了解 Text 模式如何处理制表符,可以输入一些带制表符和空格的行:

在缓冲区的下一个新行中输入两个空格,然后输入文本 Gave thee life, and baid thee feed,并按 Enter 结束这个新的段落。

按 Tab,注意光标如何与前面的行(段落)进行对齐,然后输入 By the stream and o'er the mead;,并按 Enter。

输入一个不带缩进的新行:Gave thee something of delight, 并按 Enter。

按 Tab。注意您是怎样输入多个空格的,插入了一个字母制表符。输入行 Softest something, woolly, bright; 并按Enter。

输入 Gave thee such a tender voice, 并按 Enter。

按 Tab。插入了另一个制表符。输入行 Making all the vales rejoice?

您的缓冲区现在看起来应该与图 2 所示类似。

在 Text 模式中输入制表符

表 2 显示了 Text 模式所设置的键绑定。

键 描述或者函数
Esc 作为 mode-specific 命令的前缀
Esc Tab、M-Tab ispell-complete-word
Esc S、M-S center-paragraph
Esc s、M-s center-line

3.Abbrev 模式

Emacs 的缩写 是用一个特定的字符串定义的特殊单词。当在缓冲区中输入一个缩写时(并且 Abbrev 模式已打开),将对这个缩写进行扩展 或者使用定义它的字符串来替换它。

Abbrev 模式(一种次要模式)使得您可以对较长的字符串或者短语进行速记,但是您可能还会想到一些其他的使用方式。

添加缩写的简单方式是,运行一个 inverse-add 缩写函数 inverse-add-global-abbrev 或者 inverse-add-local-abbrev。这些函数允许您为缓冲区中的某个单词定义一个缩写,第一个函数可以对当前 Emacs 会话中打开的任何缓冲区应用这一缩写,而第二个函数仅对与当前缓冲区具有相同的主要模式的缓冲区定义这一缩写。后者可用于定义仅适用于某些模式的缩写,例如对包含程序源代码的缓冲区中的长变量名进行定义。

尝试定义一个缩写,并使其应用于所有的缓冲区:

在下一新行中,输入一个缩写单词 li,,以使得光标位于这个单词的末尾(即在 i 之后)。

通过输入 C-x a i g,运行 inverse-add-global-abbrev 函数。

在小缓冲区中给出提示的地方定义您的缩写:输入 Little lamb 并按 Enter。

请注意,您在缓冲区中输入的缩写使用定义它的字符串进行了替换,并且光标移到了这个定义的开头。

现在,将光标移动到一个新行,并按您刚刚用过的方法生成一个新的缩写,通过输入 x(缩写不区分大小写),并使用这个字符串 He is 来定义它。

现在您已经定义了两个缩写。然而,正如您在模式行里看到的,Abbrev 模式是关闭的。请打开它:输入 M-x abbrev-mode。用您刚刚生成的定义删除这两行,然后输入清单 1 中的代码。

Li, I’ll tell thee,
Li, I’ll tell thee:
x called by thy name,
For he calls himself a lamb.
x meek, and x mild;

li 和 x 的缩写按照您的输入进行了扩展,当您完成以上操作后,缓冲区看起来就应该与图 3 所示类似。

Emacs 缓冲区中的缩写扩展

这个示例显示了如何定义在所有缓冲区中都可以使用的缩写。要定义一个缩写,以使其仅应用于当前模式的缓冲区,可以使用 C-x a i l。

您还可以为缓冲区中的单个单词定义缩写。当您在编写程序源代码并且刚输入了一个较长的变量时,这种方式是特别有用的。

要为一个单词定义缩写,可以在光标位于这个单词之后时使用 C-x a g。在完成了这个操作之后,当 Abbrev 模式开启时,小缓冲区将提示您用缩写来替代那个单词。

现在,请尝试下面的操作:

在新行中输入 He became a little child。

当光标紧跟在 child 这一单词之后时,输入 C-x a g。

在小缓冲区中输入 c 并按 Enter。

用句点结束当前行,然后输入更多的行以观察所发生的扩展:

.
We are called by his name.
I a c, and thou a lamb,

请注意,Emacs 将逗号前面的字母 c 作为缩写,而不是单词 called 中的字母 c。

同样地,要定义一个仅应用于当前主要模式的缩写,可以使用 C-x a l。

要删除您在会话中定义的全部缩写,可以使用 kill-all-abbrevs 函数。

请尝试下面的操作:键入 M-x kill-all-abbrevs。

现在,在任何缓冲区(无论其处于何种模式)中都没有使用您所定义的缩写(li、x 和 c)对其进行扩展。再输入两行内容作为结束:

Little lamb, God bless thee!
Little lamb, God bless thee!

4.文本操作

在这一部分中,将学习一些用于编辑文本的特殊命令和键绑定,无论当前的主要模式是何种模式,其中大多数的命令和键绑定都是可用的。

可以自动对区域按不同的方式进行缩进。通过输入 C-x C-i 来运行 indent-rigidly 函数,该函数会将区域中所有行向右缩进一个空格。

尝试下面的操作:

输入 C-Space 以便对缓冲区底部的标记进行设置。

将光标移到“Little lamb, I'll tell thee,”这一行的开头,以将缓冲区中最后的 10 行标记为区域。

输入 C-x C-i 以使这一区域缩进一个空格。

再次输入 C-x C-i 以使这个区域再缩进一个空格。

正如您可以多次运行 indent-rigidly,通过在该函数的前面加上 C-u 和一个数字,您还可以按指定的空格数来进行缩进,使用负数可以将区域向左移动。

尝试下面的操作:

要再对这一区域缩进 10 个空格:输入 C-u 10 C-x C-i。

要使缩进回退 5 个空格:输入 C-u -5 C-x C-i。

在完成该操作之后,您的缓冲区应该与图 4 所示类似。

插入严格缩进

indent-rigidly 函数也绑定到 C-x Tab。

要填充这一区域,调整右边距参差不齐的文本,并运行 fill-region 函数。还有一个类似的函数 fill-paragraph,它适用于当前段落。它与 M-q 的键盘绑定是相同的。

尝试下面的操作:输入 M-x fill-region。请注意,在填充了该区域之后,光标将移动到这个区域之后。

和任何 Emacs 格式化命令一样,可以使用 undo 函数对缩进和填充命令进行撤消,本系列文章的第一部分教程中对其进行了描述。现在立即尝试下面的操作以撤消区域填充:输入一次 C-_。

正如您可以使用缩进来添加或删除垂直的间距,您还可以去掉任何现有的水平间距。要进行这项操作,可以使用 delete-horizontal-space 函数,M-/(在 Meta 键后面加上 / 键)。它将删除位于光标左边的第一个非空格字符和光标右边的第一个非空格字符之间所有的前导空格,而无论光标是否恰好位于空格处。

继续尝试下面的操作。要删除缓冲区中的所有前导空格,可以将光标移到每一行的空格处,并输入 M-/,然后光标将移动到下一个有空格的行。

要添加一行的垂直间距,您始终可以按 Enter,但这样做将会移动光标。要添加垂直间距而不移动光标,可以运行 open-line 函数,它绑定到 C-o。

尝试下面的操作:将光标从缓冲区的顶端向下移动 8 行,以使其位于“Little lamb, I’ll tell thee,”这一行的开始处,并输入 C-o。现在,您的缓冲区应该与图 5 所示类似。

删除水平间距并插入垂直间距

Emacs 有一些用于调换 的命令,这些命令允许您交换紧挨在光标前面的和紧挨在光标后面的字符、单词或者行。对于实现文本中的快速更正,这些命令是非常合适的。

使用 C-t,transpose-chars 函数,以调换光标前的单个字符和光标后的单个字符;使用 M-t,transpose-words 函数,以调换光标前后的单个单词。

现在,请尝试下面的操作:

将光标移动到单词 For 中的字母 o 处,然后输入 C-t 以调换字符 o 和 F。

再次输入 C-t 以调换字符 r 和 F。

将光标移回到 F 处,并输入一次 C-t,以将 F 回退一个字符。

将光标再次移回到 F 并再一次输入 C-t,以将 F 移动到这一行的开头处。

输入 M-t以调换单词 For 和 he。

再次输入 M-t 以调换单词 For 和 calls。

将光标移动到 he 和 For 之间,并再次输入 M-t 以调换它们。

将光标移动到 calls 和 For 之间,并再次输入 M-t,以调换它们。

最后一次输入 M-t,以调换 calls 和 he。

transpose-lines 函数,C-x C-t,可以调换光标所在的行和光标前面的行。

尝试下面的操作:将光标移动到以“I a child”开头的行的开头处,并输入 C-x C-t。

请注意,您还可以使用通用参数在这些命令之前加上一个数值,C-u: C-u 2 C-x C-t 会将光标所在的行与光标前面的两行进行调换。

另一个有用的命令是 delete-indentation,它可以将光标所在的行与前面的行连接起来,并用空格进行分隔。它绑定到 M-^,通过按住 Meta 键并使用 Shift 键输入一个脱字符号 (^) 来输入该命令。另一种方法是,C-1 M-^ 可以将当前行与紧跟其后的行连接起来。

有几个 Emacs 函数可以用于转换大小写。uppercase-word 函数(绑定到 M-u)可以将光标处到光标所在词的词尾之间的所有文本都转换为大写字母。类似地,downcase-word(绑定到 M-l)可以将光标处到光标所在词的词尾之间的所有文本转换为小写字母。

在缓冲区中尝试下面这些操作:

将光标移动到以“For he calls”开头的行,并输入 M-c M-c M-l M-c M-l M-c 以使这一行正确地变为大写。

向下移动光标到以“We are called”开头的行,并且输入 M-u M-u M-u M-u M-u M-u 以使整行内容转换为大写字母。

输入 C-a 以便将光标移动到这一行的开头,并输入 C-c C-l C-l C-l C-l C-c C-l 以使这一行正确地变为大写。

通过在这些命令前面加上带负参数的函数(如 M–),您可以对光标之前 的单词进行操作,可以通过按住 Meta 键然后按连字符 (-) 来输入这个命令。通过使用 downcase-region 和 upcase-region 函数,您可以对区域 应用改变大小写的命令,这两个函数分别绑定到 C-x C-l 和 C-x C-u。

表 3 列出了您刚刚学过的各种文本操作命令,并对它们的含义进行了描述。

绑定 命令或者函数 描述
C-x C-i、C-x Tab indent-rigidly 这一命令对区域中的(或光标所在的)行进行缩进。
fill-region 这一命令填充区域里的所有段落。
M-q fill-paragraph 这一命令填充光标所在的单个段落。
M-/ delete-horizontal-space 这一命令删除光标左右的任何水平间距。
C-o open-line 这一命令以垂直间距在光标下方打开一个新行,而不移动光标。
C-t transpose-chars 这一命令调换光标左右的单个字符。
M-t transpose-words 这一命令调换光标左右的单个单词。
C-x C-t transpose-lines 这一命令调换光标所在的行与光标前面的行。
M-^ delete-indentation 这一命令将光标所在的行和前面的行连接起来。以 C-1 作为开始,以连接光标所在的行和下一 行。
M-u uppercase-word 这一命令将光标处到其所在词的词尾之间的文本转换为大写字母。
M-l downcase-word 这一命令将光标处其所在词的词尾之间的文本转换为小写字母。
C-x C-l downcase-region 这一命令将区域中的内容转换为小写字母。
C-x C-u upcase-region 这一命令将区域中的内容转换为大写字母。

5.搜索和替换文本

Emacs 中的搜索和替换命令可以在所有模式中使用,本部分将对这些命令进行描述。

增量搜索

Emacs 中最基本和最常用的搜索方式是使用增量搜索,之所以称为增量搜索,是因为当您输入第一个字符时,将立即开始搜索工作。这一方式在您输入每个字符时进行增量 搜索,以搜索文本 lamb 为例,您输入字符 l 时,光标将移动到缓冲区中的下一个 l,接着您输入字符 a,光标将移动到 la 的第一个实例处(这与找到的第一个 l 的位置不一定相同),依此类推。

这是一种很有效的文本搜索方式,因为与带有搜索框工具的应用程序不同,在这些应用程序中,您需要输入一个术语,然后按Enter(或者更糟,您必须单击 OK 按钮),而在您输入关键词的第一个字母时立即开始进行增量搜索。一旦找到正确的匹配项,您即可停止输入。

最常用的增量搜索是 isearch-forward 函数,它绑定到 C-s。它从缓冲区中光标处开始前向搜索您给出的文本。要重复搜索或移到下一个匹配项,可以再次输入 C-s。

当您到达了缓冲区的末尾,Emacs 会发出提示声,并在小缓冲区中显示一则消息,即已到达缓冲区末尾。如果此后您再次输入 C-s,搜索工作将回绕到缓冲区的开头(小缓冲区将给出提示信息)。

尝试下面的操作:

输入 C-s。请注意小缓冲区中如何提示您提供要进行搜索的字符串。

输入 l 并观察缓冲区中光标如何移动到下一个 l。如果您使用的是最新版本的 Emacs,那么将突出显示缓冲区中所有的 l 字符。

输入 e 并观察光标如何向前移动和突出显示下一个 l,以及紧跟其后的 e 字符。

输入一个空格并且观察光标如何移动到下一行并突出显示其中的 le 。

输入 C-s 重复搜索 le ,并观察光标如何移动到下一行。

输入 C-s 重复搜索 le ,并注意 Emacs 如何告诉您搜索工作失败,即搜索工作已到达缓冲区末尾,而没有找到您要搜索的 le的另一个匹配项。

输入 C-s 以便从头开始重复搜索 le,并观察光标如何移动到在缓冲区顶部找到的第一行。

Emacs 还提供了一种搜索缓冲区中可见文本的搜索方式:C-s C-w 将光标处到其所在词的词尾之间的字符串放入搜索缓冲区,而 C-s C-y 将光标处到其所在行 的行尾之间的所有内容放入搜索缓冲区。

增量搜索通常是不区分大小写的;然而,如果您在搜索中指定搜索全部小写字母之外的任何内容,那么将仅匹配您所给出的大小写。

后向增量搜索

要从光标处开始后向搜索,可以使用 isearch-backward(绑定到 C-r),它将逆向搜索整个缓冲区。

与向前增量搜索相同,两次输入这个命令将开始搜索最近搜索过的文本。当您到达缓冲区的顶部,再次输入 C-r 则将回绕到缓冲区的底部。

尝试下面的操作:输入 C-r lit 以进行逆向搜索,然后多次输入 C-r,用以逆向回绕到缓冲区的底部。

非增量搜索

Emacs 也提供了非增量搜索的方式。例如,您希望搜索缓冲区中可见的某个特定短语或者字符串,那么您希望进行粘贴而不是输入,在这种情况下,非增量搜索是非常有用的。

无论是进行前向和逆向搜索,非增量搜索的工作方式都是相同的。要完成这项操作,可以在输入 C-s 或者 C-r 之后按 Enter,输入要搜索的完整字符串,并再次按 Enter。

尝试下面的操作:

输入 C-s 以开始前向搜索,并按 Enter 以指定通过非增量搜索来完成。

输入单词 little 并按 Enter。

单词搜索

有时您可能希望搜索缓冲区中的单词或短语,而不管它们是如何分隔或者如何进行格式化的,它们甚至可能位于不同的行。

例如,如果您希望在缓冲区中匹配 feed by,而这个短语刚好被换行符分隔开了,那又应该如何操作呢?

尝试下面的操作:输入 C-r 并给出 feed by 作为要搜索的文本。

因为这两个单词之间有一个换行符,所以 Emacs 很快地发出提示音并报告“Failing I-search”。

要对短语进行匹配,而不管单词之间存在何种分隔,可使用 Emacs 的单词搜索。无论使用前向或者逆向搜索都可以这样操作,按Enter,输入 C-w,然后给出要搜索的单词或者短语。

再次尝试这一搜索:

将光标移动到缓冲区的顶端。

输入 C-s 以开始前向搜索。

按 Enter。

输入 C-w 以指定单词搜索。

输入 feed by 并按 Enter。

即使这个字符串跨行,也能够进行匹配,并且光标移动到这个短语第二行的 By 之后。

正则表达式搜索

您还可以在 Emacs 编辑器中搜索正则表达式。要完成这项操作,可以运行 isearch-forward-regexp 或者 isearch-backward-regexp 函数。这两个函数分别绑定到 C-M-s 和 C-M-r。然后,给出一个正则表达式作为参数。这些搜索是增量的。

尝试前向搜索,并注意随着您所构建的正则表达式的不同,其匹配项也会发生变化:

输入 C-M-s 以开始前向正则表达式搜索。

给出正则表达式 l.*e,并注意对于您输入的每个字符,其匹配结果是如何变化的。

替换文本

Emacs 中提供了几种替换文本的方式。

replace-string 函数将提示您输入进行匹配和进行替换的字符串,它将替换从光标处到缓冲区末尾的所有实例。

尝试将缓冲区中的全部 something 替换为 clothing:

输入 M-x replace-string 并按 Enter。

输入 something 并按 Enter。

输入 clothing 并按 Enter。

在该命令运行结束之后,Emacs 将在小缓冲区中向您报告执行了多少次替换,在这个示例中是两次。

要在整个缓冲区中删除 某个单词或者短语,可以运行这个命令,并且将其替换为空字符串。

另一个用于替换文本的功能强大的函数是 replace-regexp,这个函数使用正则表达式作为要搜索的字符串,并且将其替换为一个文本字符串。

最后,您可以运行 query-replace 函数,它会对每个需要替换的实例提出询问。它绑定到 M-%。表 4 对每次匹配询问的选择进行了描述。

表 4. Emacs 的 query-replace 函数的选项
键 描述
空格、y 替换这个匹配。
Del、n 跳过这一匹配到下一个匹配。
Enter、q 退出 query-replace。
. 进行本次替换,然后退出 query-replace。
, 进行本次替换,将光标移动到此处,然后退出 query-replace。
C-r 指定递归编辑。
C-w 删除这个匹配并递归编辑。
C-l 重绘屏幕,并使这一行位于屏幕正中位置。
! 继续进行所有的替换,而无需再次询问。
E 编辑替换的字符串。
^ 退回到前一次替换。

replace-regexp 和 query-replace-regexp 函数的工作方式是类似的,但是它们使用正则表达式作为要进行替换的字符串。

搜索和替换命令汇总

表 5 汇总了您在前面刚刚学习到的各种 Emacs 搜索和替换命令。

表 5. Emacs 搜索和替换命令
绑定 命令或者函数 描述
C-s [字符串] [C-w] [C-y] isearch-forward 前向增量地在整个缓冲区中搜索字符串(在缺省情况下,将搜索您上一次给出的搜索字符串,如果存在),C-w 使用从光标处到光标所在单词的词尾之间的文本,以及 C-y 使用从光标处到光标所在行的行尾之间的全部内容。
C-r [字符串] [C-w] [C-y] isearch-backward 后向增量地在整个缓冲区中搜索字符串(在缺省情况下,将搜索您上一次给出的搜索字符串,如果存在),C-w 使用从光标处到光标所在单词的词尾之间的文本,C-y 使用从光标处到光标所在行的行尾之间的全部内容。
C-s Enter C-w 单词或者短语 word-search-forward 在整个缓冲区中前向搜索给定的单词或者短语(不管它们之间如何分隔)。
C-r Enter C-w 单词或者短语 word-search-backward 在整个缓冲区中后向搜索给定的单词或者短语(不管它们之间如何分隔)。
C-M-s isearch-forward-regexp 在整个缓冲区中前向增量搜索给定的正则表达式。
C-M-r isearch-backward-regexp 在整个缓冲区中后向增量搜索给定的正则表达式。
replace-string 从光标处到缓冲区末尾搜索给定的字符串,并使用给定的字符串来替换它。
replace-regexp 从光标处到缓冲区末尾搜索给定的正则表达式,并使用给定的字符串来替换它。
M-% query-replace 从光标处到缓冲区末尾搜索给定的字符串,对于搜索到的每个实例,询问(如表 4 中所述)是否使用给定的字符串来进行替换。
C-M-% query-replace-regexp 从光标处到缓冲区末尾搜索给定的正则表达式,对于搜索到的每个实例,询问(如表 4 中所述)是否使用给定的字符串来进行替换。

6.使用拼写检查器

Ispell 是一个交互式的 UNIX 拼写检查器,并且 Emacs 中内置了这个拼写检查器,对于检查缓冲区中拼写错误的单词,它的功能非常强大并且易于使用。本部分内容对各种 ispell- 函数进行了描述。

单词拼写检查

使用 ispell-word 函数(或者它等价的键绑定 M-$)来检查光标处单词的拼写。

单词 baid 看起来似乎不正确。将光标移动到这个单词,并通过输入 M-$ 来检查这个单词的拼写。

Emacs 不认识这个单词,所以将其突出显示为拼写错误;缓冲区窗口上方将出现一个新窗口,其中给出了建议列表,如图 6 所示。每个建议的前面都有一个字符,您可以输入这个字符以使用相应的建议来替换拼写错误。(您也可以输入 C-g 以取消这个替换。)

图 6. 在 Emacs 中使用 Ispell 纠正拼写
在 Emacs 中使用 Ispell 纠正拼写。

找到您所需要的单词 bid,然后按与之相应的键。Ispell 退出,同时用您所选择的单词替换拼写错误的单词。

检查一个区域中的拼写

您还可以使用 ispell-region 函数检查某个区域中的拼写。

尝试使用鼠标突出显示缓冲区里的最后两行,在拖动鼠标时按住 B1(如本系列文章的第一个教程中所述)。然后输入 M-x ispell-region 以检查被突出显示的区域中文本的拼写。

Ispell 在小缓冲区中向您报告拼写检查完成,且没有发现拼写错误。

检查缓冲区的拼写

要检查整个缓冲区里的拼写,可以使用 ispell-buffer 函数。

尝试进行以下操作:键入 M-x ispell-buffer。

对于所有的 Ispell 命令,当在缓冲区的拼写检查中发现了拼写错误时,可以对其进行各种处理。表 6 对这些选项进行了描述。

表 6. Ispell 单词替换命令
键 描述
字符 使用以(字符)开头的替换建议。
空格 在此上下文中接受这个单词作为更正。
i 接受这个单词作为更正并将其插入到个人字典文件。
a 仅对于此次 Emacs 会话接受这个单词作为更正。
A 仅对于此次 Emacs 会话中的缓冲区,接受这个单词作为更正。
r 使用您输入的字符串替换这个单词(Ispell 会再次进行拼写检查)。
R 使用您输入的字符串替换这个单词(Ispell 会再次进行拼写检查),并对整个缓冲区的剩余部分运行 query-replace。
l 使用给定的字符串替换这个单词,并在给定的字典文件中查找这个新的字符串。
u 将这个单词的小写形式插入到个人字典文件。
m 使用给定的字符串替代这个单词,将其保存到个人字典,然后再次对该单词进行拼写检查。
C-l 使当前行位于屏幕中心位置。
C-r 进入一个递归编辑。
C-z 挂起 Emacs。(In X 窗口系统中,这个操作将对 Emacs 客户端窗口进行图标化。)
x 退出拼写检查,并将光标移回到它的原始位置。
X 退出拼写检查,并使光标位于它当前所在的位置。
q 立刻结束拼写检查。
? 显示选项菜单。

在发生拼写错误时进行捕获

Flyspell 模式是一个特殊的次要模式,该模式可以在您输入拼写错误的单词时,突出显示这些错误。当您在编写快速文档(如电子邮件)或者第一次编写需要即刻投入使用的草案初稿时,这一模式特别有用。当 Emacs 发现了拼写错误时,它并不会让您停止输入,您可以继续输入,但将在缓冲区中突出显示这一拼写错误的单词。

Flyspell 模式的工作原理是在后台运行 Ispell;在您打开 Flyspell 模式后,将检查缓冲区中现有的文本,并将突出显示其中所有的拼写错误。

尝试下面的操作:

打开 Flyspell 模式:键入 M-x flyspell-mode。

向下移动光标到第一节的末尾,输入下面的两行内容,且有意地在第一行中出现拼写错误:

Little lamb, hwo made thee?
Dost thou know who made thee?

请注意,Emacs 无法识别 Blake 古语 Dost,尽管您知道这一拼写是正确的。它和拼写错误的单词 hwo 都被突出显示,如图 7 所示。

图 7. 使用 Emac 的 Flyspell 模式
使用 Emacs 的 Flyspell 模式

要纠正这些突出显示的单词,可以使用鼠标指针在每个错误的单词上单击中键,这时会出现建议单词的菜单。对于 hwo,选择正确的who;对于 Dost,选择 Accept (buffer) 以在该缓冲区中将此拼写作为正确的拼写而接受。

除了鼠标控制之外,Flyspell 模式还绑定了更多的命令;表 7 给出了相应的列表。

表 7. Flyspell 模式的键绑定
绑定 描述
M-$ 使用 Ispell 纠正最近一个拼写错误的单词。
M-x flyspell-auto-correct-word,M-Tab 根据 Ispell 给出的修改建议,自动地纠正最近一个拼写错误的单词。
M-x flyspell-auto-correct-previous-word 根据 Ispell 给出的修改建议,自动地纠正前面拼写错误的单词。
M-x flyspell-correct-word,B2 显示单词建议的弹出菜单。

Emacs 拼写命令汇总

表 8 汇总了您刚刚学习过的各种 Emacs 拼写函数,对其含义进行了描述,并给出缺省键绑定(如果存在)。

表 8. Emacs 的拼写命令
绑定 命令或者函数 描述
M-$ ispell-word 调用 Ispell 以检查光标处单词的拼写。
ispell-region 调用 Ispell 以检查某一区域中的拼写。
ispell-buffer 调用 Ispell 以检查从光标处到缓冲区末尾的所有单词的拼写。
flyspell-mode 在您输入内容的同时,调用 Ispell 以便在后台检查缓冲区中所有单词的拼写,突出显示所有的拼写错误。

7.总结

在完成本教程的学习之后,您对 Emacs 中的许多重要编辑概念有了很好的理解,并且在学习过程中,您还了解到了许多功能强大的技术。您还了解了什么是 Emacs 模式,以及如何使用这些模式,您了解了各种文本操作诀窍,包括进行缩进的方法、改变大小写、以及搜索和替换,您了解了如何使用 Emacs 拼写检查器和缩写工具。

您已开始获知 Emacs 的基本用法,但对于 Emacs 值得知道的还有很多。请注意看本系列文章的第三部分,以获得一些高级概念。

你可能感兴趣的:(Emacs 编辑环境,第 2 部分: 学习 Emacs 的基本模式和编辑特性)