Skip to main content

第11章 可视模式

高亮显示文本块并对其进行更改,是很多文本编辑器中的常见功能。 Vim也可以使用可视模式实现这一功能。在本章中,您将学习如何使用可视模式来有效地处理文本块。

三种可视模式

Vim有三种可视模式,分别是:

v         逐字符可视模式
V 逐行可视模式
Ctrl-v 逐块可视模式

如果您有下列文字:

one
two
three

逐字符可视模式用于选择单个字符。在第一行的第一个字符上按v。然后使用j跳转至下一行。它高亮显示从"one"到光标位置的所有文本。现在,如果您按gU,Vim将高亮显示的字符转为大写。

逐行可视模式适用于整行。按V并观看Vim选择光标的所在行。就像逐字符可视模式一样,如果您运行gU,Vim将高亮显示的字符转为大写。

逐块可视模式适用于行和列。与其他两种模式相比,它为您提供了更大的移动自由度。按Ctrl-V,Vim像逐字符可视模式一样高亮显示光标下的字符,但向下移动时,除非光标已经在行尾,否则不会高亮显示光标上方的整行,它跳转至下一行时高亮显示尽可能少的字符。尝试用h/j/k/l移动,并观察光标的移动。

在Vim窗口的左下方,您会看到显示-- VISUAL ---- VISUAL LINE ---- VISUAL BLOCK --以提示您所处的可视模式。

当您处于可视模式时,可以通过按vVCtrl-V键切换到另一种可视模式。例如,如果您处于逐行可视模式,并且想要切换为逐块可视模式,请运行Ctrl-V。试试吧!

有三种退出可视模式的方法:escCtrl-C和与当前可视模式相同的键。后者的意思是,如果您当前处于逐行可视模式(V),则可以通过再次按V退出它。如果您处于字符可视模式,则可以通过按v退出它。如果您处于逐块可视模式,请按Ctrl-V

实际上,还有另一种进入可视模式的方式:

gv    转到上一个可视模式

它将在与上次相同的高亮显示的文本块上启动相同的可视模式。

可视模式导航

在可视模式下,您可以使用Vim动作(motion)扩展高亮显示的文本块。

让我们使用之前使用的相同文本:

one
two
three

这次让我们从"two"行开始。按v进入字符可视模式(这里的方括号[]表示高亮显示的字符):

one
[t]wo
three

j,Vim将高亮显示从"two"行到"three"行的第一个字符的所有文本。

one
[two
t]hree

假设您刚刚意识到还需要高亮显示"one"行,因此按k。令您沮丧的是,它现在排除了"three"高亮。

one
[t]wo
three

有没有一种方法可以自由地扩展视觉选择范围,以向您想要的任何方向发展?

答案是肯定的。让我们先恢复光标到高亮显示"two"和"three"行的位置。

one
[two
t]hree <-- 光标

高亮区域跟随光标移动。如果要将其向上扩展到行"one",则需要将光标移动到"two",现在您的光标在"three"行上。这时可以用oO切换光标位置。

one
[two <-- 光标
t]hree

现在,当您按k时,它不再缩小选择,而是向上扩展。

[one
two
t]hree

在可视模式中使用oO,光标会在高亮选择区域的开头和结尾跳转,以便与您扩展高亮区域。

可视模式语法

可视模式与普通模式使用相同的操作符(operations)。

例如,如果您有以下文字,然后您想在可视模式中删除前两行:

one
two
three

用逐行可视模式(V)高亮显示"one"和"two"行:

[one
two]
three

按下d键将删除选择,类似于普通模式。请注意,与普通模式的语法规则有所不同,动词+名词不适用可视模式。虽然存在相同的动词(d),但在可视模式下没有名词。可视模式下的语法规则是名词+动词(反过来了),其中名词是高亮显示的文本。首先选择文本块,然后进行操作。

在普通模式下,有一些命令不需要名词(motion),例如x删除光标下方的单个字符,还有r替换光标下方的字符(rx将当前光标下的字符替换为x)。在可视模式下,这些命令现在将应用于整个高亮显示的文本,而不是单个字符。回到高亮显示的文本:

[one
two]
three

运行x会删除所有高亮显示的文本。

您可以使用此行为在markdown文本中快速创建标题。假设您需要快速下面的文本转换为一级markdown标题("==="):

Chapter One

首先,您使用yy复制文本,然后使用p粘贴文本:

Chapter One
Chapter One

现在转到第二行,以逐行可视模式选择它:

Chapter One
[Chapter One]

在markdown中,您可以通过在文本下方添加一系列=来创建标题,因此您可以通过运行r=来替换整个高亮显示的文本:

Chapter One
===========

要了解有关可视模式下的运算符的更多信息,请查看:h visual-operators

可视模式和Ex命令

您可以有选择地在高亮显示的文本块上应用Ex命令。如果您具有以下表达式,并想将前两行的"const"替换为"let":

const one = "one";
const two = "two";
const three = "three";

任意 可视模式高亮显示前两行,然后运行替换命令:s/const/let/g

let one = "one";
let two = "two";
const three = "three";

请注意,我说过您可以使用 任何 可视模式执行此操作。您不必高亮显示整个行即可在该行上运行Ex命令。只要您在每行上至少选择一个字符,就会应用Ex命令。

跨多行编辑

您可以使用逐块可视模式在Vim中跨多行编辑文本。如果需要在每行末尾添加分号:

