vim入门笔记
vim 被称为编辑器之神,学习难度很大,但是熟练掌握后可以更高效地敲代码,因此学一下。
安装与配置文件
vim 默认是命令行版本的,而 gvim 是 GUI 版本的 vim,这里我们使用的是 Git for Windows 里面附带的 vim(不含 GUI),可以按 Linux 风格进行配置和使用,感觉比直接下载Vim 官网的 Windows 版的 gvim 更方便,便于直接把配置应用到到 Linux 服务器上。
在 vim 中输入:version
可以查看很多信息,例如
1 | // vim的版本号 |
还有一个列表描述了当前编译的 vim
支持或不支持的功能列表,例如+clipboard
意味着剪贴板功能被编译支持了,-clipboard
意味着剪贴板特性没有被编译支持。
打开和关闭,保存
在命令行直接输入vim filename
即可打开或新建指定的文件:
- 对于已存在的文件会打开它;
- 对于不存在的文件,会创建一个临时文件,如果退出时选择保存,则会真实地创建该文件。
注意,如果直接输入vim
,不接文件名,则 vim
会给出如下的欢迎界面——帮助乌干达的贫困儿童。
其中行首的~
占位,表示该行不存在。
在编辑完成之后,退出 vim
的操作首先要明确所处的模式,假设当前处于命令模式中(输入:
会进入底线命令模式),有如下几种退出方式:
:q
直接退出(quit),只适合于当前文件没有被改动时,如果文件有改动,则会报错无法退出,因为必须处理对文件的修改;:wq
保存并退出(write and quit),也可以拆成两个命令:保存:w
,退出:q
;:q!
加感叹号表示强制退出,如果不希望保存文件的改动,则可以强制进行不保存的退出。
使用:x
也可以保存并退出,而且和:wq
相比有细微的差别,它仅仅会在文件真正改动时才写入文件。
使用:w newfilename
可以把改动另存为新的文件。
使用:w n1,n2 newfilename
可以把 n1 行到 n2
行的内容截断存储到新的文件中。
对于不熟悉 vim 的用户,几乎不可能体面地关闭 vim,不管你按什么按键。一个冷笑话是:如何生成一串完全随机字符串? 让新手退出 vim。
工作模式
vim 主要包括三种模式:
- 命令模式(Command mode)
- 插入(编辑)模式(Insert mode)
- 底线命令模式(Last line mode)
启动 vim
会直接进入命令模式,此时的按键不会被视作输入字符,而是视作命令,例如输入i
会切换到插入(编辑)模式,进行正常的文本编辑状态(下方会显示-- INSERT --
);输入英文冒号:
会切换到底线输入模式,此时在最底行输入复杂命令(命令模式只支持一些基本的命令)
三个模式的转换如下图,其中命令模式相当于中枢,其他模式按 Esc 键会返回命令模式。
vim 的命令繁琐比较难记,有很多类似的速查图帮助记忆:
不论在命令模式还是编辑模式,在打开的文本中都存在一个可移动的光标,从命令模式变成编辑模式,有如下几种方法:
- 插入:
i
在光标所在字符前开始插入(光标所处的字符会被挤到后面);I
在光标所在行的行首开始插入,如果行首有空格则在空格之后插入。 - 添加:
a
在光标所在字符后开始插入(光标会自动后移一格);A
在光标所在行的行尾开始插入。 - 删除插入:
s
删除光标所在的字符并开始插入;S
删除光标所在行并开始插入
大小写的操作都是相关的,小写的操作通常是字符尺度的,大写的操作通常是行尺度的。
此外还有:o
在光标所在行的下面创建新行插入;在光标所在行的上面创建新行开始插入。
光标移动
不论是在命令模式还是编辑模式,都可以使用上下左右方向键来移动光标。 在底线命令模式中,光标锁定在底线等待复杂命令的输入,可以左右移动调整光标,也可以上下翻页命令的历史记录。 但是在命令模式中,我们不希望离开主键区,使用下面的 4 个按键来移动光标
h
左移;j
下移;k
上移;l
右移;
可以配合数字使用,例如nh
代表光标左移 n
个字符,nj
代表光标下移 n
行(如果目标行足够长,则保持列数不变,长度不足时则变成行尾,行数不足时停在文件尾行)。在命令模式中,还可以使用gi
来直接返回在编辑模式中最后的光标位置,直接以插入的方式进入编辑模式。
光标可以在当前行快速移动:
0
移动到当前行首;$
移动到当前行尾;w
移动到(下一个)单词的首字母;(可以使用nw
一次性移动 n 个单词)e
移动到(当前)单词的尾字母;(可以使用ne
一次性移动 n 个单词)n<space>
数字加空格,光标向后移动 n 个字符;(相当于nl
)n<enter>
数字加回车,光标向下移动 n 行到达非空字符位置;(相当于nj
)
0
和$
在vim的很多操作中都具有开头和结尾的语义。
可以根据非空字符来移动光标:
^
移动到当前行的第一个非空字符;+
(shift
+=
) 移动到上一行的非空字符位置;-
移动到下一行的非空字符位置;
可以在整个文件中移动:
- 命令模式中
gg
移动到当前文件的第一行;ngg
或nG
移动到当前文件的第 n 行;G
移动到当前文件的最后一行;n%
移动到当前文件对应 n 比例的位置,例如30%
- 底线命令模式中,还有如下的命令(需要加回车来执行):
:0
移动到当前文件的第一行;:n
移动到当前文件的第 n 行;:$
移动到当前文件的最后一行;
可以在屏幕尺度下进行移动:
H
移动到屏幕顶端的行;M
移动到屏幕中部的行;L
移动到屏幕底部的行;
还有:
ctrl+u
和ctrl+d
:保持光标在屏幕中的相对位置,将文本上移和下移,移动行数约为屏幕显示行数的一半;zz
,zt
和zb
:将光标所在的行移动到屏幕中间,顶部和底部。(如果位置允许的话)
常用功能
在命令模式下,支持如下的撤销操作:
- 撤销功能
u
(undo) - 撤销对整行的操作
U
- 重做
ctrl+r
- 重复当前动作
.
(句号)
注意:在命令模式下,backspace 键仅仅是光标的回退而不会删除字符,enter 键也不会换行
删除:(理解为剪切也可以)
- 删除光标所在的字符
x
,连续删除 n 个字符nx
- 删除光标之前的一个字符
X
- 删除一整个单词
dw
,删除连续的 n 个单词ndw
(dnw
好像也一样) - 删除直到当前单词的尾部
de
(和dw
很类似,但是不包括单词尾部的空格) - 删除光标所在的一整行
dd
,删除(向下的)连续的 n 行ndd
- 删除光标之前的(当前行)所有字符
d0
- 删除光标字符以及之后的(当前行)所有字符
d$
- 删除光标所在行直到文件末尾行的所有字符
dG
- 删除光标所在行直到文件开头行的所有字符
d1G
替换:
- 替换当前字符为
<a>
:r<a>
- 连续替换多个字符:
R
(逐个输入进行替换,直到esc) - 删除直到当前单词结尾,并进入插入模式:
cw
- 删除直到当前行结尾,并进入插入模式:
c$
复制:
- 复制当前字符
y
- 复制整行
yy
或Y
,复制(向下的)连续的 n 行nyy
- 复制光标之前的(当前行)所有字符
y0
- 复制光标字符以及之后的(当前行)所有字符
y$
- 复制光标所在行直到文件末尾行的所有字符
yG
- 复制光标所在行直到文件开头行的所有字符
y1G
粘贴:
- 把复制(或删除)的字符片段粘贴到当前行之后
p
(小写) - 把复制(或删除)的字符片段粘贴到当前行之前
P
(大写)
查找:
/abc
向后查找 abc 字符串?abc
向前查找 abc 字符串n
继续(或切换为)向后搜索N
继续(或切换为)向前搜索
查找替换:
:s/abc/xyz
替换当前行的 abc 字符串为 xyz(仅替换第一个匹配项):s/abc/xyz/g
替换当前行的 abc 字符串为 xyz(g
代表替换所有匹配项):%s/abc/xyz/g
替换所有行的 abc 字符串为 xyz(%
代表针对当前文件的所有行):%s/abc/xyz/gc
替换所有行的 abc 字符串为 xyz(c
代表交互式确认每一处的替换,可以执行、跳过或退出):10,20s/abc/xyz/g
替换指定范围内(两个数字代表起止行号)的 abc 字符串为 xyz
括号匹配:将光标放在括号上,使用%
可以自动跳转到匹配的括号。
执行外部命令::!<cmd>
可以利用shell执行外部命令,支持传递参数,提供一个临时界面展示命令的输出。
插入文件内容::r <file>
可以直接将指定文件的内容插入到当前位置。
缩进:>>
和<<
可以对当前行或选择的多行设置缩进。
可视模式:v
进入可视模式,选择要复制或处理的内容,光标移动会显示选中效果,使用V
进入的是整行操作的可视模式。
对于选中的片段可以进行很多操作:
- 输入
:
(会自动补充为:'<,'>
)和w filename
可以另存到文件中。 - 输入
y
可以复制选择的内容 - 输入
d
可以删除选择的内容
获取帮助:
:help <cmd>
可以获取指定命令的帮助,例如关于按键的;:xxx
输入一些单词后可以使用ctrl+d
获取命令补全提示。
补充:使用q:
可以查看命令行的历史记录;使用q
会开启宏录制,用于简化重复操作,暂时用不上,再次按q
退出录制宏。
配置与配置文件
我们可以设置显示绝对行号:set number
(或者简写为:set nu
),效果如下图
可以设置:set nonumber
关闭行号。(一般的配置项都可以通过加no
前缀来取消)
可以使用:set number?
来查询当前行号是开启还是关闭的,会显示number
或nonumber
。(一般的配置项都可以通过加?
查询状态)
还可以设置显示相对行号:set relativenumber
,光标所在的行记作
0,上下相邻的行记作 1,以此类推,效果如下图
绝对行号和相对行号可以同时出现,效果如下图
:set cursorline
可以高亮光标所在的行,这里的高亮有可能是改成红色背景,有可能是整行添加下划线。
:set filetype=c
(:set ft=c
)可以设置文件类型,默认情况下可以自动识别文件类型。
:! command
可以暂时返回命令行界面执行指令,然后回车可以回到
vim,常用:! ls
快速查询目录。
:set nocompatible
可以不兼容 vi
的操作命令,默认开启。
:set showmode
可以提示当前是命令模式还是插入模式,默认开启。
在底线命令模式中,可以输入相关的设置命令,但仅仅对于当前窗口有效,如果希望在每次打开
vim
时都自动采用某些设置,则应该写入配置文件中,配置文件的位置和优先级可以通过:version
查找,通常用户自定义的配置文件为~/.vimrc
(对于
Windows 的
gvim,可能叫做_vimrc
)。在配置文件中,以双引号"
开头的行被视作注释。
vim 的内容实在是太多了,包括丰富的插件系统,可以实现各种个性化的功能,最终甚至达到一个 IDE 的效果,但是我现在并不需要,只是轻量级的使用,因此入门的笔记就到此为止了。
不使用插件的纯净vim配置文件存放在fenglielie/dotfiles仓库,注意.vimrc
配置文件的回车不是
CRLF 而是 LF。
与外部的复制粘贴
vim本身有自己的复制粘贴机制,非常复杂不想讨论。
有的版本还支持与Linux系统的剪切板进行交互,但是需要一些配置,而且系统自带的版本通常都不支持,可以用下面的命令查看支持情况
1
vim --version | grep clipboard
对于文本文件的大段复制,还是直接用less查看,然后用鼠标进行选择复制算了,比较省事。对于文本文件的大段粘贴,如果直接ctrl+v
会出现很多异常:
- 例如如果当前不是insert模式,那么在开头的部分字符可能会被丢弃,直到出现
i
或a
等字符才会生效。 - 例如vim可能产生异常的缩进,还可能将某些行自动注释掉。
这是因为vim将字符流视为用户从键盘进行的输入行为。可以通过下面的选项将vim设置为粘贴模式,此时就可以保持原样进行粘贴
1
:set paste
在执行ctrl+v
之前,最好让vim保持在如下模式
1
-- INSERT (paste) --
在粘贴完成后关闭这个选项即可 1
:set nopaste