Vim - oceanbei333/leetcode GitHub Wiki
[TOC]
Vim是从vi发展出来的一个文本编辑器。
对于大多数用户来说,Vim有着一个比较陡峭的学习曲线。这意味着开始学习的时候可能会进展缓慢,但是一旦掌握一些基本操作之后,能大幅度提高编辑效率。
- 普通模式(Normal mode)
在普通模式中,用的编辑器命令,比如移动光标,删除文本等等。这也是Vim启动后的默认模式。这正好和许多新用户期待的操作方式相反(大多数编辑器默认模式为插入模式)。
- 插入模式(Insert mode)
在这个模式中,大多数按键都会向文本缓冲中插入文本。大多数新用户希望文本编辑器编辑过程中一直保持这个模式。
- 可视模式(Visual mode)
这个模式与普通模式比较相似。但是移动命令会扩大高亮的文本区域。高亮区域可以是字符、行或者是一块文本。
当执行一个非移动命令时,命令会被执行到这块高亮的区域上。
- 选择模式(Select mode)
这个模式和无模式编辑器的行为比较相似(Windows标准文本控件的方式)。这个模式中,可以用鼠标或者光标键高亮选择文本
- 命令行模式(Command line mode)
在命令行模式中可以输入会被解释成可执行的文本。例如执行命令(
:
键),搜索(/
和?
键)或者过滤命令(!
键)。在命令执行之后,Vim返回到命令行模式之前的模式,通常是普通模式。
- Ex模式(Ex mode)
这和命令行模式比较相似,可以一次执行多条命令
按键 | 说明 | |
---|---|---|
h |
左 | |
l |
右(小写L) | |
j |
下 | |
k |
上 | |
w |
移动到下一个单词 | |
e | 移动到当前/下一单词的结尾 | |
b |
移动到上一个单词 | |
ge | 反向移动到上一单词的结尾 |
动作可以用数字搭配使用,n动作
4j
u键会触发撤销命令,它会撤销最新的修改。
一次修改可以是改变文档内文本的任意操作,其中包括在普通模式、可视模式以及命令行模式中所触发的命令,
而且一次修改也包括了在插入模式中输入(或删除)的文本,
因此我们也可以说,i{insert some text} 是一次修改。
. 善用重复
操作符是对某个区域文本执行的操作。比如,d
、c
、gU
和 >
都是操作符。这些操作符既可以在普通模式下使用,也可以在可视模式下使用。
操作符+动作=操作
dj 删除当前行以及上面一行
dl 删除左边一个字符
也可以配合数字使用
3dj或者d3j
操作符也可以和文本对象搭配使用
操作符+文本对象
文本对象操作一般用 i
或 a
加上对象标识符操作,其中 i
表示在对象内(英文 inner)操作,a
表示对整个对象(英文 around)操作,这时开头和结尾的空格都会被考虑进来。举个例子,diw
可以删除当前单词,ci(
可以改变括号中的内容。
文本对象同样可以与数字搭配使用。比如,像 ((( )))
这样的文本,假如光标位于最内层的括号上或最内层的括号内,那么 d2a(
将会删除从最内层开始的两对括号,以及他们之间的所有内容。其实,d2a(
这个操作等同于 2da(
。
Vim的语法只有一条额外规则,即当一个操作符命令被连续调用两次时,它会作用于当前行。所以 dd 删除当前行,而 >> 缩进当前行
命令 | 说明 |
---|---|
x |
删除游标所在的字符 |
X |
删除游标所在前一个字符 |
Delete |
同x
|
dd |
删除整行 |
dw |
删除一个单词(不适用中文) |
d$ 或D
|
删除至行尾 |
d^ |
删除至行首 |
dG |
删除到文档结尾处 |
d1G |
删至文档首部 |
命令 | 说明 |
---|---|
i |
在当前光标处进行编辑 |
I |
在行首插入 |
A |
在行末插入 |
a |
在光标后插入编辑 |
o |
在当前行后插入一个新行 |
O |
在当前行前插入一个新行 |
cw |
替换从光标所在位置后到一个单词结尾的字符 |
退出插入模式 esc
:e 文件名
从普通模式输入:
进入命令行模式,
输入w
回车,保存文档。
输入:w 文件名
可以将文档另存为其他文件名或存到其它路径下
命令 | 说明 |
---|---|
:q! |
强制退出,不保存 |
:q |
退出 |
:wq! |
强制保存并退出 |
:x |
保存并退出 |
:wq | 保存并退出 |
在Vim的命令行模式中,给命令加一个叹号前缀(参见:h:!)就可以调用外部程序。
初时,先有 ed,ed 为 ex 之父,ex 为 vi 之父,而vi为 Vim 之父。
Vim为几乎所有功能都提供了相应的Ex命令
有时使用 Ex 命令,能比用普通模式命令更快地完成同样的工作。
举个例子,普通模式命令一般操作当前字符或当前行,
而 Ex 命令却可以在任意位置执行,这意味着我们无需移动光标就可以使用 Ex 命令做出修改。
但使 Ex 命令脱颖而出的最让人赞叹的功能,是它们拥有能够在多行上同时执行的能力。
![截屏2021-01-07 上午10.08.38](/Users/isea/Desktop/截屏2021-01-07 上午10.08.38.png)
范围 (Ranges) 其实很好理解,但很多 Vim 用户的理解不到位。
- 很多命令都可以加一个数字,用于指明操作范围
- 范围可以是一个行号,用于指定某一行
- 范围也可以是一对通过
,
或;
分割的行号 - 大部分命令,默认只作用于当前行
- 只有
:write
和:global
是默认作用于所有行的
命令 | 操作的行 |
---|---|
:d |
当前行 |
:.d |
当前行 |
:1d |
第一行 |
:$d |
最后一行 |
:1,$d |
所有行 |
:%d |
所有行(这是 1,$ 的语法糖) |
:.,5d |
当前行至第 5 行 |
:,5d |
同样是当前行至第 5 行 |
:,+3d |
当前行及接下来的 3 行 |
:1,+3d |
第一行至当前行再加 3 行 |
:,-3d |
当前行及向上的 3 行(Vim 会弹出提示信息,因为这是一个保留的范围) |
:3,'xdelete |
第三行至标注 为 x 的那一行 |
:/^foo/,$delete |
当前行以下,以字符 "foo" 开头的那一行至结尾 |
:/^foo/+1,$delete |
当前行以下,以字符 "foo" 开头的那一行的下一行至结尾 |
需要注意的是,;
也可以用于表示范围。区别在于,a,b
的 b
是以当前行作为参考的。而 a;b
的 b
是以 a
行作为参考的。举个例子,现在你的光标在第 5 行。这时 :1,+1d
会删除第 1 行至第 6 行,而 :1;+1d
会删除第 1 行和第 2 行。
使用:t和:m命令复制和移动行
![截屏2021-01-07 上午10.25.13](/Users/isea/Library/Application Support/typora-user-images/截屏2021-01-07 上午10.25.13.png)
指定范围上执行普通模式命令
-
批量注释
:1,5normal I#
-
批量执行宏
Vim的可视模式允许我们选中一块文本区域并在其上进行操作,表面看这应该很容易理解,因为大多数编辑软件都沿用此模式
Vim具有3种不同的可视模式,分别用于操作字符文本、行文本或块文本
某些可视模式命令执行的基本功能与普通模式相同
在普通模式中,我们先触发修改命令,然后使用动作命令指定其作用范围
在可视模式中,我们先选中选区,然后再触发修改命令。
按 v 可激活面向字符的可视模式
我们能够选择任意的字符范围,不论它是单个字符,还是位于一行内,或是跨若干行的指定字符范围,都没问题。该模式适用于操作单词或短语。
按V(v和Shift键一起按)可激活面向行的可视模式,
按 (v和Ctrl键一起按)则可激活面向列块的可视模式
面向列块的可视模式则允许我们对文档中的列块进行操作。
替换行与列
行首添加
打开的文件都是作为缓冲区的一部分显示的。
窗口 是缓冲区上一层的视窗。如果你想同时查看几个文件或者查看同一文件的不同位置,那样你会需要窗口。
标签页 (标签)是窗口的集合。因此当你想使用多种窗口布局时候请使用标签。
在一次编辑会话中,可以打开多个文件。用Vim的缓冲区列表可以对这些文件进行管理。
文件与缓冲区的区别
常会说“我们正在编辑一个文件”,但真实情况并不是这样,我们所编辑的只是文件在内存中的映像,也就是 Vim 术语中的“缓冲区”。
:ls命令会列出所有被载入到内存中的缓冲区的列表
用 :bn 和 :bp 来遍历缓冲区列表
参数列表易于管理,适用于对一批文件进行分组,使其更容易访问。
参数列表记录了在启动时作为参数传递给Vim的文件列表。
默认情况下所有参数都被放在全局参数列表下,
但是你可以使用 :arglocal
命令去创建一个新的本地窗口的参数列表。
使用 :args
命令可以列出当前参数。使用 :next
,:previous
,:first
,:last
命令可以在切换在参数列表中的文件。通过使用 :argadd
,:argdelete
或者 :args
等命令加上一个文件列表可以改变参数列表。
:close
标签页是可以容纳一系列窗口的容器
标签页的编号从1开始,我们可以用 {N}gt 命令在标签页间切换,可以把此命令记成“跳到标签页{N}”
如果省略了数字前缀,则会跳到下一个标签页。gT 命令的功能与此相同,只是跳转方向相反
f{char} 命令是在 Vim 中移动的最快方式之一。它会在光标位置与当前行行尾之间查找指定的字符,如果找到了,就会把光标移到此字符上;如果未找到,则保持光标不动
Vim会记录上一次执行的查找命令,再次查找时可以使用 ; 命令来完成相同查找。
如果查询跳过头了,可以使用 , 命令返回光标之前的位置
f{char} : 正向移动到下一个{char}所在位置
F{char} : 反向移动到上一个{char}所在位置
t{char} : 正向移动到下一个{char}的前一个字符上
T{char} : 反向移动到上一个{char}的后一个字符上
跳转文件首行
vim普通模式下,使用 gg
跳转到当前文件的第一行;
vim命令行模式下,使用 :0
或 :1
跳转光标到当前文件的首行。
跳转文件尾行
vim普通模式下,使用 G
跳转光标到当前文件的最后一行 (尾行); vim命令行模式下,使用 :$
跳转光标到当前文件的尾行。
跳转文件任意行
vim普通模式下,使用 nG 跳转光标到当前文件的第 n 行。
vim命令行模式下,使用命令 :n
跳转光标到当前文件的第 n 行。
% 命令允许我们在一组开、闭括号间跳转
你可以使用标注功能来标记一个位置,也就是记录文件某行的某个位置。
标注 | 设置者 | 使用 |
---|---|---|
a -z
|
用户 | 仅对当前的一个文件生效,也就意味着只可以在当前文件中跳转 |
A -Z
|
用户 | 全局标注,可以作用于不同文件。大写标注也称为「文件标注」。跳转时有可能会切换到另一个缓冲区 |
0 -9
|
viminfo |
0 代表 viminfo 最后一次被写入的位置。实际使用中,就代表 Vim 进程最后一次结束的位置。1 代表 Vim 进程倒数第二次结束的位置,以此类推 |
如果你想定义当前文件中的标注,可以先按下 m
再按下标注名。比如,按下 mm
就可以把当前位置标注为 m
。在这之后,如果你的光标切换到了文件的其他位置,只需要通过 'm
或者 ``m`即可回到刚才标注的行。
按键 | 跳转至 |
---|---|
'[ 与 ``[` |
上一次修改或复制的第一行或第一个字符 |
'] 与 ``]` |
上一次修改或复制的最后一行或最后一个字符 |
'< 与 ``<` |
上一次在可视模式下选取的第一行或第一个字符 |
'> 与 ``>` |
上一次在可视模式下选取的最后一行或最后一个字符 |
'' 与 ``'` |
上一次跳转之前的光标位置 |
'" 与 ``"` |
上一次关闭当前缓冲区时的光标位置 |
'^ 与 ``^` |
上一次插入字符后的光标位置 |
'. 与 ``.` |
上一次修改文本后的光标位置 |
'( 与 ``(` |
当前句子的开头 |
') 与 ``)` |
当前句子的结尾 |
'{ 与 ``{` |
当前段落的开头 |
'} 与 ``}` |
当前段落的结尾 |
Vim 的寄存器是一组用于保存文本的简单容器。 它们既可像剪贴板那样,剪切、复制和粘贴文本;也可以记录一系列按键操作,把它们录制成宏。
类型 | 标识 | 读写者 | 是否为只读 | 包含的字符来源 |
---|---|---|---|---|
Unnamed | " |
vim | 否 | 最近一次的复制或删除操作 (d , c , s , x , y ) |
Numbered |
0 至9
|
vim | 否 | 寄存器 0 : 最近一次复制。寄存器 1 : 最近一次删除。寄存器 2 : 倒数第二次删除,以此类推。对于寄存器 1 至 9 ,他们其实是只读的最多包含 9 个元素的队列。这里的队列即为数据类型 queue
|
Small delete | - |
vim | 否 | 最近一次行内删除 |
Named |
a 至z , A 至Z
|
用户 | 否 | 如果你通过复制操作存储文本至寄存器 a ,那么 a 中的文本就会被完全覆盖。如果你存储至 A ,那么会将文本添加给寄存器 a ,不会覆盖之前已有的文本 |
Read-only |
: 与. 和%
|
vim | 是 |
: : 最近一次使用的命令,. : 最近一次添加的文本,% : 当前的文件名 |
Alternate buffer | # |
vim | 否 | 大部分情况下,这个寄存器是当前窗口中,上一次访问的缓冲区。请参阅 :h alternate-file 来获取更多帮助 |
Expression | = |
用户 | 否 | 复制 VimL 代码时,这个寄存器用于存储代码片段的执行结果。比如,在插入模式下复制 <c-r>=5+5<cr> ,那么这个寄存器就会存入 10 |
Selection |
+ 和*
|
vim | 否 |
* 和 + 是 剪贴板 寄存器 |
Drop | ~ |
vim | 是 | 最后一次拖拽添加至 Vim 的文本(需要 "+dnd" 支持,暂时只支持 GTK GUI。请参阅 :help dnd 及 :help quote~ ) |
Black hole | _ |
vim | 否 | 一般称为黑洞寄存器。对于当前操作,如果你不希望在其他寄存器中保留文本,那就在命令前加上 _ 。比如,"_dd 命令不会将文本放到寄存器 " 、1 、+ 或 * 中 |
Last search pattern | / |
vim | 否 | 最近一次通过 / 、? 或 :global 等命令调用的匹配条件 |
我们可以通过给命令加 "{register} 前缀的方式指定要用的寄存器。若不指明,Vim 将缺省使用无名寄存器。
将文本存到指定的寄存器中: 命令 "aY
可以将当前行复制,并存储到寄存器 a
中。这时移动光标至其他位置,通过命令 "AY
就可以把这一行的内容扩展到寄存器 a
中,而之前存储的内容也不会丢失。
Vim的加号寄存器与系统剪贴板等效,
程序中用剪切或复制命令获取了文本,就可以通过 "+p 命令(或在插入模式下用 +)将其粘贴到Vim 内部。
可以在 Vim 中录制一系列按键,并把他们存储到寄存器中。
对于一些需要临时使用多次的一系列操作,把它们作为宏保存起来会显著地提升效率。
对于一些复杂的操作,建议使用 Vim 脚本来实现。
q 键既是“录制”按钮,也是“停止”按钮。
- 首先,按下 q,然后按下你想要保存的寄存器,任何小写字母都可以。比如我们来把它保存到
q
这个寄存器中。按下qq
,你会发现命令行里已经显示了 "recording @q"。 - 如果你已经录制完成,那么只需要再按一次 q 就可以结束录制。
- 如果你想调用刚才录制的宏,只需要
[count]@q
- 如果你想调用上一次使用的宏,只需要
[count]@@
串行执行
5@a
并行执行
:1,5normal @a
普通模式下,按下 / 键会调出 Vim 的查找提示符,可在它的后面输入要查找的模式或者原义文本。另外,只有当我们按下 键时,Vim才会执行查找命令
当我们使用 / 键执行一次查找时,Vim将进行正向扫描。
而如果是用 ? 键调出查找提示符的话,Vim则会进行反向查找。
n 命令用于跳转到下一处匹配,而 N命令则用于跳转到上一处匹配。
在普通模式下,* 命令让我们可以查找光标下的单词。
substitute是一个ex命令,允许我们先查找一段文本,再用另一段文本将其替换掉。
命令的语法如下所示: :[range]s[ubstitute]/{pattern}/{string}/[flags]
模式,可以使用正则
将substitute命令的查找域留空,意味着Vim将会重用上次的查找模式。我们可以利用这一特点精简工作过程。
标志位 g使得 subsititute 命令可在全局范围内执行,即可以修改一行内的所有匹配,而不仅仅是第一处匹配。 标志位c让我们有机会可以确认或拒绝每一处修改。 标志位 n 会抑制正常的替换行为,即让 Vim 不执行替换操作,而只是报告本次substitute 命
%s///gn
.vimrc 是控制 vim 行为的配置文件,位于 ~/.vimrc
各类 vim 插件帮助文档中经常出现 ,即,前缀键。vim 自带有很多快捷键,再加上各类插件的快捷键,大量快捷键出现在单层空间中难免引起冲突,为缓解该问题,引入了前缀键
递归 | 非递归 | 模式 |
---|---|---|
:map |
:noremap |
normal, visual, operator-pending |
:nmap |
:nnoremap |
normal |
:xmap |
:xnoremap |
visual |
:cmap |
:cnoremap |
command-line |
:omap |
:onoremap |
operator-pending |
:imap |
:inoremap |
insert |
经验法则:除递归映射是必须的,否则总是使用非递归映射。
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l
map <leader>z :Goyo<cr>
map <leader>nn :NERDTreeToggle<cr>
vscode
Easymotion
多光标模式
"workbench.action.showCommands",
pycharm
chrome
zsh
tmux
vim 配置方案 https://github.com/amix/vimrc
插件管理 vundle https://github.com/VundleVim/Vundle.vim
vscode vim插件 https://github.com/VSCodeVim/Vim
vim 配置方案 https://github.com/SpaceVim/SpaceVim
<<Vim 使用技巧>>