const one = "one"
const two = "two"
const three = "three"

将光标放在第一行上:

  • 进入逐块可视模式,并向下两行(Ctrl-V jj)。
  • 高亮显示到行尾($)。
  • 按(A) ,然后键入";"。
  • 退出可视模式(esc)。

您应该看到在每一行后面附加的 ";"。666! 有两种方法可以从逐块可视模式进入输入模式:可以使用A在光标后输入文本,也可以使用I在光标前输入文本。请勿将它们与普通模式下的AI混淆。(普通模式中,A表示在行尾添加内容,I表示在行尾非空字符前插入内容)。

另外,您也可以使用:normal命令在多行添加内容: -高亮显示所有3行(vjj)。 -输入:normal! A;

记住,:normal命令执行普通模式命令。您可以指示它运行A;在该行的末尾添加文本";"。

递增数字

Vim有Ctrl-XCtrl-A命令来减少和增加数字。与可视模式一起使用时,可以跨多行递增数字。

如果您具有以下HTML元素:

<div id="app-1"></div>
<div id="app-1"></div>
<div id="app-1"></div>
<div id="app-1"></div>
<div id="app-1"></div>

有多个具有相同名称的id是一个不好的做法,因此让我们对其进行递增以使其唯一:

  • 将光标移动到 第二行的 "1"。
  • 启动逐块可视模式,并向下移动3行(Ctrl-V 3j)。这高亮显示剩余的"1",现在除了第一行,所有的"1"应该已经高亮。
  • 运行g Ctrl-A

您应该看到以下结果:

<div id="app-1"></div>
<div id="app-2"></div>
<div id="app-3"></div>
<div id="app-4"></div>
<div id="app-5"></div>

g Ctrl-A在多行上递增数字。 Ctrl-X/Ctrl-A也可以增加字母。如果您运行:

:set nrformats+=alpha

nrformats选项指示Vim将哪个基数视为Ctrl-ACtrl-X递增和递减的“数字”。通过添加alpha,现在将字母字符视为数字。如果您具有以下HTML元素:

<div id="app-a"></div>
<div id="app-a"></div>
<div id="app-a"></div>
<div id="app-a"></div>
<div id="app-a"></div>

将光标放在第二个"app-a"上。使用与上述相同的技术(Ctrl-V 3j 然后 g Ctrl-A)增加ID。

<div id="app-a"></div>
<div id="app-b"></div>
<div id="app-c"></div>
<div id="app-d"></div>
<div id="app-e"></div>

选择最后一个可视模式区域

前面章节中我提到了gv可以快速高亮显示上一个可视模式选择的内容。您还可以使用以下两个特殊标记转到最后一个可视模式的开始和结束位置:

'<    转到上一个可视模式高亮显示的第一个位置(行)(译者注,英文原版中'<'前面的符号是`,但这应该是一个错误,应该是单引号')
'> 转到上一个可视模式高亮显示的最后位置(行)

之前,我提到过您可以在高亮显示的文本上有选择地执行Ex命令,例如::s/const/let/g。当您这样做时,您应该看到以下内容:

:'<,'>s/const/let/g

您实际上是在使用('<, '>) 标记作为范围来执行 s/const/let/g命令。这太有趣了!

您随时可以随时编辑这些标记。比如,如果您需要从高亮显示的文本的开头到文件的末尾进行替换,则只需将命令行更改为:

:'<,$s/const/let/g

从插入模式进入可视模式

您也可以从插入模式进入可视模式。在插入模式下进入字符可视模式:

Ctrl-O v

回想一下,在插入模式下运行Ctrl-O可以使您执行普通模式命令。在普通模式命令挂起模式下,运行v进入逐字可视模式。请注意,在屏幕的左下方,它显示为--(insert) VISUAL--。该技巧适用于任何可视模式运算符:vV,和Ctrl-V

选择模式

Vim具有类似于可视模式的模式,称为选择模式。与可视模式一样,它也具有三种不同的模式:

gh         逐字符选择模式
gH 逐行选择模式
gCtrl-h 逐块选择模式

选择模式比Vim的可视模式更接近常规编辑器的文本高亮显示行为。

在常规编辑器中,高亮显示文本块并键入字母(例如字母"y")后,它将删除高亮显示的文本并插入字母"y"。如果您使用逐行选择模式(gH)高亮显示一行文本并键入"y",它将删除高亮显示的文本并插入字母"y",这与常规文本编辑器非常相似。

将此行为与可视模式进行对比:如果您使用逐行可视模式(V)高亮显示一行文本并键入"y",则高亮显示的文本不会被删除且被字母"y"代替,而是仅将其复制(yank)。在选择模式中,你不能执行对高亮文本执行普通模式的命令。

我个人从未使用过选择模式,但是很高兴知道它的存在。

以聪明的方式学习可视模式

可视模式是Vim高亮显示文本的过程。

如果发现使用可视模式操作的频率比正常模式操作的频率高得多,请当心。我认为这是一种反模式。运行可视模式操作所需的击键次数要多于普通模式下的击键次数。假设您需要删除一个内部单词(inner word,请回顾前面的文本对象),如果可以只用三个按键(diw),为什么要使用四个按键viwd(先v进入可视模式,然后iw高亮一个内部单词,最后d删除)呢?前者更为直接和简洁。当然,有时使用可视模式是合适的,但总的来说,更倾向于直接的方法。