玩转Vim
世界上10种人,会用Vim的和不会用Vim的
玩转Vim,从放弃到爱不释手
什么是Vim
Linux下两大编辑神器之一Vim
- Linux/Unix下使用最多的编辑器
- Vi的改进版
- 可能是最难上手的编辑器之一
为什么要学习Vim ?
都21世纪了,为什么还需要学习Vim ?
- 只要你用服务器,Vim就是个必备技能
- 后端和运维工程师必须掌握的编辑器,不然服务器上操作很尴尬
- 可以纯键盘编辑,提升编辑效率
痛点
Vim难上手,学习曲线陡
- Vim视频学习资料很少,网上很多博客讲解零散,不够直观
- 缺少系统的教程。Vim命令众多,难以学习和记忆
- Vim学习曲线比较陡,需要较长时间才能上手,劝退很多初学者
目的
帮你驯服 Vim
- 了解和掌握Vim中的基本概念
- 熟悉Vim基本使用方法,能够做到日常编辑(纯键盘编辑)
- 知道如何自定义Vim,安装插件无限扩充 Vim的功能
内容
如何学习Vim ? Vim经常被诟病难以上手和使用
- Vim的概念和基本操作,比如移动和增删改查
- 如何配置Vim,编写自己的vimrc文件
- 如何安装和使用插件,无限扩充Vim 功能
预备知识
不要求掌握Vim的基础知识,但最好使用Linux/Unix系统
- 熟悉基本的命令行操作(一般Vim多在Linux服务器上使用)
- 知道如何安装 Vim
- 有其他编辑器使用经验。几乎所有流行IDE和编辑器都有Vim扩展
初识Vim,想说声爱你以很久
开始编辑
输入i
(insert)进入编辑模式,开始输入文字
i
表示在当前字符的后一个位置插入
a
表示在当前字符的前一个位置插入
o
表示在当前字符所在行的下一行插入
I
表示在当前字符所在行的最后一个位置插入
A
表示在当前字符所在行的第一个位置插入
O
表示在当前字符所在行的上一行插入
:w
保存当前文件
:q
退出当前文件
:wq
保存并退出当前文件
:h option-list
查看设置缩写
esc
回到正常(normal)模式
Vim小技巧
快速修正
进入vim之后使用a/i/o
之一进入插入模式
ctrl+h
删除上一个字符
ctrl+w
删除上一个单词
ctrl+u
删除当前行
快速切换insert
和normal
模式
使用ctrl+c
替换Esc
(但是可能会中断某些插件)或者ctrl+[
gi
快速跳转到你最后一次编译的地方并进入插入模式
Vim的反人类移动
normal下模式移动
字符间的移动
h
左移,j
下移,k
下移,l
右移
单词间的移动
w/W
移动到下一个word/WORD
开头
e/E
移动到下一个word/WORD
尾
b/B
回到上一个word/WORD
开头
word
指以非空格符分割的单词,WORD
指以空格符分割的单词
行间搜索移动
同一行移动的方式是搜索一个字符并且移动到该字符
使用f{char}
可以移动到char
字符上,t
移动到char
的前一个字符
如果第一次搜到,可与使用分号/逗号
继续搜索该行下一个/上一个
F
表示反过来搜索前面的字符
水平移动
0
移动到行首第一个字符,^
移动到第一个非空白字符
$
移动到行尾,g_
移动到行尾非空白字符
页面移动
gg/G
移动到文件开头/结尾,使用ctrl+o
快速返回
H/M/L
跳转到屏幕的开头、中间、结尾
ctrl+u
和ctrl+f
上下翻页,zz
把当前行置为屏幕中间
Vim的增删改查
增加字符就是进入插入模式,开始敲键盘
进入插入模式编辑文本
使用a/i/o
进入插入模式
快速删除
Vim在normal
模式下使用x快速删除一个字符
使用d
配合文本对象快速删除一个单词
dw
删除一个单词,默认daw
daw
删除一个单词包括周围的空格
diw
删除一个单词不包括周围的空格
dd
删除当前行
dt
+char
当前位置删除到char
位置
d$
当前位置删除到行尾
d0
当前位置删除到行首
d
和x
都可以搭配数字来执行多次
2dd
删除两行(相当于dd
执行两次)
4x
删除4个字符(相当于x
执行四次)
快速修改
相比删除,更常用修改,一般都是删除之后改成我们期望的文本
常用的有三个r
(replace),c
(change),s
(substitute)
normal
模式下使用r
可以替换一个字符,s
删除并进入插入模式
R
不断替换后面的单词,S
整行删除并进入插入模式
使用c
配合文本对象快速修改,删除并进入插入模式
查询
使用/
或?
进行前向或者反向搜索
使用n
或N
跳转到下一个或上一个匹配
使用*
或者#
进行当前单词的前向和后向匹配
Vim搜索替换
substitute命令允许我们进行查找并替换文本,并支持正则式
:[range]s[ubstitute]/{pattern}/{string}/[flags]
-
range
表示范围,比如: 10,20
表示10-20行,%
表示全部 -
pattern
是要替换的文本 -
string
是替换后文本 -
flage
有几个常用的标志g
(global)表示全局范围内执行c
(confirm)每次修改前需要确认,可以同意或者拒绝n
(number)报告匹配到的次数而不替换,可以用来查询匹配次数
:[range]s[ubstitute]/{\<pattern>}/{string}/[flags]
精确匹配到文本单词
Vim多文件操作
几个文件相关的概念:Buffer,Window、Tab
Buffer是指打开一个文件的内存缓冲区
Window是Buffer可视化的分割区
Tab可以组织窗口为一个工作区
Buffer
- Vim打开一个文件后,会加载文件内容到缓冲区
- 之后的修改都是针对内存中的缓冲区,并不会直接保存到文件
- 知道我们执行
:w
(write)的时候才会把修改的内容写到文件里
如何在buffer之间切换?
- 使用
:ls
会列举当前缓冲区,然后使用:b n
跳转到第n个缓冲区 :bpre
:bnext
:bfirst
:blast
- 或者用
:b buffer_name
加上tab
补全来跳转
Window窗口
窗口是可视化的分割区域
- 一个缓冲区可以分割成多个窗口,每个窗口也可以打开不同缓冲区
<ctrl+w>+s
水平分割,<ctrl+w>+v
垂直分割。或者:sp
和:vs
- 每个窗口可以继续被分割
如何切换窗口
切换窗口的命令都是使用ctrl+w
(window)作为前缀
命令 | 用途 |
---|---|
<ctrl+w>+w | 在窗口间循环切换 |
<ctrl+w>+h | 切换到左边的窗口 |
<ctrl+w>+j | 切换到下边的窗口 |
<ctrl+w>+k | 切换到上边的窗口 |
<ctrl+w>+l | 切换到右边的窗口 |
Tab将窗口分组
-
相比窗口,Tab一般用的比较少,Tab太多管理起来不方便
-
Vim的Tab和其他编译器不太一样,可以想象成Linux的虚拟桌面
-
比如一个Tab全用来编辑Python文件,一个Tab全是HTML文件
Tab操作
命令 | 用途 |
---|---|
:tabe[dit] {filename} | 在新标签页中打开{filename} |
<ctrl+w>T | 把当前窗口移到一个新标签页 |
:tabc[lose] | 关闭当前标签页及其中的所有窗口 |
:tabo[nly] | 只保留活动标签页,关闭所有其他标签 |
Tab切换操作
Ex命令 | 普通模式命令 | 用途 |
---|---|---|
:tabn[ext] {N} | {N}gt | 切换到编号为{N}的标签页 |
:tabn[ext] | gt | 切换到下一标签页 |
:tabp[revious] | gT | 切换到上一标签页 |
Vim的Text Object
之前我们已经使用过文本对象了,如dw(删除一个单词)
[number]<command>[text object]
number
表示次数,command
是命令,如d(delete)
、c(change)
、y(yank)
,text object
是要操作的文本对象,比如单词w
、句子s
、段落p
Vim的复制粘贴与寄存器的使用
Normal模式下的复制粘贴
normal
模式下的复制粘贴分别使用y(yank)
和p(put)
,剪贴d
和p
- 使用
v(visual)
命令选中所要复制的地方,然后使用p
粘贴 - 配合文本对象,比如
yiw
复制一个单词,yy
复制一行
Vim里的剪贴(cut)复制(copy)粘贴(paste)分别是delete/yank/put
Insert模式下的复制粘贴
很多人会使用鼠标进行选中,然后使用ctrl+v
或者cmd+v
粘贴
- 这个其他文本编译器差不多,但是粘贴代码有个坑
- 很多人在
vimrc
中设置了autoindent
,粘贴代码缩进错乱 - 这个时候需要在进如
insert
模式之前,先使用:set paste
,粘贴后退出insert
模式,在使用:set nopaste
Vim寄存器
- Vim里操作的是寄存器而不是系统复制剪贴板,这和其他编译器不同
- 默认我们使用
d
删除或者y
复制的内容都放到了“无名寄存器” - 用x删除一个字符放到无名寄存器,然后
p
粘贴,可以调换俩字符
Vim不使用单一剪贴板进行剪贴、复制、粘贴,而是多组寄存器
- 通过
"
{register}前缀可以指定寄存器,不指定默认使用无名寄存器 - 比如使用
"ayiw
复制一个单词到寄存器a中,"bdd
删除当前行到寄存器b中 "+y
复制到系统剪贴板,"+p
将系统剪贴板内容复制到Vim里
强大的Vim宏(macro)
什么是宏
- 宏可以看成是一系列命令的集合
- 我们可以使用宏“录制”一系列操作,然后用于“回放”
- 宏可以非常方便地把一系列命令用在多行文本上
如何使用宏
- Vim使用
q
来录制,同时也是q结束录制 - 使用
q
{register}选择要保存的寄存器,把录制的命令保存其中 - 选中要操作的文本使用
:normal @
{register}回放寄存器中保存的一系列命令
Vim补全大法
只要手速快,补全都是浮云
常用的补全类型有三种
- 使用
ctrl+n
和ctrl+p
补全单词 - 使用
ctrl+x ctrl+f
补全文件名 - 使用
ctrl+x ctrl+o
补全代码,学要开启文件类型检查,安装插件
给Vim换个配色
很多现代化编译器和IDE都支持更换主题,Vim当然也可以
- 使用
:colorscheme
显示当前的主题颜色,默认是default - 用
:colorscheme <ctrl+d>
可以显示所有配色 - 使用
:colorscheme 配色名
就可以修改配色
从网上下载配色
- 从网络上寻找更好看的配色
- githab
- 安装之后就有大量的主题可以更换了
Vim命令和快捷键
编写Vim配置,我的Vim我做主
如何编写自己的Vim配置文件
- Linux/Unix下新建一个隐藏文件vim ~/.vimrc
- windows系统vim $MYVIMRC,通过环境变量编辑配置文件
- 接着就可以自定义自己的配置了
编译Vim配置文件,可以设置的内容
- 常用设置,比如
:set nu
设置行号,colorscheme hybrid
设置主题 - 常用的Vim映射,比如
noremap <leader>w :w<cr>
保存文件 - 自定义的vimscript函数和插件的配置
Vim插件
下章介绍
Vim脚本
Vim有自己的脚本语言Vimscript
- Vim脚本对于Vim高级玩家来说可以实现强大的Vim插件
- 初学者知道这个概念就好,Vim脚本是一种简单的脚本语言
- 可以通过vimscript实现更多vim的控制,开发自己的插件
Vim映射
-
Vim映射就是把“一个操作”映射到“另一个操作”
-
或者你想映射一些方便的快捷键
-
按照你的意愿去定制Vim。当我按下某些建时,放弃你默认的操作,按照我的想法去做
基本映射
基本映射是指normal模式下的映射,当然还有其他模式下的映射
-
使用map就可以实现映射。比如:map - x 然后按-就会删除字符
-
:map <space> viw
告诉Vim按下空格的时候选中整个单词 -
:map <c-d> dd
可以使用ctrl + d
执行dd
删除一行 -
:unmap
取消映射 -
可以将
map
命令加到.vimrc
文件中实现持久化
模式映射
Vim常用模式normal/visual/insert都可以定义映射
- 用
nmap/vmap/imap
定义只在normal/visual/insert分别有效 :vmap \ U
把visual模式下选中的文本转换大小写(u/U转换大小写)- 在insert模式下删除一行
:map <c-d> <Esc>ddi
现有映射的问题
定义:nmap - dd
与:nmap \ -
后,当按下\
时,Vim会解析其为-
。我们又映射了-
,Vim会解析-
为dd
,即删除整行(类似于递归)
递归与非递归映射
*map系列命令又递归的风险
- 如果你安装了一个插件,插件映射了同一个按键的不同行为,有冲突就会有一个失效
- 想保证插件映射没有冲突就会非常痛苦
- 解决方案就是使用非递归映射
非递归映射
Vim提供了非递归映射,这些命令不会递归解释
- 使用
*map
对应nnoremap/vnoremap/inoremap
- 何时使用递归映射(
*map
),何时使用非递归映射(*nnoremap
)? - 任何时候都应使用非递归映射,拯救自己和插件作者
Vim中安装和使用插件
什么是插件
和其他现代流行编译器一样,Vim同时支持强大的插件扩展
- Vim插件是使用vimsctipt或者其他语言编写的vim功能扩展
- 编译器自带的功能有限,有了插件之后几乎可以无限制扩充其功能、
- 网络上有很多开源的Vim插件可以使用
如何安装插件
原始的方式是直接clone插件代码,如今vim有很多插件管理器
- 目前Vim有很多插件管理器可供选择,你可以选择一个顺手的
- 常见的有vim-plug,Vundle,Pathogen,Dein.Vim,volt等
- 综合性能、易用性、文档等几个方面,推荐使用vim-plug
使用vim-plug安装插件
我们将使用vim-plug安装我们第一个插件
- github
- 学习一个新东西的最好方式就是看官方文档示例
- 按照官方的教程,我们就可以非常容易地了解他的使用方式
安装vim-startify插件
- github
- 修改
.vimrc
文件,增加该插件名称 - 重新启动Vim或者
source
一下.vimrc
,执行:PlugInstall
如何寻找需要的插件
现有需求,后有插件。大部分插件托管在github上
- 通过Google搜索关键字寻找想要的插件
- 在网站上查找
- 浏览网上开源的Vim配置借鉴想要的插件
Vim美化插件:让你的Vim与众不同
Vim的外观
Vim配色方案
Vim文件目录和搜索插件
默认的文件目录管理比较简陋,nerdtree弥补了这个问题
文件管理器nerdtree
使用nerdtree插件进行文件目录树管理
- github
autocmd vimenter *NERDTree
可以在启动vim的时候打开nnoremap <leader>v :NERDTreeFind<cr>
查找文件位置
模糊搜索器
使用nerdtree并不能快速查找到想要打开的文件,如果想要快速查找打开一个文件可以使用ctrlp插件
- github
let g:ctrlp_map = '<c-p>'
- 使用ctrl+p然后开始输入少量字符就可以搜索了
Vim快速定位插件
Vim移动命令
- w/e基于单词移动,gg/G文件首尾,0/$行首位,f{char}查寻字符
- ctrl+f,ctrl+u前后翻屏
如何快速跳转到当前窗口显示区的任意位置
- 可以使用vim的搜索/加上n跳转,但是使用easymotion更方便
- github
namp ss <Plug>(easymotion-s2)
Vim成对编辑
如果快速让你更换一对单引号为双引号?
- 一个一个查找然后替换,是不是比较低效?
- github
vim-surround使用
normal模式下增加,删除,修改成对内容
ds
(delete a surrounding)cs
(change a surrounding)ys
(you add a surrounding)
Vim模糊搜索和替换插件
模糊搜索
我们经常需要在一个代码项目中模糊搜索一些文本,怎么办呢?
- Vim自带的搜索
/
可以搜索当前文件,但是项目有很多个文件 - 需要一个插件来模糊搜索多个文件内容
- 使用
Ag.vim
或者fzf.vim
都可以很好地支持模糊搜索
fzf与fzf.vim
fzf是一个强大的命令行模糊搜索工具,fzf.Vim果成到了Vim里
- github
- 使用
Ag [PATTERN]
模糊搜索字符串 - 使用
Files [PATH]
模糊搜索目录
搜索替换插件far.vim
如果想要批量搜索替换,可以试试 far.vim
- github
- 比如在重构代码的时候经常会用到
:Far foo bar **/*.py
vim-go插件
编辑器VS IDE
IDE一代又一代,经典的编辑器却长久不衰
- 除了Java,很多人用vim编写shell/php/golang/python/ruby
- 前端很多人使用vscode , sublime/Atom有末落之势
- 很多后端和运维工程师使用vim,微信后台和阿里飞天系统很多代码出自在服务器上使用vim的工程师
vim-go
功能强大的golang 插件vim-go
- github
- 代码补全,重构,跳转,自动格式化,自动导入等功能
- 基本可以满足golang日常开发
python_mode插件
Python-mode
Python 插件使用比较多的是jedi-vim和python-mode
-
python-mode同样具备基本的补全、跳转、重构、格式化功能
-
即使是在服务器上也能愉快调试 python代码了
-
如果遇到了问题,尝试查询python-mode文档解决
Vim tagbar,更愉快的浏览代码
tagbar
代码大纲,Vim当然也有,而且支持非常多编程语言
- github
- 需要安装Universal Ctags 生成对应的tag文件
- 快速浏览当前文件代码结构,并且搜索跳转到对应代码块
vim-interestingwords
高亮你感兴趣的单词,浏览代码很有用
- github
- 浏览代码的时候经常需要知道一个变量的使用方式
- 我们可以使用这个插件同事高亮多个单词
Vim代码补全插件
deoplete.nvim
一个强大的neovim/vim8异步补全插件
- github
- 多编程语言的支持,支持模糊匹配
- 需要安装对应编程语言的扩展
coc.vim
一个强大的neovim/vim8补全插件。LSP支持
- github
- full Language Server Protocol support as VSCode
- 多语言插件支持
Vim代码格式化与静态检查
格式化与静态检查
为什么需要这些工具呢?能让工具做的就不用让人去费心
- 把精力集中代码逻辑本身,而不是整理格式这些浪费精力的事情上
- 静态检查是为了让编写的代码更加规范。golint/pylint/eslint等
- 无论你编写何种编程语言,最好都加上自动格式化和静态检查
Neoformat
vim-autoformat和Neoformat是两种使用较多的格式化插件
- 你可以按照自己的喜好来选择,这里我们使用neoformat
- github
- 需要安装对应语言的格式化库。python autopep8/js的prettier等
静态检查Lint
neomake和ale是两种常用的lint 插件,这里我们选用ale
- github
- 同样需要安装对应语言的lint库。比如eslint/pylint/golint等
- vim8/neovim支持异步检查,不会影响vim编辑,推荐使用
Vim快速注释代码
vim-commentary
vim注释插件有很多,这里使用这个比较轻量的
- github
- 记住常用的命令gc注释和取消注释
- 插件会根据不同的文件类型使用不同注释,python(#) golang(/)
Vim与git结合使用的插件
Fugitive
在Vim里使用Git
- github
- Gedit, Gdiff, Gblame, Gcommit 等
- 笔者更喜欢用tmux新开一个窗口来使用git,后面我们会讲到
vim-gitgutter
在vim里显示文件变动
- github
- 当我们修改文件之后可以显示当前文件的变动
- 哪些行新增,哪些行修改了,哪些行删除了
gv.vim
如何在命令行查看提交记录呢?有个命令行工具叫做tig
- github
- 使用:GV命令调用
- 可以浏览代码提交变更
寻找自己的插件
Vim插件千干万
本章我们介绍了如何安装和使用常见的插件
- Vim插件很多,不可能都全部介绍。学会自己寻找和安装
- 通过搜索引擎google关键词/vimawesome/参考开源配置寻找插件
- 学会阅读插件的Readme 文件和doc里的帮助文件学习插件使用
与时俱进的Vim
Vim与tmux,天作之合
Tmux
强大的终端复用工具。通过brew(mac) apt-get(ubuntu)安装
- 可以复用终端、分屏、托管进程等
- 在服务器上即使退出服务器也不会被kill,托管进程也很方便
- 可以方便地分割屏幕实现多个进程公用屏幕
一个tmux可以包含多个session,一个session可以包含多个window,一个window可以包含多个pane。
实例:
tmux:
session 0:
window 0:
pane 0
pane 1
pane 2
...
window 1
window 2
...
session 1
session 2
...
tmux操作
tmux
:新建一个session,其中包含一个window,window中包含一个pane,pane里打开了一个shell对话框。- 按下
Ctrl + b
后手指松开,然后按%
:将当前pane左右平分成两个pane。 - 按下
Ctrl + b
后手指松开,然后按"
(注意是双引号"):将当前pane上下平分成两个pane。 Ctrl + d
:关闭当前pane;如果当前window的所有pane均已关闭,则自动关闭window;如果当前session的所有window均已关闭,则自动关闭session。- 鼠标点击可以选pane。
- 按下
ctrl + b
后手指松开,然后按方向键:选择相邻的pane。 - 鼠标拖动pane之间的分割线,可以调整分割线的位置。
- 按住
ctrl + b
的同时按方向键,可以调整pane之间分割线的位置。 - 按下
ctrl + b
后手指松开,然后按z
:将当前pane全屏/取消全屏。 - 按下
ctrl + b
后手指松开,然后按d
:挂起当前session。 tmux a
:打开之前挂起的session。- 按下
ctrl + b
后手指松开,然后按s
:选择其它session。- 方向键 —— 上:选择上一项 session/window/pane
- 方向键 —— 下:选择下一项 session/window/pane
- 方向键 —— 右:展开当前项 session/window
- 方向键 —— 左:闭合当前项 session/window
- 按下
Ctrl + b
后手指松开,然后按c:在当前session中创建一个新的window。 - 按下
Ctrl + b
后手指松开,然后按w:选择其他window,操作方法与(12)完全相同。 - 按下
Ctrl + b
后手指松开,然后按PageUp:翻阅当前pane内的内容。 - 鼠标滚轮:翻阅当前pane内的内容。
- 在
tmux
中选中文本时,需要按住shift
键。(仅支持Windows和Linux,不支持Mac,不过该操作并不是必须的,因此影响不大) tmux
中复制/粘贴文本的通用方式:- 按下
Ctrl + b
后松开手指,然后按[ - 用鼠标选中文本,被选中的文本会被自动复制到tmux的剪贴板
- 按下
Ctrl + b
后松开手指,然后按],会将剪贴板中的内容粘贴到光标处
- 按下
让Vim嵌入你的开发工具
几乎流行的编辑器和IDE都支持vim插件,让vim嵌入你的开发工具,甚至chrome都有vimium插件
- 即使你不用vim 作为主力编辑器,依然可以使用它的编辑方式
- 几乎流行的开发工具都支持vim插件,以vim的方式编辑
- 比如Vscode/Atom/Pycharm等都支持安装vim插件
与时俱进的Vim之neovim
Neovim
一个新的vim版本支持异步特性( vim8也支持)
- 官网
- 开发更活跃,更丰富的特性和扩展,异步支持
- neovim的设计可以嵌入到很多GUI里,加上好看的“外壳”
Vim开源配置
如果你已经熟悉了vim配置,可以从网上直接使用一些开源配置
Vim虐我千百遍,我待Vim如初恋
可以用一生的编辑器
Vim从诞生到现在已经走过了快三十个年头
- 几十年之间,无数的编辑器或者开发工具昙花一现
- 但是 vim一直到现在依然很多人在使用,甚至嵌入到各种开发工具
- 如今vim/neovim依然在活跃开发,很多开发者贡献插件
学习方法
熟练vim靠的是肌肉记忆。脱离鼠标编辑能提升编辑效率
- 虽然讲了这么多,vim仍然很多东西没讲到,时不时发现一些技巧
- 在学中练,在练中学。熟能生巧,肌肉记忆
- 衡量投入产出比,是点到为止还是继续深入