# NORMAL 普通模式
进入 vim 默认是 normal 模式(因为大部分情况是浏览而不是编辑)。 normal 模式下可以进行各种命令操作和移动。使用 Esc 可以从 insert 模式回到 normal 模式。
# 光标移动
- h 向左移动光标。
- j 向下移动光标。
- k 向上移动光标。
- l 向右移动光标。
# 单词移动
w/W移动到下一个 word/WORD 开头,e/E移动到下一个 word/WORD 结尾。b/B(back word) 回到上一个 word/WORD 开头。- word 指以非空白字符分割的单词,WORD 以空白字符分割的单词。
# 行间搜索移动
同一行快速移动的方式是搜索一个字符并且移动到该字符。
- 使用
f{char}可以移动到 char 字符上,t移动到 char 的前一个字符。 - 使用
;或,继续搜索该行下一个或上一个。 - 大写的
F表示反过来搜索前面的字符。
# 水平移动
快速移动到一行的行首或行尾。
0移动到行首第一个字符,^移动到第一个非空白字符。$移动到行尾,g_移动到行尾非空白字符。
# 页面移动
gg / G移动到文件开头和结尾,可以使用Ctrl + o快速返回,一直往后退到上次的文件和位置。H / M / L跳转到窗口的开头(Head),中间(Middle) 和结尾(Lower)。Ctrl + u / Ctrl + f上下翻页(upward/forward)。zz把光标所在位置的内容移动到窗口中间。
# 快速删除
x快速删除一个字符。d配合文本对象快速删除一个单词daw/dw(delete around word)。dd删除一行,d0删除到行首,d$删除到行尾,dt;删除到;不包含;,df;刪除到;包含;。d和x可以搭配数字执行,表示重复执行,4dd删除 4 行,4x删除 4 个字符。
# 快速修改
rreplace 替换一个字符,R进入replace模式,连续向后替换。ssubstitute 删除当前字符并进入插入模式,4s删除 4 个字符进入插入模式,S整行删除进入插入模式。cchange 配合文本对象修改,cw删除当前单词进入插入模式;ct;删除到;不包含;进入插入模式,cf;删除到;包含;进入插入模模式;C整行删除进入插入模式。
# 查询
/或者?进行前向或者反向搜索。n / N跳转到下一个或者上一个匹配,需要先使用enter退出搜索。* / #进行当前单词的前向和后向匹配。
# 复制 / 剪切 / 黏贴
ddelete 删除。yyank 复制。Pput 在当前行上方粘贴。pput 在当前行下方粘贴。
# 撤销和重做
u撤销上一步的操作。Ctrl+r恢复上一步被撤销的操作。
# INSERT 插入模式
# 进入 INSERT 模式
normal 模式切换到 insert 模式有如下几种方式。
| Command | Meaning |
|---|---|
| i | insert before of current character |
| a | append after of current character |
| I | insert of line start |
| A | append of line end |
| o | append a line below |
| O | insert a line above |
# 删除操作
如下命令也可以在 Terminal 中使用。
Ctrl + h删除上一个字符。Ctrl + w删除上一个单词。Ctrl + u删除当前行。
# COMMAND 命令模式
| Command | Meaning |
|---|---|
:wq/:x |
写入并退出 |
:vs |
vertical split 垂直分屏 |
:sp |
split 水平分屏 |
:set nu |
设置行号 |
:set nu! |
取消行号设置 |
:% s/foo/bar/g |
全局替换 foo -> bar |
:help s |
查询帮助 |
:e b.txt |
打开当前目录下的 b.txt 文件 |
:e! |
重新加载并且不保存当前文件 |
# 替换命令
substitute 命令可以用来查找并且替换文本,并且支持正则表达式。
:[range]s[ubstitute]/{pattern}/{string}/[flags]
range表示范围,例如: 10,20 表示 10-20 行,% 表示全部。pattern要替换的模式。string需要替换成的文本。flags替换标志位。g(global)表示全局范围内执行。c(confirm)表示确认,可以确认或者拒绝修改。n(number)报告匹配的次数而不替换,可以用来查询匹配次数。
example: :% s/\<foo\>/bar 精确匹配 foo, 替换成 bar.
# VISUAL 可视模式
visual 模式一般用来块状选择文本。 normal 模式下进入 visual 模式有如下三种方式。
-
v进入VISUAL模式选择一个字符。 -
V进入VISUAL LINE模式选择整行。 -
Ctrl + v进入VISUAL BLOCK进行块状选择。
注释多行 Python 文本。
Ctrl + v进入VISUAL BLOCK, 选中要注释的行。I #在行前加上#。Esc退出,所有块选的行都会添加上#。
# 模式切换
insert => normal
Esc 可以从 insert 模式回到 normal 模式,也可以使用 Ctrl + c 或者 Ctrl + [ 代替 Esc (可能会中断某些插件)。
normal => insert
i, a, I, A, o, O 进入插入模式。
gi 快速跳转到最后一次编辑的地方并进入插入模式。
# 多文件操作
Buffer 是指打开的一个文件的内存缓冲区,Window 是 Buffer 可视化的分割区域,Tab 可以组织多个 Window 为一个工作区。
# Buffer
Buffer 是指打开的一个文件的内存缓冲区。
- Vim 打开一个文件后会加载文件内容到缓存区,之后的修改都是针对内存中的缓存区,并不会直接保存到文件,直到我们执行
:w(write) 的时候才会把修改内容写入到文件里。 :e filename打开多个文件,创建多个缓存区,使用:ls会列举当前缓存区,然后使用:b n跳转到第n个缓存区。:bpre:bnext:bfirst:blast分別跳转到上一个,下一个,第一个最后一个缓存区。:b buffer_name跳转到指定缓存区。
# Window
Window 是 Buffer 可视化的分割区域。
- 一个缓存区可以分割成多个窗口,每个窗口也可以打开不同的缓存区。
<Ctrl + w> s水平分割,<Ctrl + w> v垂直分割。或者使用:sp和:vs。
注意: <Ctrl + w> s 这种命令要先按 Ctrl + w , 松开后按 s 。
| Command | Meaning |
|---|---|
<Ctrl + w> w |
在窗口间循环切换 |
<Ctrl + w> h |
切换到左边的窗口 |
<Ctrl + w> j |
切换到下边的窗口 |
<Ctrl + w> k |
切换到上边的窗口 |
<Ctrl + w> l |
切换到右边的窗口 |
<Ctrl + w> H |
把窗口移动到左边 |
<Ctrl + w> L |
把窗口移动到右边 |
可以在 vimrc 加入映射配置使窗口切换更加简单。
1 | " 使用 Ctrl + h/j/k/l 切换窗口 |
# Tab
Tab 可以组织 Window 为一个工作区。
-
Vim 的 Tab 和其它编辑器不太一样,可以想象成 Linux 的虚拟桌面。
-
比如一个 Tab 全部用来编辑 Python 文件,一个 Tab 全部是 HTML 文件。
| Command | Meaning | |
|---|---|---|
:tabn[ew] {filename} |
在新标签页打开 | |
:tabe[dit] {filename} |
在新标签页打开 | |
<Ctrl+w> T |
把当前窗口移动到一个新的标签页 | |
:tabc[lose] |
关闭当前标签页及其中的所有窗口 | |
:tabo[nly] |
只保留活动标签页,关闭其它标签页 | |
| Ex Command | Normal Command | Meaning |
| ---------------- | -------------- | --------------------------- |
:tabn[ext] {N} |
{N}gt |
切换到编号为 {N} 的标签页 |
:tabn[ext] |
gt |
切换到下一标签页 |
:tabp[revious] |
gT |
切换到上一标签页 |
# Text Object
Text Object 文本对象。
- Vim 里文本也有对象的概念,比如一个单词,一段句子,一个段落。
- Vim 可以通过操作文本对象来修改文本比指操作单个字符高效。
Text Object 文本对象操作方式
[number] <command> [text object]number表示次数command是命令,d(elete),c(hange),y(ank)- text object 是要操作的文本对象,比如单词
w, 句子s, 段落p
iw 表示 inner word, 如果键入 viw 那么首先 v 将进入选择模式,然后 iw 选中当前单词。
aw 表示 around word, 它不但会选中当前单词,还会包含单词之后的空格。
i( , i) 选中 () 里面的内容,其它的 i< , i" 等也可以。
a( , a) 选中 () 和 () 里面的内容。
# 复制粘贴与寄存器
# NORMAL 模式下的复制与粘贴
- normal 模式下复制粘贴分別使用
y(yank)和p(put), 剪切使用d(delete) + p(put). - 可以使用
v(visual)命令选中所要接收复制内容的地方,然后使用p粘贴。 - 配合文本对象,比如使用
yiw复制一个单词,yy复制一行。
# INSERT 模式下的复制与粘贴
- 和其它文本编辑器差不多,使用
Ctrl + c选中,使用Crtl + v粘贴(Widows Git 中使用 Vim, 使用鼠标右键复制粘贴)。 - 在
vimrc中设置了autoindent的情况下,粘贴 Python 代码缩进会混乱,这个时候需要使用:set paste进行粘贴,粘贴之后执行:set nopaste。
# 寄存器
Vim 在 normal 模式下复制 / 剪贴的内容去了哪?
- Vim 里操作的是寄存器而不是系统剪贴板,这和其它编辑器不同。
- 默认我们使用
d删除或者y复制的内容以及x删除一个字符都放到了无名寄存器。
# 深入寄存器 (register)
Vim 不使用单一剪贴板进行剪贴,复制与粘贴,而是多组寄存器。
- 通过
"{register}前缀可以指定寄存器,不使用默认的无名寄存器。 - 比如
"ayiw复制一个单词到寄存器a中,"bdd删除当前行到寄存器b中。:reg a查看a寄存器。"ap粘贴a寄存器中的内容。
- Vim 中
""表示无名寄存器,缺省使用。""p其实就等于p.
# 其它常用寄存器
除了有名的寄存器 a-z , Vim 中还有一些其它常见的寄存器。
- 复制专用寄存器
"0, 使用y复制文本到无名寄存器的同时会被拷贝到复制寄存器0. - 系统剪贴板
"+, 可以在复制前加上"+复制到系统剪贴板。:echo has('clipboard')输出的是1表示支持系统剪贴板。:set clipboard=unnamed可以让你直接复制粘贴系统剪贴板内容,在 Vim 中y复制的内容,可以在其它编辑软件中Ctrl + v粘贴,在其它编辑软件Ctrl + c复制的内容,在 Vim 中可以用p直接粘贴(Widows Git 中使用 Vim 默认支持这种方式的复制粘贴)。
- 其它一些寄存器,比如
"%表示当前文件名,".上次插入的文本。
# Macro 宏
宏可以看成一系列命令的集合。我们可以使用宏录制一系列操作,然后用于回放。宏可以非常方便把一系列命令用在多行文本上。
- Vim 使用
q来录制宏,同时也是使用q结束录制。 - 使用
q{register}选择要保存的寄存器,把录制的命令保存其中。 - 使用
@{register}回访寄存器中保存的一系列命令。
使用宏给如下文本每行前后添加上双引号。
- normal 模式定位到第一行,
qa开始录制宏到a寄存器。 - (Caps Lock 切换到大写)
I进入 insert 模式,在行首添加";Esc退回到 normal 模式;A进入 insert 模式,在行末添加"。 - (Caps Lock 切换到小写)
Esc退回到 normal 模式;q结束宏录制。 - normal 模式定位到第二行,
V进入 visual 模式并选中当前行,G向下选中所有行。 - command 模式使用 normal 命令,
:'<,'>normal @a回放a寄存器中的宏命令。
1 | https://khmdb.googleapis.com |
不使用宏给上面文本每行前后添加上双引号。
- normal 模式定位到第一行,
V进入 visual 模式并选中当前行,G向下选中所有行。 :'<,'>normal I"在每行行首添加上".:然后按下Ctrl + p执行上一个命令,替换命令为:'<,'>normal A"在每行行尾添加上".
# 补全
常见的三种补全方式。
- 使用
Ctrl + n和Ctrl + p补全单词。 - 使用
Ctrl + x+Ctrl + f补全文件名。:r[ead]插入命令输出到 buffer。:r! echo %插入当前文件名。:r! echo %:p插入当前文件全路径名。
- 使用
Ctrl + xCtrl + o补全代码,需要开启文件类型检查,安装插件。
# 配色
- 使用
:colorscheme显示当前的主题色,默认是default. - 使用
:colorscheme <Ctrl + d>可以显示所有的配色。 - 使用
:colorscheme {schemename}可以修改配色。
使用网上下载的配色,以 GitHub - w0ng/vim-hybrid: A dark color scheme for Vim 为例。复制 colors/hybrid.vim 到 ~/.vim/colors/hybrid.vim , 没有 ~/.vim/colors 目录需要先手动建立,之后可以使用插件管理器管理,然后在使用 :colorscheme hybrid 选择配色。如果要持久化配色方案需要在 ~/.vim/vimrc 中添加相应配置。
1 | set background=dark |
注意:Windows Git 默认 term 是 xterm, 不支持 256 色,需要调整为 xterm-256color, :set term=xterm-256color .
# 配置
- 可以把常用的设置写到
~/.vim/vimrc中,避免每次打开 vim 重新设置。 - 比如设置行号
set nu; 设置主题colorscheme hybrid.
1 | " 设置行号 |
如何使配置生效,第一种是重新打开 Vim, 第二种是 w 保存但是不退出,然后执行 :source % , % 表示当前文件名。
# 映射
Vim 映射就是把一个操作映射到另一个操作。
# 基本映射
基本映射指的是 normal 模式下的映射。使用 map 添加映射命令, unmap 取消映射命令。
:map - x按下-会删除字符。:map <space> viw按下空格的时候会选中整个单词。:map <c-d> dd按下Ctrl + d执行dd删除一行。:unmap -取消-的映射。
# 模式映射
Vim 常用模式 normal/visual/insert 都可以定义映射,用 nmap , vmap , imap 定义只在 normal/visual/insert 分別有效。
:vmap \ U在 visual 模式下使用\转换所选字符或块字母为大写(U/u 转换大小写)。- 在 insert 模式下映射
Ctrl + d来删除一行:imap <c-d> <Esc>ddi.
# 递归映射与非递归映射
如下,当你按下 \ 时,Vim 会解释其为 - , 然后又映射了 - , Vim 会继续解释 - 为 dd , 即它会删除整行。 nmap , vmap , imap 命令有递归的风险,如果安装了一个插件,插件映射了同一个按键的不同行为,就会有冲突,有一个就会失效。
1 | :nmap - dd |
所以 Vim 提供了非递归映射 (no recursive map),这些命令不会递归解释, nnoremap , vnoremap , inoremap .
在 ~/.vim/vimrc 中添加映射配置。
1 | """"""" 基本配置 """""" |
# 插件
# 如何安装插件
- 原始的方式是直接 clone 插件代码。
- 现在可以使用插件管理器。常见的插件管理器有 vim-plug , Vundle, Pathogen, Dein.Vim, volt, minpac 等。
以 minpac 为例。
Meet minpac
GitHub - k-takata/minpac: A minimal package manager for Vim 8 (and Neovim)
在 ~/.vim/vimrc 中添加插件配置。
1 | " Use Vim settings, rather than Vi settings (much better!). |
# 如何搜寻插件
-
大部分插件托管在了 github 上,可以通过 google 搜索关键词寻找想要的插件,例如 vim file manager plugin, vim python plugin github.
-
可以在 Vim Awesome 查找需要的插件,Vim Awesome: AWESOME VIM PLUGINS from ACROSS THE UNIVERSE.
-
浏览网上开源的 vim 配置借鉴想要的插件。
# 常用插件
# vim-startify
GitHub - mhinz/vim-startify: The fancy start screen for Vim.
1 | call minpac#add('mhinz/vim-startify') |
# vim-airline
GitHub - vim-airline/vim-airline: lean & mean status/tabline for vim that’s light as air
1 | call minpac#add('vim-airline/vim-airline') |
# vim-indentline
GitHub - Yggdroot/indentLine: A vim plugin to display the indention levels with thin vertical lines
1 | call minpac#add('Yggdroot/indentLine') |
# nerdtree
GitHub - preservim/nerdtree: A tree explorer plugin for vim.
1 | call minpac#add('preservim/nerdtree') |
# ctrlp
GitHub - kien/ctrlp.vim: Fuzzy file, buffer, mru, tag, etc finder.
1 | call minpac#add('kien/ctrlp.vim') |
# easymotion
GitHub - easymotion/vim-easymotion: Vim motions on speed!
1 | call minpac#add('easymotion/vim-easymotion') |
-
normal 模式下,连续按两次
s. 输入需要查找的两个字符。例如op. -
选择 Tagget key, 例如这里选择
s会定位到第63行的 opt 前面。
# vim-surround
GitHub - tpope/vim-surround: surround.vim: Delete/change/add parentheses/quotes/XML-tags/much more with ease
1 | call minpac#add('tpope/vim-surround') |
normal 模式下增加,删除,修改成对内容。
-
ys(you add a surrounding)ys iw "为当前光标定位的单词前后添加". -
cs(change a surrounding)cs ( [替换()为[ ]此时[ ]前后有空格,如果不需要空格,使用cs ( ]. -
ds(delete a surrounding)ds "删除单词左右的".
# fzf.vim
GitHub - junegunn/fzf.vim: fzf vim
1 | call minpac#add('junegunn/fzf.vim') |
:Files [PATH]模糊搜索当前目录文件,:Files /搜索当前目录。:Ag [PATTERN]模糊搜索字符串,Ctrl + j到下一个匹配项,Ctrl + k到上一个匹配项;并且可以继续输入字符串进行更精确的匹配。(Windows 需要额外配置)
# far.vim
GitHub - brooth/far.vim: Find And Replace Vim plugin
1 | call minpac#add('brooth/far.vim') |
:Far foo bar **/*.py替换 foo 为 bar。:Fardo确认替换。
# Terminal 快速操作
| Command | Meaning |
|---|---|
Ctrl + h |
删除上一个字符 |
Ctrl + d |
删除下一个字符 |
Ctrl + w |
删除上一个单词 |
Ctrl + k |
删除后面所有字符 |
Ctrl + u |
删除当前行 |
Ctrl + a |
移动到行首 |
Ctrl + e |
移动到行尾 |
Ctrl + b |
向前移动一个字符 |
Ctrl + f |
向后移动一个字符 |
Ctrl + _ |
撤销上一步的操作 (Window Git: Ctrl + Shift + _) |
Ctrl + l |
清屏置顶 |