vim 入门笔记——2. 基本使用
前一篇只是 vim 的极简使用,现在正式进入 vim 的学习笔记。
工作模式
vim 包括三种主要模式
- Normal 模式
- Insert 模式
- Command 模式
以及一个临时的 Visual 模式。
启动 vim 会直接进入 Normal
模式,此时的按键不会被视作输入字符,而是视作命令,例如输入i
会切换到
Insert 模式,进行正常的文本编辑状态;输入英文冒号:
会切换到
Command 模式,此时光标会留在最底行,可以输入复杂的命令。
几个模式的转换如下图,Normal 模式作为转换的中枢,在其他模式中可以通过
<Esc>
键可以返回 Normal 模式,也可以使用
<Ctrl+[>
替代(默认情况下,它和<Esc>
键功能完全等价)。
从 Normal 模式出发
光标移动基础
在 Normal
模式中,为了保证操作的高效连贯,我们不希望双手离开主键区,主要使用按键
hjkl
来移动光标:(当然四个方向键也可以)
h
:左移j
:下移k
:上移l
:右移
整个文件尺度的移动:
gg
:移动到当前文件的第一行G
:移动到当前文件的最后一行
按照行号定位:
{lineno}gg
/{lineno}G
:跳转到第lineno
行{percent}%
移动到当前文件对应比例的位置,例如30%
在 Command 模式中,还有如下的命令可以按行跳转(需要回车执行):
:0
移动到当前文件的第一行;:{lineno}
移动到当前文件的第lineno
行;:$
移动到当前文件的最后一行;
屏幕尺度下的移动:
H
:移动到屏幕顶端的行;M
:移动到屏幕中部的行;L
:移动到屏幕底部的行;
翻页:(尽量保持光标在屏幕中的相对位置不变)
<Ctrl-u>
:(up) 将文本上移半页<Ctrl-d>
:(down) 将文本下移半页<Ctrl-b>
:将文本上移一页<Ctrl-f>
:将文本下移一页
光标行定位:
zz
:光标行居中zt
:光标行置于屏幕第一行zb
:光标行置于屏幕最后一行
进入 Insert 模式
从 Normal 模式进入 Insert 模式,常见方法如下:
- 插入:(insert)
i
:在光标所在字符前开始插入(光标所处的字符会被挤到后面);I
:在光标所在行的行首开始插入,如果行首有空格则在空格之后插入。
- 添加:(append)
a
:在光标所在字符后开始插入(光标会自动后移一格);A
:在光标所在行的行尾开始插入。
- 替换:(substitude)
s
:删除光标所在的字符并开始插入;S
:删除光标所在行并开始插入
- 插入新行:
o
:在光标所在行的下面创建新行插入;O
:在光标所在行的上面创建新行开始插入。
大小写命令对应的操作不同,但是普遍具有相关性:
- 如果小写的操作是字符尺度的,那么大写的操作通常是行尺度的;
- 如果小写的操作具有方向性,那么大写通常是相反方向的操作。
进入 Command 模式
Normal 模式下,可以通过 :
进入 Command
模式,此时可以输入命令,例如:
:help
或:h
显示帮助(:h xxx
显示对应条目的帮助):w
保存:q
退出:wq
保存并退出:!{cmd}
:利用shell执行外部命令,支持传递参数,提供一个临时界面展示命令的输出。
在 Command
模式,输入单词开头部分,即可可以使用<Ctrl-d>
获取补全提示,也可以使用tab
获取补全建议。
进入 Visual 模式
Normal 模式下,输入 v
/V
进入 Visual
模式,常见操作:
- 移动光标选中文本进行操作;(
v
以字符为单位,V
以整行为单位) x
:剪切y
:(yank) 复制d
:(delete) 删除p
:(paste) 粘贴- 可以退出到 Normal 模式进行
- 如果直接在选中一部分内容的状态下进行粘贴,会直接覆盖掉当前选中的内容
除了 <Esc>
,再次输入 v
或者某些操作完成后也会自动退出 Visual 模式。
移动 (Motion)
vim 在 Normal 模式下提供了各种快捷键用于快速移动光标,这些按键所绑定的行为称为移动 (Motion)。
基于单词的移动
w
/W
:(word) 移动到(下一处)单词的首字母;b
/B
:(back) 移动到(上一处)单词的首字母;e
/E
:(end) 移动到(下一处)单词的尾字母;ge
:移动到(上一处)单词的尾字母; (e
的反向操作)
大小写版本的 W
/B
/E
区别在于分词逻辑:大写操作只按照空格分词,例如 open-source
在小写操作中视作三个单词(-
也视作一个单词),但是在大写操作中视作一个单词。
基于单词的操作对于中文并不友好,因为单词的分词是简单地基于空格等符号所进行的,中文需要根据语义分词,这一点很难做到,可能会把整个句子视作一个单词。
行内搜索与移动
行内搜索:
f{char}
/F{char}
:跳转到本行的下一个/上一个{char}
字符位置;t{char}
/T{char}
:跳转到本行的下一个/上一个{char}
字符位置之前;;
:继续(或切换为)向后搜索,
:继续(或切换为)向前搜索
注:
- 行内搜索只能基于指定字符,除此之外,vim 还提供了一套支持模式匹配的全局搜索命令,见下文。
;
/,
在跳转时仍然限于本行内部,但是可以通过插件实现跨行跳转。
基于标记的移动
vim 提供了一套标记系统,可以在特定位置打上标记,从而基于标记快速移动:
m{mark}
:在当前位置打一个标记mark
(mark
要求是小写字母,例如mm
)`{mark}
:跳转到到标记mark
内置的特殊标记:
``
:上次跳转前的位置`.
:上次修改的位置`^
:上次插入的位置
在 Normal 模式中,还可以使用 gi
来直接跳转到 Insert
模式中的光标最后位置,并且直接进入 Insert 模式。
基于文本的移动
(
/)
:向前/向后跳转到一个句子的开头{
/}
:向前/向后跳转到一个段落的开头%
:如果光标位于括号等配对符,会跳转到匹配的符号,否则向后跳转到下一个配对符
实用的局部跳转
0
/$
:跳转到当前行开头/末尾(含空格)^
/g_
:跳转到当前行的第一个/最后一个非空白字符+
/-
:跳转到上一行/下一行的第一个空白字符
粘贴
Vim 的粘贴命令为
p
/P
,它们会根据复制内容的类型自动选择进行“字符粘贴”或“行粘贴”,两者的区别是在光标后或光标前:
- 如果复制的是字符或词:
p
:粘贴在光标后P
:粘贴在光标前
- 如果复制的是整行(如使用
yy
或dd
):p
:将复制内容插入到当前行的下方P
:将复制内容插入到当前行的上方
重复与撤销
.
:重复上一次修改(批量操作常用)u
:撤销上一次修改<Ctrl-r>
:重做上一次修改(撤销的相反)
与 u
不同,大写的 U
对应的撤销更加彻底:恢复某一行进入编辑时的状态,这也意味着重复按
U
无效。
全局搜索匹配
文件中搜索:(pattern
可以是正则表达式)
/{pattern}
:搜索模式{pattern}
,并跳转到匹配的下一个位置;?{pattern}
:搜索模式{pattern}
,并跳转到匹配的上一个位置;n
:继续(或切换为)向后搜索N
:继续(或切换为)向前搜索*
:自动以当前光标所在单词为pattern
,向后搜索
进阶
重复移动
在移动前面加上数字就可以重复多次移动。 1
[count]{motion}
例如
5j
:向下移动 5 行;5k
:向上移动 5 行;2w
:向右移动 2 个单词;
Operator + Motion = Action
操作符和移动可以组成的一个完整编辑动作,移动前后的光标所组成的就是这次编辑所对应的范围。
1
{operator}{motion}
常见的重要操作符:
c
:(change) 修改(删除并进入 Insert 模式)d
:(delete) 删除y
:(yank) 复制v
:(visual) 选中文本,进入 Visual 模式
这里并没有剪切操作,因为 vim 实现的删除操作其实就是剪切,它会把删除内容记录下来,可以被用于粘贴。
在操作符后面加上移动即可组成完整命令,例如:
dgg
:删除到第一行ye
:复制到单词结尾d$
:删除到行尾dt;
:删除到遇到分号;
如果不确定
{motion}
的作用范围,可以先尝试v{motion}
,再执行c
/d
/y
操作。
重复两次操作符通常是作用在当前行:
cc
:修改当前行(删除并进入 Insert 模式)dd
:删除当前行yy
:复制当前行
但是 vv
会进入 Visual 模式然后退出。
由于历史兼容性等原因,这几个操作符的大写含义为:
C
=c$
:修改到行尾D
=d$
:删除到行尾Y
=yy
:复制整行(注意不是复制到行尾)
Count + Action
[count]{action}
代表重复 {action}
行为
[count]
次,这里的 {action}
也可以进一步展开,变成
1 | [count]{operator}{motion} |
例如:
5j
:向下移动5行3dw
:删除3个单词2yy
:复制2行4p
:粘贴4次
这里的组合方式其实非常灵活,例如 {motion}
通常也可以换成
[count]{motion}
,例如:
3dw
解释为dw
(删除到单词末尾)且重复3次;d3w
解释为为按照3w
的移动范围进行删除。
两者效果是一样的。
文本对象及其操作
vim 将如下文本结构视作文本对象:
- 单词:
w
/W
(word)(两者区别是单词的定义) - 句子:
s
(sentence) - 段落:
p
(paragraph) - 配对符定义的对象:
(
/)
,[
/]
,{
/}
,<
/>
,'
/"
有两种基本格式:
i
:(inner) 内部a
:(around) 完整对象,额外包括边界的空格或两边的配对符
⽂本对象使⽂本具有了结构化的语义,进而允许我们以语义对象为操作单元,进行更具体的操作。
1 | [count]{operator}{textobjects} |
例如:
diw
:删除单词ci(
:修改小括号内部yi{
:复制大括号内部
但是这里的 {textobjects}
不能独立使用,而且重复数量只能加在 {operator}
前面。
如果不确定
{textobjects}
的作用范围,可以先尝试v{textobjects}
,再执行c
/d
/y
操作。
补充
命令补充:
~
:大小写翻转J
:拼接两行r
:快速替换单个字符R
:进入字符替换的模式(<Esc
退出)
操作符补充:(操作符不能单独使用,这里的 g
也不能单独使用)
gu
/gU
:转换为小写/大写g~
:大小写翻转<
/>
:调整缩进(例如>>
和<<
调整当前行的缩进)
vim 支持 bash 中常见的几个删除操作(甚至是在 Insert 模式下也支持!):
<Ctrl+u>
:删除至行首<Ctrl+w>
:删除光标前的单词<Ctrl+h>
:删除光标前的字符(与<Backspace>
相同)
vim 有着非常详细的操作历史记录:
- 使用
q:
可以查看 Command 模式的历史记录。 - 使用
q/
可以查看 Search 模式(正则匹配)的历史记录。
这些历史记录以及寄存器内容等会被存储在 .viminfo
文件中,再次打开 vim 时,这些内容会自动恢复。