# 第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 --`以提示您所处的可视模式。

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

有三种退出可视模式的方法：`esc`，`Ctrl-C`和与当前可视模式相同的键。

后者的意思是，如果您当前处于逐行可视模式(`V`)，则可以通过再次按`V`退出它。如果您处于字符可视模式，则可以通过按`v`退出它。如果您处于逐块可视模式，请按`Ctrl-V`。

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

```
gv    转到上一个可视模式
```

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

## 可视模式导航

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

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

```
one
two
three
```

这次让我们从"two"行开始。按`v`进入字符可视模式：

```
one
[t]wo
three
```

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

```
one
[two
t]hree
```

假设您刚刚意识到还需要高亮显示"one"行，因此按`k`。令您沮丧的是，它现在排除了"three"。按`k`实际上会还原高亮，而不是使其高亮。

```
one
[t]wo
three
```

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

答案是肯定的。让我们稍微备份一下高亮显示"two"和"three"行的位置。

```
one
[two
t]hree    <-- 光标
```

视觉高光跟随光标移动。如果要将其向上扩展到行"one"，则需要在光标位于字母"two"而不是"three"上时向上移动光标。现在，您的光标在"three"行上。要移动它，用`o`或`O`切换光标位置。

```
one
[two     <-- 光标
t]hree
```

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

```
[one
two
t]hree
```

## 可视模式语法

可视模式是Vim的一种模式。成为一种模式意味着同一键的工作方式可能不同于另一种模式。幸运的是，可视模式与普通模式共享许多常用键。

例如，如果您有以下文字：

```
one
two
three
```

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

```
[one
two]
three
```

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

在普通模式下，有一些命令不需要移动，例如`x`删除光标下方的单个字符，`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 one = "one";
const two = "two";
const three = "three";
```

您只需要用"let"替换"const"的前两行。用*任何*可视模式高亮显示前两行，然后运行替代命令`: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`)。

您应该看到附加的 ";" 在每一行上。顺便说一下，在逐块可视模式下，要进入插入模式，可以使用`A`在光标后输入文本，也可以使用`I`在光标前输入文本。请勿将它们与正常模式下的`A`和`I`混淆。

另外，您也可以使用`:normal`命令：

-高亮显示所有3行(`vjj`)。 -输入`:normal! A;`。

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

## 递增数字

Vim有`Ctrl-X`和`Ctrl-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"s。 -运行`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-A`和`Ctrl-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--`。该技巧适用于任何可视模式运算符：`v`，`V`，和`Ctrl-V`。

## 选择模式

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

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

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

在常规编辑器中，高亮显示文本块并键入字母（例如字母"y"）后，它将删除高亮显示的文本并插入字母"y"。

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

将此行为与可视模式进行对比：如果您使用逐行可视模式(`V`)高亮显示一行文本并键入"y"，则高亮显示的文本不会被删除，而是由文字字母"y"代替。仅将其拉动并存储在拉动寄存器`"0`中。

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

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

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

如果发现使用可视模式操作的频率比正常模式操作的频率高得多，请当心。我认为这是一种反模式。运行可视模式操作所需的击键次数要多于普通模式下的击键次数。如果您需要删除一个内部单词，那么为什么只用三个按键(`diw`)就可以使用四个按键`viwd`（在视觉上高亮显示一个内部单词然后删除）呢？后者更为直接和简洁。当然，有时会使用适当的可视模式，但总的来说，更倾向于直接的方法。
