效率至上-一文带你真正走进vim
vim一直是程序员之间比较有争议的一个话题。有人认为她是编辑器之神,有人则认为她古老过时,远远不如IDE,或是以当红小生vscode为代表的图形化文本编辑器。无论爱恨,我们的开发工作,大到远程登录服务器coding,修改config文件,小到git commit message,或多或少总要接触她。
为什么要写这篇blog呢,是因为我发现各大平台充斥的vim教程类blog其实很不友好,大多数是命令的堆砌,很少有对思想的解读。由此造成的结果,很多工 程师对vim总是敬畏三分,或者就算部分人可以使用vim,也只是以自己的固有思维,结合vim的命令操作,并没有真正掌握vim的精髓。所以我尝试用自己的方式,试图帮助大家系统地建立起vim的知识系统。
文章主要结构如下:
- 首先介绍
vim编辑器最简单、基本的操作,让你快速入门,在遇到vim时,可以不至于惊慌,从容完成任务。如果想到某些操作,比如常用的复制、粘贴之类,可以到第二部分查找对应高阶操作,循序渐进使用vim。 - 接下来,将会介绍
vim一系列高级操作,将我们的效率最大化。注:这部分信息量较大,建议您在阅读部分内容后,快速浏览不熟悉的命令,做到心中有数;随后可前进到第三部分;回过头来,再循序渐进,边学边练。 - 最后,试图讲述
vim思想的精髓,既让我们真正对vim的操作融会贯通,又让我们可以在使用其他IDE/编辑器时应用这些思想,甚至在我们自己设计、实现功能、组件时,都能进行应用。这才算真正掌握了神器vim。
vim有三个模式,分别为普通(正常)模式、插入模式以及命令模式。
- 普通模式:一般用于浏览文件,也包括一些复制、粘贴、除等操作。
- 插入模式:主要用来输入、修改、删除字符,此时的操作,除了不能用鼠标外,与我们日常在编辑器中操作无异。普通模式下,通过
i等命令进入插入模式。 - 命令模式:用以执行一些输入并执行一些vim或插件提供的指令。在普通模式下通过输入
:后,可以发现,屏幕的右下角会出现:,此时便进入了命令模式。本文中使用:开头的命令 ,便可视为输入:进入命令模式后,输入后面的字符,执行命令。
很多人对于vim的第一点疑惑,便来源于此。我们习惯了图形化编辑器下,始终处于插入状态。然而在vim中,大多数情况下,我们会处于正常模式。只有当需要输入字符时,进入插入模式;当需要使用命令时,进入到命令模式。在插入和命令模式下,输入Esc便可返回正常模式。一张图概括如下:
注:后文讲解,如无特殊说明,均为普通模式下操作。
基本操作
如果不追求效率,只想完成修改文件的任务,并保存退出,只需要掌握以下三个命令:
- 移动:
h j k l最简单的移动,相当于键盘上面的方向键,分别对应左下上右。 - 进入插入模式:
i - 保存退出:
ZZ(注意区分大小写)
流程如下:
- 普通模式下,通过
h j k l移动到想要修改的位置 - 输入
i进入插入模式,此时通过输入(字母、数字、符号),删除(Backspace)等,完成基本修改操作 Esc回到普通模式,ZZ,保存修改并退出。
进阶:命令形式
普通模式下,vim的命令主要分为以下三种:
-
动作,用以移动光标,或者定义操作的范围;比如:
h:定义操作范围为一格,单独使用时,向左移动光标一格。w:定义操作范围为一个单词,移动光标到下一个单词首部。
-
操作,这种命令需要在后面接表示操作范围的指令;
d,删除,后接表示一个单词操作范围的w,即dw时,表示删除到当前词尾。c,修改,后接表示一个单词操作范围的w,即cw时,表示修改当前单词。(编辑器行为表现为,删除到当前词尾,同时进入插入模式)。
-
命令,直接执行的命令,其中一部分,在执行命令后,直接进入编辑模式;比如:
D,删除至行末。I,到行首进入插入模式。 我们的使用方式主要也是三种:命令、动作、操作+动作。 此外,在动作类的命令前,加上number为可选项,可实现重复n次的效果:
-
[number] + h/j/k/l向左/下/上/右移动number个字符。比如,'2j',向下移动光标2个字符。 -
依旧使用
d和w来举例,d是删除,w是单词,dw代表删除一个单词,d2w代表删除两个单词。后面的命令,大多都可应用此种形式组合使用,大家多注意,养成这种操作 + [次数] + 范围的思维模式,举一反三,便可发挥最大功效。
移动进阶
单词级别的移动
这里有仅大小写不同的两组命令,两组命令的功能,是相同的:跳转光标到对应位置。但是对应的单位不同,分别为word和string。具体区别是:
-
string仅以空格分开; -
word以字母数字以外的字符分开。以这个字符串为例:
hello world-hehe111 abcde -
word有5个,分别为helloworld,-,hehe111和abcde。 -
string有3个,分别为helloworld-hehe111和abcde。
两组命令如下:(跳转光标至)
-
w下一个单词开头 -
e当前或下一个单词结尾 -
b当前或上一个单词开头 -
ge上一个单词的结尾 -
W下一个字符串的开头 -
E当前或下一个字符串结尾 -
B当前或上一个字符串的开头 -
GE上一个字符串的结尾
举个例子,当光标位于hehe111的第一个字符h时,前后的单词/字符串信息如下:
| 前一个 | 当前 | 后一个 | |
|---|---|---|---|
| 单词 | - | hehe111 | abcde |
| 字符串 | hello | world-hehe111 | abcde |
那么以上各个敲击以上各个命令的结果,便一目了然(加粗字表示命令运行后光标位置):
句子,段落级别的移动
-
0移动到当前行行首 -
^移动到当前行的第一个非空字符 -
$移动到当前行尾 -
(跳转到当前或前一个句子的开头 -
)跳转到当前或下一个句子的结尾 -
{跳转到当前或前一个段落的开头 -
}跳转到当前或下一个段落的结尾 -
这里段落很容易理解,是以空行分隔开的。句子麻烦些,是按照句号来算的。
-
记得在这些命令前添加
d试一下效果吧,掌握操作+范围这种命令形式吧。
页面级别的移动
按行移动光标
gg移动到文本第一行行首G移动到文本末行行首[n] + %:按百分比近似定位到某行,该行位于整个文件的n%处[n] + gg/G跳转到第n行,常用。
要想用好上述几个命令,有两个简单的建议:
- 结合命令:
ctrl-g。该命令的作用是显示当前行的位置信息(第几行,相对整个文本行数的百分比)。 - 在命令模式下输入以下命令,或在
~/.vimrc中添加如下代码片段
set nu " 显示行号
set cursorline " 高亮光标所在行</pre>
显示页面内移动光标
H:屏幕顶部行首M:屏幕中央行首L:屏幕底部行首
滚动与翻页
-
ctrl-d/u:前进/后退半页 -
ctrl-f/b:前进/后退整页 -
ctrl+e:上滚一行 -
ctrl+y:下滚一行 -
zt:使光标所在位置移动到屏幕的顶部(所有内容做位移) -
zz:使光标所在位置移动到屏幕的中央(所有内容做位移) -
zb:使光标所在位置移动到屏幕的底部(所有内容做位移)
匹配
f+单个字符:在本行内向右移动到指定字符F+单个字符:在本行内向左移动到指定字符t+单个字符:在本行内向右移动到指定字符的前一个字符T+单个字符:在本行内向左移动到指定字符的前一个字符%: 在“( )”、“[ ]”、“”类符号的首尾间切换*和#: 匹配光标当前所在的单词,移动光标到下一个(或上一个)匹配单词(*是下一个,#是上一个)。
Mark
m+[a~z]:在当前光标做标记,如ma'+[mark]:光标返回指定标记所在的行,如'a,则光标返回到标记a所在行首- "`"+[mark]:光标返回指定标记
ctrl+o:跳转回光标前一个位置ctrl+i:跳转回较新的光标位置- 建议结合命令模式下如下两个命令,可获得更好体验:
:marks:显示全部mark:delmarks [mark]:删除指定mark
编辑进阶
进入插入模式
在不同位置进入插入模式
i:在光标前插入字符I:在行首插入字符a:在光标后插入字符A:在行尾插入字符o:在光标下发插入空行O:在光标上方插入空行
使用修改命令进入插入模式
-
c:修改,后面需要接范围 -
c+w:删除光标位置单词,并进入插入模式 -
c+l / s:删除光标位置字符,并进入插入模式 -
c+c / S:删除光标所在行,并进入插入模式 -
c+$ / C:删除光标位置到行尾的字符,并进入插入模式 -
r: 替换当前字符。 -
R:(进入replace模式)持续替换光标所在字符,直到使用ESC退出替换模式。