引言

2013 年的时候我才开始接触 Vim,简单学了一下,也没用起来,后来只记得普通模式以及怎么进入插入模式,然后就是保存退出这几个命令了。

直到最近买了一个 HHKB 键盘以及发现使用 Vim 编码效率要高很多,所以我决定重拾 Vim,为了加强自己的记忆,于是我就整理了这篇文章。

模式

这个是 Vim 区别普通编辑器的最大差别。Vim 有好几种模式,在不同的模式下可以干不同的事情。

普通模式

这个是 Vim 的默认模式,在这种模式下,你可以通过键盘移动光标,可以删除文字。

方向键

  • h:左 ←
  • j:下 ↓
  • k:上 ↑
  • l:右 →

这几个是最常用的方向键盘,怎么记呢?除了记住『j 长得有点像 ↓』之外就是勤加练习了。

其他

  • w:移动到下一个单词的开头
  • e:移动到下一个单词的结尾
  • 0:移动到行首
  • $:移动到行尾
  • b:移动到上一个单词的开头
  • gg:移动到文件的开头
  • G:移动到文件的结尾
  • nG:移动到第 n 行
  • dd:删除当前行
  • d$ 或者 D:删除当前光标到行尾
  • d0:删除当前光标到行首
  • yy:剪切当前行
  • p:粘贴内容到下一行
  • v$yjp:选中光标到行尾内容,跳转下一行粘贴内容

插入模式

专门用来插入文字的模式,你可以把其他编辑器的默认模式理解为 Vim 的插入模式。

如何从普通模式进入插入模式?

  • i:在光标之前插入(insert 插入)
  • a:在光标之后插入(append 追加)
  • I:在光标行行首插入
  • A:在光标行行尾插入
  • o:在光标行下面插入新一行并且保持插入模式
  • O:在光标行上面插入新一行并且保持插入模式

除了以上命令我们还可以使用 c 命令进入插入模式:

  • cc:删除当前行内容,并且进入插入模式
  • c$ 或者 C:删除当前光标到行尾,并且进入插入模式
  • cw:从光标处删除到单词结尾并且进入插入模式
  • caw:删除整个单词并且进入插入模式(即使你的光标在单词中间)

如何回到普通模式?

Esc 键最方便。

可视模式

可以理解为选中模式,通过一些命令选中字符、行、块,再针对选中区域做操作。

普通模式和可视模式可以这样互相切换

  • v:切换面向字符的可视模式
  • V:切换面向行的可视模式
  • Control + v:切换面向块的可视模式(当你需要对几行字符做相同操作的时候,这种模式非常有用)

相关命令

  • gv:进入上次可视模式状态
  • o:切换选中区域的活动端(试一下 vwwoe 自己感受一下)

实际场景示例

  • vi'c:从当前光标位置删除 ' 之前的内容,并且进入插入模式
  • vi}:选中 {} 之间的内容,同理 } 可以换成 '"] 等(i 可以立即为 inside)
  • va}:选中 {} 以及其之间的内容,同理 } 可以换成 '"] 等(a 可以理解为 around)
  • vit:选中两个标签之间的内容
  • viw:选中当前字符
  • viW:选中当前字串(字串含义见后面内容)

更多可以参考下图,来源《VIM 学习笔记 文本对象(Text Objects)》

命令行模式

进入命令行模式之后我们可以执行一些命令对文本进行操作。

进入命令行模式

  • ::进入命令行模式
  • /:向下进行搜索,按 n 跳转到下一个,按 N 跳转到上一个
  • ?:向上进行搜索,按 n 跳转到下一个,按 N 跳转到上一个

一些常用的命令

  • :x:保存并且退出
  • :wq:保存并且退出
  • :w:保存
  • :q:退出
  • :0:跳转到文件头,0 代表行号
  • :t:复制,把一行或者多行复制到指定位置
  • :m:移动,在用法上和复制类似
  • < 或者 >:缩进或者反缩进

