复制,粘贴,删除(相当于剪切)

y  - yank
yy - 复制当前行(yank)

p  - paste
P  - 在光标上一行paste
x  - 向后删除当前字符
X  - 向前删除字符
dd - 删除当前行(delete)

复制y,删除d都可以与移动命令结合,比如:

y^
y$
yw
ynw
yG
ynG - 复制到第n行

直接移动和拷贝:

:n1,n2 co n3 将n1行到n2行之间的内容拷贝到n3行下
:n1,n2 m n3 将n1行到n2行之间的内容移动到n3行下

使用特定的寄存器中:

"ay     拷贝到a寄存器
"ap     粘贴a寄存器中的内容

ctrl+r  inset text from a register

各种插入

i   - (insert)
I   - 在本行第一个字符前插入
a   - (after)
A   - 在行末尾插入, 比如A;
o   - 向下插入一行
O   - 向上插入一行
r   - 替换一个字符
R   - 从当前位置连续替换字符
s   - 清除一个字符插入
S   - 清除一行内容插入
c0  - 在当前光标删除到行首并插入
c$  - 在当前光标删除到行尾并插入
cNw - 删除N个词后插入
cc  - 清除一行插入(可缩进到适当位置)
C   - 删除光标后的内容后插入

对括号,引号,标签内容的操作

i代表inner

di{ - 删除{}里所有的代码
di( - 把()清空为()
di[ - 清空[]
di<
di"
di'
di`
dit - 删除一对html/xml的标签内的所有字符

将i换为a可以在操作时包含两边的标签,a代表around

da{ - 删除{}和它里面的所有东西

d代表delete,c代表change,用c代替d会在删除之后进入插入模式

d换为v, y可以完成选定和复制

vi{ - 选定
yi{ - 复制

还可以对单词进行操作

caw - 删除当前单词并进入到插入模式

缩进

>>  - 向右给它进当前行
<<  - 向左缩进当前行
=   - 缩进当前行(和上面不一样的是,它会对齐缩进)

可以和移动配合,比如:

=%   - 把光标位置移到语句块的括号上,然后按=%,缩进整个语句块(%是括号匹配)
gg=G - 缩进整个文件(G是到文件结尾,gg是到文件开头)

还原操作

Vim使用tree数据结果来存储内容变更的历史记录,而不是采用queue。你的每次改动都会成为存储为树的节点。而且,除了第一次改动(根节点),之后的每次改动都可以找到一个对应的父节点。每一个节点都会记录改动的内容和时间。其中,「分支」代表从任一节点到根节点的路径。当你进行了撤销操作,然后又输入了新的内容,这时候就相当于创建了分支。这个原理和 git 中的 branch(分支)十分类似。

考虑以下这一系列按键操作:

ifoo<esc>
obar<esc>
obaz<esc>
u
oquux<exc>

那么现在,Vim 中会显示三行文本,分别是 “foo”、”bar” 和 “quux”。这时候,存储的树形结构如下:

     foo(1)
       /
    bar(2)
   /      \
baz(3)   quux(4)

这个树形结构共包含四次改动,括号中的数字就代表时间顺序。

现在,我们有两种方式遍历这个树结构。一种叫「按分支遍历」,一种叫「按时间遍历」。

按分支遍历,沿父节点进行,比如我们现在在quus分支,那么我们无法到baz分支:

:undo [count]
[count]u           - 撤销操作
U                  - 回退至最新的改动

:redo [count]
[count]ctrl+r      - 恢复撤销

按时间遍历:

:earlier [count]?  - ?可以是s, m, h, d, f
[count]g-          - 撤销操作(按时间遍历)

:later [count]?
[count]g+          - 恢复撤销(按时间遍历)

:h undo.txt

关键字补全

在insert模式下,我们可以按如下快捷键:

<c-n>        - Vim会向下搜索已打开缓冲区的代码
<c-x><c-n>   - Vim会向下搜索当前缓冲区的代码
<c-p>        - Vim会向上搜索已打开缓冲区的代码
<c-x><c-p>   - Vim会向上搜索当前缓冲区的代码

接下来我们可以使用Ctrl PCtrl N上移或下移光标进行选择,也可以回到你写的词继续输入来帮助过滤关键词。

<c-y>      - 确认当前补全项

与此类似的,还有更多的补齐,都在Ctrl X下面:

<c-x><c-]> - 标签补齐(使用ctags)
<c-x><c-l> - 对整个行补齐
<c-x><c-f> - 文件名 补齐
<c-x><c-p> - context-aware word completion
<c-x><c-n> - keywords in the current file
<c-x><c-k> - 字典补全 (执行:set dictionary+=[字典文件] 设置字典)
<c-x><c-d> - 定义或宏定义补齐
<c-x><c-i> - keywords in the current and included files
<c-x><c-v> - vim command-line

<c-x>s     - 拼写建议

<c-x><c-u> - 用户自定义补全(通过`completefunc`定义)

<c-x><c-o> - omni completion(通过`omnifunc`定义)

vim 提供默认的 omnifunc,定义在 autoload 目录下,可以用 :set omnifunc? 查看当前的 omnifunc

completeopt 配置补全选项,使用 :help completeopt 查看可选的值,以下是我的配置:

" 不加 preview,否则在补全列表中选择时会弹出 preview window 显示当前项的额外信息,这会打乱当前窗口布局
" 增加 noselect,不要选择第一个选项,ctrl-n 之后跳到第一项,否则会到第二项
set completeopt=menu,menuone,noselect,noinsert
" 增加 popup,在补全列表中选择时会弹出 popup window 显示当前项的信息(vim8.2 之后支持,preview 的替代方案)
if has('popupwin')
    set completeopt+=popup
endif

complete 配置关键字补全范围/源,使用 :help complete 查看可选的值

:help CTRL-X, :help i_CTRL-Y :help i_CTRL-X_CTRL-O

:help ins-completion 查阅所有以 开头的快捷键说明

:help complete-functions 查阅如何编写 omnifunc 或者 completefunc 的方法

字符相关

guu - 把一行的文字变成全小写
gUU - 把一行的文件变成全大写
按v键进入选择模式,然后移动光标选择你要的文本,按u转小写,按U转大写
gU - 变大写
gu - 变小写
ga - 查看光标处的ascii码
g8 - 查看光标处的utf-8编码
ctrl+a - 把光标下的数字加1
ctrl+x - 把光标下的数字减1