一些示例

  • :2,3t.:把第 2 和 3 行的内容复制到当前光标行下方
  • :2,.t5:把第 2 行到当前光标行复制到第 5 行下方
  • :2m.:把第 2 行移动到当前行下方
  • :t5:把当前行复制到第 5 行下方
  • :t$:把当前行复制到最后一行
  • :t.:把当前行复制到下一行,同 yyp
  • :%s/echocai/forecho:把当前文件每行第一个 echocai 替换为 forecho
  • :%s/echocai/forecho/g:把当前文件的所有 echocai 替换为 forecho
  • :'<,'>s/field/echo:把当前高亮区域中所有的 field 替换为 echo (高亮区域可以事先通过 Vjjj 选中,再输入 : 的时候,会自动输入 '<,'>
  • :![cmd]:运行 shell 命令(示例::!pwd:!ls
  • 10<<:缩进 10 行,10>>:反缩进 10 行

移动光标

这个是非常常用的功能,在普通模式下我们除了使用 hjkl 移动外,我们还可以:

  • Control + d:向下滚动半屏幕
  • Control + u:向上滚动半屏幕
  • gg:跳转到文件头部
  • 12gg:跳转到第 12 行
  • G:跳转到文件末尾
  • f{char}:行内搜索,跳转到下一个{char}所在的位置上(示例:fx 跳转到下一个 x 所在的位置)
  • F{char}:行内搜索,跳转到上一个{char}所在的位置上。(示例:Fx 跳转到上一个 x 所在的位置)
  • t{char}:行内搜索,跳转到下一个{char}的前一个位置上。(示例:光标在行首的时候,在有 ActiveForm 的行内使用 tc 跳转到 A 所在的位置)
  • T{char}:行内搜索,跳转到上一个{char}的前一个位置上。
  • w:跳转到下一个单词的第一个单词上
  • b:跳转到上一个单词的第一个单词上
  • e:跳转到下一个单词的最后一个单词上
  • ge:跳转到上一个单词的最后一个单词上
  • zz:让光标处于屏幕正中间,不会移动光标。

上面的 wbe 都有对应的大写 WBE,区别就是大写范围更大。小写范围是单词(word),大写范围是字串(WORD),区别:

  • 单词(word):由数字、字母、下划线或者其他非空白字符串组成
  • 字串(WORD):以空白字符串分割

另外在使用 fFtT 命令的时候,要注意:

  • 尽量找低频字母
  • ;:重复上一次行内搜索,可以理解为跳转到下一个目标位置
  • ,:撤回上一次行内搜索,可以理解为跳转到上一个目标位置

动作

动作是指再普通模式下执行的一些行为,需要跟其他指令一起使用。最常用的有这些:

  • d:删除
  • c:删除并且进入插入模式
  • r:替换,在普通模式下替换一个字符,比方说把光标移动 t 上,按下 rT 会直接把 t 替换为 T 并且还处于普通模式下
  • R: 进入替换模式,会替换光标所在的文字,直到按 Esc 为止
  • x:普通模式下删除一个字符,保持普通模式
  • u:撤销操作
  • Control + r:重做

以上这些动作都可以用数字或者其他指令组合,一些示例:

  • daw:即使你处于单词中间,你也可以通过这个命令把整个单词删除。
  • 4dddd 是删除一行,4dd 是删除 4 行

宏录制

Vim 的录制宏是一个非常强大的功能,当我们需要对一些重复的操作进行批量处理的时候,可以使用宏来完成。比方说,我们需要下面每行文字都用双引号包起来,并且在结尾加上逗号

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
972ea750-3ff7-48a0-b7b9-9e07532765e
97303b94-e378-4c70-9cfe-9a2d1781b67
973085e8-0c6a-487a-8e95-5f217f79b39
963b60c9-a441-44cf-a7f0-eecda25bb50
96d3a702-ff06-42d5-996e-ab0349f4d3b
9736e7da-aaa1-4368-8a27-90442a13da0
9739b00e-caa5-4628-a870-5e71e1eefd6
973d3fd4-7a2b-4d75-8ba8-596856a0e8c
963b6240-e78a-41bf-9e84-601f7218535
969df9b8-4d30-4ada-9c04-276a3e11aed
9747ade0-efc3-466d-84f8-6fc51c212a6
9747c63e-59b2-4232-8518-658bb339bc4
9747c73b-a341-4bcd-b474-205fe3b5255
9747c7b5-fc70-4532-ab6c-31193c84447
9747c817-bad5-43d6-95cd-b13243cfd2a
9747cc8a-e236-4ea6-b38e-a3effe1b90b
9747d202-3332-40e0-b7c5-46626df88a8
9747dccf-6ef7-4fe8-9e31-74d69e0b8b8
9747ddf8-a243-4c5d-adf4-ad1c0879244

不用 Vim 宏录制功能的话,我一般用 Sublime Text 的批量选中(按住 Option 然后按住鼠标往下拉就能批量选中),然后批量操作来完成。

要处理的行数比较少,这种方式还挺快的。但是遇到要处理几百甚至几千行,这种方式就不太适合了。这时候就可以用 Vim 的宏录制功能来完成了。

宏录制的功能你可以理解为记录一系列按键操作,然后批量「播放」执行。

宏录制步骤:

  • 普通模式下 q + a,然后开始录制,这里的 a 是宏的名字,可以是任意字母或者数字
  • 开始正常的 Vim 操作,比方说移动光标,删除,插入等等。这里需要注意的是不能用方向键移动光标,只能用 hjkl 或者 w 等移动光标的命令
  • 普通模式下 q,结束录制。如果是批量操作行,记得在结束之前要按一下 j 换行

宏使用步骤:

普通模式下 @ + a,这里的 a 是你之前保存的宏的名字,100 行的话,按一下 100@a 就可以了,依次类推。

实战

上面的需求,我们可以用下面的宏来完成:

  • 开始录制:Esc + q + 1
  • 具体操作:0 + i + " + Esc + A + " + , + Esc + j + q 这个操作可以用宏来完成,具体操作如下:
  • 执行宏:Esc + 18@1

配置 Vim

插件

安装插件有几种方式,我是使用的是 pathogen.vim 的方式,方法:

1
2
3
mkdir -p ~/.vim/autoload ~/.vim/bundle && \
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
vim ~/.vimrc

然后插入:

1
2
3
execute pathogen#infect()
syntax on
filetype plugin indent on

下面推荐几个插件

vim-abolish

转换单词,示例:

  • crm:把下划线风格转换成大驼峰风格(foo_bar 转换为 FooBar
  • crc:把下划线风格转换成小驼峰风格(foo_bar 转换为 fooBar
  • crs:把小驼峰风格转换成下划线风格(fooBar 转换为 foo_bar
  • cru:转化为下划线分割全大写风格
  • cr-:转化为小写中划线分割风格
  • cr.:转化为小写点分割风格
  • cr.:转化为小写点分割风格
  • cr.:转化为小写点分割风格
  • 其他功能看文档吧

安装

1
2
cd ~/.vim/bundle
git clone git://github.com/tpope/vim-abolish.git

ybian/smartim

自动切换输入法,保证回到普通模式的时候是英文输入法。

安装

1
2
3
cd ~/.vim/bundle
git clone git@github.com:ybian/smartim.git
im-select

如果不是 com.apple.keylayout.US 就要修改设置:

1
vim ~/.vimrc

添加这行

1
let g:smartim_default = 'com.apple.keylayout.ABC'

最后

Vim 要了解 Vim 的哲学,学 Vim 带来的收益我认为是指数增长的,但是绝对是值得的,虽然现在很少有人直接在终端用 Vim 写代码,但是几乎所有的编辑器都可以开启 Vim 模式了。

《Vim 实用技巧 第二版》这本书我还没看完,所以本篇文章会持续更新。

参考链接