Vim 使用笔记
概述
Vim 是一个非常强大的文本编辑器,最初是 vi 编辑器的改进版。Vim 是 Vi IMproved 的缩写。Vim 支持多种编程语言和文件格式,并且可以在几乎所有的操作系统上运行。Linux 下有两大主流的文本编辑器,一个是 Emacs,另一个就是 Vim。Vim 以其强大的功能和灵活的配置选项而闻名,深受程序员和系统管理员的喜爱。
后来出现了 Neovim,Neovim 是 Vim 的一个分支,旨在提供更好的可扩展性和用户体验。Neovim 继承了 Vim 的许多功能,并在此基础上进行改进。Neovim 也常常简称为 nvim
本文将对 vim 的使用进行一些基本的介绍,重点讲述其内置帮助文档而非具体命令配置,具体的命令和配置是我的个人习惯,仅供参考。
需要强调的是,Vim 的学习曲线相对较陡,但一旦掌握,便能极大地提高文本编辑效率。
neovim 新增的功能和改进使其成为一个更现代化的编辑器,但基本的操作和命令与 Vim 保持一致。因此,本文中的许多内容同样适用于 neovim。推荐使用 neovim。
获取帮助
学习 vim 最好的教程是内置的帮助文档。建议使用:help
命令通读下,了解 vim 的帮助系统。注意,前述命令中的冒号是必需的,用于进入命令行模式,后面会具体说明模式这个概念
:help
中的开篇内容很有意思,这里简单说明下:
- 首先一来就告诉了你如何移动光标(Move around),右边还配了个形象的图。
- 然后告诉你如何关闭当前窗口,以及如何退出 vim
- 再然后告诉你如何跳转到特定主题,以及如何跳回来。
- 然后告诉你如何获取特定内容的帮助(使用
:help xxx
),甚至列了个简洁的表格,以说明可以加特定前缀获取特定上下文的帮助(如:help v_u
获取可视模式下u
命令的帮助):
WHAT PREPEND EXAMPLE Normal mode command :help x
Visual mode command v_
:help v_u
Insert mode command i_
:help i_<Esc>
Command-line command :
:help :quit
Command-line editing c_
:help c_<Del>
Vim command argument -
:help -r
Option '
:help 'textwidth'
Regular expression /
:help /[
- 再然后告诉你如何搜索包含特定关键词的帮助
- 最后告诉你如何入门(Getting Started):先做个简单的入门练习(执行
:h tutor
以了解如何使用),然后再看用户手册(User Manual)(:h usr_toc.txt
)。我也在阅读用户手册,目前才阅读完usr_12.txt
,详见 Vim自带帮助文档笔记
温馨提示:如果你发现:h tutor
中描述的:Tutor
命令无法进入教程,那么可能是你的配置或安装的插件关闭了 tutor,请使用nvim --clean
重新启动 nvim 再尝试。
这个开篇写得非常好,建议认真阅读。事实上,这整篇文章非常重要,它提供了所有帮助文件的索引,相当于一个大纲,可以帮助你快速找到需要的帮助。
另外如果你是从 vim 过渡到 nvim,建议阅读:h nvim
配置文件
vim 主要配置文件为~/.vimrc
,该文件格式为 vimscript
,它会在每次启动vim
时执行,通过修改它我们可以修改 vim 的行为。vimscript
中的命令是处于命令行模式下的命令。
需要注意的是,nvim 与 vim 不同,其配置文件为init.vim
或init.lua
(二者选其一)。与 Vim 的 ~/.vimrc
类似,init.vim
也是使用 vimscript
语言编写的。其所在路径根据操作系统的不同而有所不同,详见:h init.vim
。推荐使用init.lua
,因为 Lua 语言比 vimscript 更加现代化和高效,且易于学习和使用。
vim
的配置文件并非只能是一个,它可以在其中包含多个文件,这样可以帮助我们更好地组织配置。例如,我们可以在~/.vimrc
中使用如下命令来包含其他配置文件:
1
source xxx.vim
关于 vimscript 的使用可以参考:h vimscript
,也可参考《Learn Vimscript The Hard Way》。关于这本书我也做了阅读笔记,详见
《Learn Vimscript The Hard Way》学习笔记
如果使用 nvim,且使用配置文件init.lua
,则可以使用如下命令包含其他文件:
1
require('xxx.lua')
关于 nvim 中 lua 语言的使用教程可参考:h lua
。
模式及命令
vim 有七种基本模式和六种额外模式,详见 :h vim-modes
。每种模式下可用的命令不同,这里只说明下四种常用模式:普通模式(Normal Mode)、插入模式(Insert Mode)、命令行模式(Command-line Mode)、可视模式(Visual Mode):
- 普通模式:用得最多的模式,在该模式下,可以使用单字母命令进行移动光标、编辑文本等操作。在任意模式中按
Esc
或Ctrl+[
(可能需要多次)进入普通模式 - 插入模式:输入文本的模式,在该模式下,才能正常像记事本那样输入文本。在普通模式中使用插入相关的命令(如
i
)进入插入模式 - 命令行模式:执行命令的模式,在该模式下,可以执行各种命令,vim 配置文件中通常也执行这种模式下的命令。在普通模式中按
:
进入命令行模式 - 可视模式:选择文本模式,进入此模式后,可以移动光标,在此期间相应的文本会处于选中状态。在普通模式中按
v
或V
(行选择)或Ctrl+V
(列选择)进入选择模式
各种模式切换详见:h mode-switching
下面简单说明下各个模式下的常用命令(个人习惯使用的命令,仅供参考)。
普通模式
普通模式下的常用命令如下:
-
i
a
I
A
: 均用于进入插入模式。i
(insert)在当前字符前插入,a
(append)在当前字符后插入,I
在当前行的第一个字符前插入,A
在当前行的最后一个字符后插入 -
j
k
:j
用于移动到下一行,k
用于移动到上一行 -
h
l
:移动命令。h
向左移动一个字符;l
向右移动一个字符 -
0
^
$
: 移动命令。0
移动到行首;^
和0
类似,只是移动到行首的第一个非空白字符;$
移动到行尾 -
w
e
b
W
E
B
: 移动命令。w
右移一个单词;e
和w
类似,只是停在末尾处;b
左移一个单词;W
移动到下一个空格后的第一个字符;E
和W
类似,只是停在末尾处;B
移动到上一个空格后的第一个字符 -
f
F
t
T
,
;
: 移动命令。f
向后移动至某个字符,如fa
向后移动至a
字符;F
向前移动至某个字符;t
向后移动至某个字符的前一个字符;T
向前移动至某个字符的后一个字符;,
重复上一个和前述命令相同的移动命令;;
和,
类似,不过方向相反 -
c
(Change): 改变文本并进入插入模式。该命令合移动命令使用,如cw
改变一个单词,cb
反向改变一个单词,cl
改变一个字符等等 -
cc
: 改变当前行的所有内容,相当于0c$
-
C
: 改变当前光标所在位置至行尾的内容,相当于c$
-
s
(Substitute):cl
的简写,用于修改一个字符 -
r
(Replace): 和s
类似,只是不会进入插入模式 -
d
(Delete): 删除文本。该命令同样配合移动命令使用 -
dd
: 删除当前行的所有内容,相当于0d$
-
D
: 删除当前光标所在位置至行尾的内容,相当于d$
-
x
:dl
的简写,用于删除一个字符 -
p
P
: 粘贴命令。p
(paste)在当前字符后粘贴,P
在当前字符前粘贴。注意,该命令亦会粘贴已经删除的内容 -
y
(yank): 复制命令。和移动命令配合使用,如yl
复制一个字符,yw
复制一个单词 -
yy
: 复制整行内容。相当于0y$
-
v
: 用于选择,以进入 Visual 模式 -
*
#
: 搜索命令。*
搜索当前单词并跳转到下一处;#
搜索当前单词并跳转到上一处 -
K
: 查询当前单词的帮助。默认查询man
手册(也可以先选择后再查询,即vWK
)。详见 vim 内置帮助文档:h :Man
-
gg
G
: 跳转命令。gg
跳至整个文件的第一行;G
跳到整个文件的最后一行 -
50%
%
: 跳转命令。50%
跳到文件的50%处(即一半的地方,同理,25%
则跳到 1/4 处);%
(即前面不加数字)则完全不同,它用于跳转到当前括号的匹配括号处(如当前是(
,则跳到)
) -
gd
gD
gf
: 跳转命令。gd
跳到当前光标所指局部变量的定义位置;gD
跳到当前光标所指全局变量的定义位置;gf
跳到当前光标所指路径的文件 -
qa一堆操作q
@a
:q
是宏录制命令,qa
表示将宏录制到寄存器a
,宏是操作的集合,可以是任意的 Vim 命令或操作。当你完成录制后,按q
结束录制。要执行这个宏,只需使用@a
命令即可执行寄存器a
中的宏操作 -
@:
: 执行上一个命令行模式命令。这个命令非常有用,可以重复执行上一次的命令,而不需要重新输入 -
ma
'a
: 设置书签。ma
将当前光标位置标记为a
,可以使用'a
跳转到标记a
的位置。这样可以快速跳转到文件中的特定位置,非常实用 -
.
: 重复上一次的修改命令。这个命令非常强大,可以重复执行上一次的编辑操作,非常适合需要多次执行相同操作的场景。 -
u
Ctrl+r
: 撤销和重做命令。u
用于撤销上一次的操作,类似 Windows 下的Ctrl+Z
可以连续撤销多次;Ctrl+r
用于重做撤销的操作,类似 Windows 下的Ctrl+Y
。如果你不小心删除了某些内容,使用u
可以轻松恢复,非常实用 -
=
: 格式化命令。用于格式化选定的文本,使其符合当前的缩进规则。可以在 Visual 模式下选择文本后使用=
进行格式化,非常适合需要调整代码缩进的场景 -
>>
<<
: 缩进命令。>>
用于将当前行或选定的文本向右缩进,<<
用于将当前行或选定的文本向左缩进。这两个命令非常适合需要调整代码缩进的场景,可以帮助你快速整理代码格式 -
Ctrl+c
: 取消当前操作并返回到普通模式。这个命令类似于Esc
,但有时在某些情况下可能更有效,尤其是在处理一些复杂的操作时 -
1<C-g>
:1<C-g>
显示当前文件路径。
插入模式
-
Ctrl+P
: 上一个补全建议。这个命令可以帮助你在插入模式下快速找到之前输入过的内容,非常适合需要频繁输入相似内容的场景 -
Ctrl+N
: 下一个补全建议。这个命令与Ctrl+P
相反,用于在插入模式下查找下一个补全建议,非常适合需要频繁输入相似内容的场景 -
Ctrl+X Ctrl+L
: 补全行。 -
Ctrl+X Ctrl+F
: 补全文件名及路径。这个命令可以帮助你在插入模式下快速补全文件名,非常适合需要频繁输入文件路径的场景 -
<C-r>"
: 输入寄存器内容。在插入模式下,使用<C-r>"
可以将寄存器中的内容插入到当前光标位置,非常适合需要频繁使用寄存器内容的场景 -
Ctrl+W
: 向前清除一个单词 -
Ctrl+U
: 向前清除到行首
命令行模式
-
Ctrl+D
: 显示所有可能的结果 -
Tab
: 按可能的结果依次补全 -
h xxx<CR>
: 查看xxx
的帮助。如下述例子:-
h gd
: 输入h gd
可查看普通模式下gd
命令的帮助 -
h :h
: 输入h :h
可查看命令模式下h
命令的帮助 -
h i_CTRL_N
: 输入h i_CTRL_N
可查看插入模式下Ctrl+N
的帮助 -
h 'nu
: 输入h 'nu
可查看选项nu
的帮助(选项通过命令模式下的set
命令来设置,如set nu
)
-
可视模式
许多在普通模式下可用的命令在可视模式下也可用,但有些命令在可视模式下会有所不同,具体可自行尝试或参见 :h visual-mode
。
LSP
LSP 即 Language Server Protocol(语言服务器协议),它是一种用于编辑器和 IDE 的通信协议,旨在提供语言智能感知功能,如代码补全、错误检查、跳转定义等。通过 LSP,编辑器可以与不同的语言服务器进行通信,从而支持多种编程语言的智能感知功能。
简单来说,LSP 实现了“一个编辑器支持多种编程语言的开发”,而不需要编辑器本身内置对每种语言的支持。这样,编辑器只需实现 LSP 客户端,而语言服务器可以独立于编辑器开发和维护。
语言服务器列表可参见 Language Servers,支持 LSP 的工具/IDE 可参见 Tools supporting the LSP
vim 原生不支持 LSP,nvim 从 0.5 开始原生支持 LSP。对于 nvim 而言,LSP 相关最重要的插件莫过于 neovim/nvim-lspconfig
发行版
vim 的“发行版”是指一组预配置的 Vim 设置、插件和主题,旨在提供开箱即用的编辑体验。这些发行版通常会预先配置许多插件和功能,使用户可以立即开始使用,而无需手动配置每个细节。对于新用户来说,这些发行版可以大大简化 Vim 的入门过程(但个人并不推荐新用户使用,因为遇到问题常常无从下手)。
vim 有很多发行版:
- liuchengxu/space-vim: Lean & mean spacemacs-ish Vim distribution
- amix/vimrc: The ultimate Vim configuration (vimrc)
- …
nvim 有更多:
- nvim-lua/kickstart.nvim: A launch point for your personal nvim configuration:严格来讲,这不是一个发行版,而是一个模板,可以用来快速构建自己的配置。
- NvChad/NvChad: Blazing fast Neovim framework providing solid defaults and a beautiful UI, enhancing your neovim experience.
- LazyVim/LazyVim: Neovim config for the lazy
- LunarVim/LunarVim: 🌙 LunarVim is an IDE layer for Neovim. Completely free and community driven.
- AstroNvim/AstroNvim: AstroNvim is an aesthetic and feature-rich neovim config that is extensible and easy to use with a great set of plugins
- …
需要注意的是,不要沉迷于比较哪个发行版更好,因为每个发行版都有其独特的配置和插件选择,适合不同的用户需求和偏好。最重要的是找到适合自己的配置,并根据自己的需求进行调整和优化。如果你在使用过程中发现无法解决遇到的问题,那么我建议从头开始,如从一些教程或者我前面提到的官方 help 开始,也可参考前面提到的 kickstart.nvim
我当前使用的发行版是 LazyVim,相关的折腾可参见我的另一篇文章 使用 nvim 打造多平台通用的 IDE,在那篇笔记中,我记录了从安装、配置到使用的一些经验和教训。
遇到过的问题
编码问题?
详情参见 VIM 文件编码识别与乱码处理
在 Vim 中,有四个与编码有关的选项,它们是:fileencodings
、fileencoding
、encoding
和 termencoding
。在实际使用中,任何一个选项出现错误,都会导致出现乱码:
-
encoding
: VIM 内部字符编码建议设置:
1
set encoding=utf-8 "这通常是 VIM 的默认值
-
termencoding
: VIM 用于屏幕显示的编码建议设置:
1 2
set termencoding=utf-8 "for Linux set termencoding=gbk/cp936 "for Windows
-
fileencoding
: VIM 探测到的文件的编码建议设置:
1
set fileencoding? "通常不建议设置该选项,除非你确定你知道文件本身正确的编码
-
fileencodings
: VIM 自动识别编码的顺序建议设置:
1
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
以上的fileencodings
选项的建议设置推荐放到~/.vimrc
,避免 VIM 识别不到 GBK(CP936) 编码(这是使用 VIM 最容易遇到的编码错误的原因)。如果 VIM 确实没有识别正确,你也知道文件本身正确的编码,那么你可以使用如下命令以正确的编码重新打开本文件:
1
:e ++enc=gbk
详情参见:h :e
以encoding
为例,简要说下 VIM 中选项的查看值、设置值的方法和获取 VIM 自带帮助的方法:
1
2
3
:set encoding? "查看 VIM 内部字符编码
:set encoding=utf8 "设置 VIM 内部字符编码
:help 'encoding "查看 VIM encoding 选项的相关帮助
另外还可使用如下命令查看文件的编码:
1
2
$ file quicker.em
quicker.em: ISO-8859 text, with CRLF line terminators
不小心按了Ctrl+S
后卡死?
使用Ctrl+Q
或Ctrl+C
即可
在 Vim 脚本中忽略’Pattern not found’错误信息
- 使用
:silent[!]
前缀::h :silent
- 在
:s
替换命令后添加e
选项::h :s_flags
插入模式中从右往左书写
:set ri
详情参见::h 'ri
对齐文本
-
:ri
: 右对齐 -
:ce
: 居中对齐 -
:le
: 左对齐
详情参见::h :ri
删除二进制文件末尾的EOF
?
1
:set binary noendofline
详情参见: Vim show and be able to delete 0x0a at end of file - Stack Overflow
跨多行搜索
将搜索到的所有结果保存到某个寄存器中
1
2
:let @a=''
:%s/func\s*(\_[^;]\{-\};/\=setreg('A', submatch(0)."\n")/ng
详情参见How to store all occurrences of a multiline search in a register? - Vi and Vim Stack Exchange
如何获取当前的行号
vi - Getting the current row number? - Stack Overflow
vim 中如何使用 ctags
首先在 bash 中执行以下命令:
1
ctags -R --fields=+iaS --extra=+q *
命令解释:
-
-R
: 递归处理子目录。 -
–fields=[+|-]flags
:–fields
指定 tags 的可用扩展域(extension fields),以包含到 tags 文件。其中:-
i
: 继承信息Inheritance information -
a
:类成员的访问控制信息 Access (or export) of class members -
S
:常规签名信息,如原型或参数表 Signature of routine(e.g. prototype or parameter list)
-
-
–extra=[+|-]flags
: 指定是否包含某种扩展信息到 tags 文件。-
q
:包含类成员信息(如c++,java,Eiffel)。
-
然后在当前目录中打开 vim 即可使用。
详情参见:h ctags
用过的插件
这里列出一些我用过的插件,仅供参考:
- mattn/emmet-vim: emmet for vim: http://emmet.io/
- Yggdroot/indentLine: A vim plugin to display the indention levels with thin vertical lines
- vim-autoformat/vim-autoformat: Provide easy code formatting in Vim by integrating existing code formatters.
- SirVer/ultisnips: UltiSnips - The ultimate snippet solution for Vim. Send pull requests to SirVer/ultisnips!
- junegunn/vim-plug:
Minimalist Vim Plugin Manager
对于简单的插件,如开箱即用的插件,这里不做进一步说明,反之,会详细介绍。
vim-plug
简介
一个简约的Vim插件管理器。
只有一个文件plug.vim
(不过有 2500+ 行)
安装
在 bash 中使用如下命令即可:
1
2
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
使用
基本使用——安装插件
在你的~/.vimrc
中添加一个vim-plug
部分:
- 使用
call plug#begin()
开始该部分 - 使用
Plug
命令列出插件 - 使用
call plug#end()
结束该部分。使用call plug#end()
后会更新&runtimepath
并初始化插件系统,且会:- 自动执行
filetype plugin indent on
和syntax enable
。您可以在call
后恢复设置。即filetype indent off
,syntax off
等
- 自动执行
如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
" Specify a directory for plugins
" - For Neovim: ~/.local/share/nvim/plugged
" - Avoid using standard Vim directory names like 'plugin'
call plug#begin('~/.vim/plugged')
" Make sure you use single quotes
" Shorthand notation; fetches https://github.com/junegunn/vim-easy-align
Plug 'junegunn/vim-easy-align'
" Any valid git URL is allowed
Plug 'https://github.com/junegunn/vim-github-dashboard.git'
" Multiple Plug commands can be written in a single line using | separators
Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'
" On-demand loading
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
" Using a non-master branch
Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
" Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
Plug 'fatih/vim-go', { 'tag': '*' }
" Plugin options
Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }
" Plugin outside ~/.vim/plugged with post-update hook
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
" Unmanaged plugin (manually installed and updated)
Plug '~/my-prototype-plugin'
" Initialize plugin system
call plug#end()
重新加载~/.vimrc
文件(可以使用:source ~/.vimrc
命令)并使用:PlugInstall
命令来安装插件
其它用法
命令行模式可用的命令
命令 | 描述 |
---|---|
PlugInstall [name ...] [#threads] |
安装插件 |
PlugUpdate [name ...] [#threads] |
安装或更新插件 |
PlugClean[!] |
删除未使用的目录(爆炸版将清除而不提示) |
PlugUpgrade |
更新vim-plug 它自己 |
PlugStatus |
检查插件的状态 |
PlugDiff |
检查当前插件和最新插件的区别 |
PlugSnapshot[!] [output path] |
生成用于还原插件的当前快照的脚本 |
在 Plug 后使用的Plug
选项
选项 | 描述 |
---|---|
branch/tag/commit |
Branch/tag/commit of the repository to use |
rtp |
Subdirectory that contains Vim plugin |
dir |
Custom directory for the plugin |
as |
Use different name for the plugin |
do |
Post-update hook (string or funcref) |
on |
On-demand loading: Commands or <Plug>-mappings
|
for |
On-demand loading: File types |
frozen |
Do not update unless explicitly specified |
可在 .vimrc 文件中使用的全局选项
选项 | 默认值 | 描述 |
---|---|---|
g:plug_threads |
16 |
Default number of threads to use |
g:plug_timeout |
60 |
Time limit of each task in seconds (Ruby & Python) |
g:plug_retries |
2 |
Number of retries in case of timeout (Ruby & Python) |
g:plug_shallow |
1 |
Use shallow clone |
g:plug_window |
vertical topleft new |
Command to open plug window |
g:plug_pwindow |
above 12new |
Command to open preview window in PlugDiff |
g:plug_url_format |
https://git::@github.com/%s.git |
printf format to build repo URL (Only applies to the subsequent Plug commands) |
在:PlugDiff/PlugStatus
窗口中的键绑定
-
D
- PlugDiff -
S
- PlugStatus -
R
- Retry failed update or installation tasks -
U
- Update plugins in the selected range -
q
- Close the window -
:PlugStatus
-
L
- Load plugin
-
-
:PlugDiff
-
X
- Revert the update
-
官方 Tips
https://github.com/junegunn/vim-plug/wiki/tips
vim-table-mode
安装 vim-table-mode
使用Vim-Plug 安装:
-
在Vim配置文件(
~/.vimrc
)中的相应位置(call plug#begin('~/.vim/bundle')
后)添加如下内容:1
Plug 'dhruvasagar/vim-table-mode', { 'for': 'markdown'}
-
打开 Vim,输入
:PlugInstall
完成安装即可
关于Vim-Plug 的使用可以参考 Vim管理插件的插件Vim-Plug
使用 vim-table-mode
按键 | 助记单词 | 功能 |
---|---|---|
\t |
table | 该插件前缀 |
\T |
tableize | 将内容转换为表格 |
\tm |
table mode | 开启或关闭table mode |
\tr |
table realign | 重新对齐表的每一列 |
\t? |
显示用于定义公式的当前单元格的表示 | |
\tdd |
table dd | 删除某一行 |
\tdc |
table delete column | 删除当前列 |
\tfa |
table formula add | 添加公式 |
\tfe |
table formula evaluate | 计算公式 |
\ts |
table sort | 对某一列排序 |
| |
输入表的单元格 | |
|| |
输入表头(表的第一行) | |
[| |
移动到左边的单元格 | |
]| |
移动到右边的单元格 | |
{| |
移动到上面的单元格 | |
}| |
移动到下面的单元格 |
vim-autoformat
通用配置
编辑~/.vimrc
如下(仅供参考):
1
2
3
4
5
6
7
8
let g:autoformat_verbosemode=1 "开启详细模式便于查错
autocmd BufWrite *.sql,*.c,*.py,*.java,*.js :Autoformat "设置发生保存事件时执行格式化
"let g:autoformat_autoindent = 0
"let g:autoformat_retab = 0
"let g:autoformat_remove_trailing_spaces = 0
"autocmd FileType vim,tex let b:autoformat_autoindent=0
"gg=G :retab :RemoveTrailingSpaces
详情参见 Chiel92/vim-autoformat#how-to-use
clang-format
官网:http://clang.llvm.org/docs/ClangFormat.html
因为clang-format
是clang
的一部分,所以直接安装clang
是最简单的方法(以 CentOS 系统为例)
1
yum install clang
在~/.vimrc
中做如下配置即可:
1
2
let g:formatdef_clangformat_google = '"clang-format -style google -"' # 我比较喜欢 google 风格的代码
let g:formatters_c = ['clangformat_google']
此后使用 Vim 编辑 C 源文件时,使用:Autoformat
即可格式化代码。
关于clang-format
的高级使用(如自定义风格等)可参考 Clang-Format格式化选项介绍
亦可参考官网教程:ClangFormat — Clang 13 documentation
autopep8
GitHub 项目地址:https://github.com/hhatto/autopep8
autopep8
是使用 Python 语言写的,可以直接使用pip
安装:
1
pip install autopep8
它似乎不需要配置,可能是因为vim-autoformat
能自动识别Python
语言的特点
sqlformat
GitHub 项目地址:https://github.com/andialbrecht/sqlparse。注意sqlformat
是sqlparse
的一部分
安装 sqlformat
如前所述,sqlformat
是sqlparse
(一个 Python 模块)的一部分,所以只需安装sqlparse
即可:
1
pip install sqlparse
配置
在~/.vimrc
中进行如下配置(和clang-format
类似):
1
2
let g:formatdef_sqlformat = '"sqlformat --keywords upper -"'
let g:formatters_sql = ['sqlformat']
此后使用 Vim 编辑 SQL 文件,每当执行:Autoformat
命令都会使用sqlformat
这个外部程序格式化代码
遇到的问题
虽然这个插件(sqlparse
)官方说既支持 Python2 ,也支持 Python3 ,但是当我使用 Python2 安装后格式化代码(即在 Vim 中运行:Autoformat
命令,另外代码中有中文)时出现了如下错误:
Trying definition from g:formatdef_mysql
Evaluated formatprg: sqlformat --keywords upper -
Using python 2 code...
Formatter mysql has errors: Traceback (most recent call last):
File "/root/.pyenv/versions/2.7.15/bin/sqlformat", line 11, in <module>
sys.exit(main())
File "/root/.pyenv/versions/2.7.15/lib/python2.7/site-packages/sqlparse/cli.py", line 180, in main
stream.write(s)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 100-101: ordinal not in range(128)
Python3 默认使用 UTF-8,应该不会出现此错误,所以这可能是个 BUG (2018-11-25)。我的解决方法如下:
根据错误提示将/root/.pyenv/versions/2.7.15/lib/python2.7/site-packages/sqlparse/cli.py
文件中的第 180 行stream.write(s)
改为stream.write(s.encode('utf8'))
总的配置文件
综上,可以格式化 C 语言、Python 语言、SQL 语言的配置文件如下(仅供参考):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"for vim-autoformat
"let g:autoformat_verbosemode=1
"autocmd BufWrite *.sql,*.c,*.py,*.java,*.js :Autoformat
noremap <F3> :Autoformat<CR>
"let g:autoformat_autoindent = 0
"let g:autoformat_retab = 0
"let g:autoformat_remove_trailing_spaces = 0
"autocmd FileType vim,tex let b:autoformat_autoindent=0
"gg=G :retab :RemoveTrailingSpaces
let g:formatdef_sqlformat = '"sqlformat --keywords upper -"'
let g:formatters_sql = ['sqlformat']
let g:formatdef_clangformat_google = '"clang-format -style google -"'
let g:formatters_c = ['clangformat_google']
其中,由于发现保存文件时自动格式化是个危险的操作,所以改为了绑定快捷键<F3>
。
YouCompleteMe
0 简介
YouCompleteMe is a fast, as-you-type, fuzzy-search code completion engine for Vim. It has several completion engines:
- an identifier-based engine that works with every programming language,
- a Clang-based engine that provides native semantic code completion for C/C++/Objective-C/Objective-C++/CUDA (from now on referred to as “the C-family languages”),
- a Jedi-based completion engine for Python 2 and 3,
- an OmniSharp-based completion engine for C#,
- a combination of Gocode and Godef semantic engines for Go,
- a TSServer-based completion engine for JavaScript and TypeScript,
- a racer-based completion engine for Rust,
- a jdt.ls-based experimental completion engine for Java.
- and an omnifunc-based completer that uses data from Vim’s omnicomplete system to provide semantic completions for many other languages (Ruby, PHP etc.).
总之,YouCompleteMe 是目前(2018-11-26)最强大的代码补全插件(但同时也是最难安装的插件)
1 安装 Python
使用 pyenv
(Simple Python version management)进行安装
-
安装
pyenv
1 2 3 4 5
git clone https://github.com/pyenv/pyenv.git ~/.pyenv echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bashrc . ~/.bashrc
-
安装编译
CPython
(即最流行的Python
)需要使用的依赖,因为pyenv
要用:1
yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel
-
使之后
Python
的编译拥有动态库(dynamic library),因为后面需要:1
echo 'export PYTHON_CONFIGURE_OPTS="--enable-shared"' >> ~/.bashrc
-
安装一个
Python
版本(如2.7.15
):1
pyenv install 2.7.15
2 安装 Vim
-
安装编译
Vim
需要的依赖:1 2 3 4 5
sudo yum install -y ruby ruby-devel lua lua-devel luajit \ luajit-devel ctags git \ tcl-devel perl perl-devel perl-ExtUtils-ParseXS \ perl-ExtUtils-XSpp perl-ExtUtils-CBuilder \ perl-ExtUtils-Embed
-
移除已经安装的
Vim
:1
apt remove vim vim-runtime gvim
-
安装
Vim
:1 2 3 4 5 6 7 8 9 10 11 12 13
cd ~ git clone https://github.com/vim/vim.git cd vim/src ./configure --with-features=huge \ --enable-multibyte \ --enable-pythoninterp=yes \ --with-python-config-dir=/root/.pyenv/versions/2.7.15/lib/python2.7/config/ \ #通过 `find ~/.pyenv -name "config"` 获取该目录 --enable-luainterp=yes \ --enable-cscope \ --prefix=/usr/local make VIMRUNTIMEDIR=/usr/local/share/vim/vim81 make install
-
验证安装,确认Vim已带有python支持:
1
vim --version
注:如果失败了可以使用make uninstall
卸载找到原因后重来(我重来了好几次,因为系统自带的Python2.7.5
好像不行,所以我才使用Python
的版本管理工具pyenv
安装了Python2.7.15
,之所以没直接卸载系统自带的Python2.7.5
是因为我卸载不掉,它说它被很多其他软件依赖)
3 通过安装 vim-plug 安装 YouCompleteMe
-
往
~/.vimrc
中添加如下配置:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
if empty(glob('~/.vim/autoload/plug.vim')) silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim autocmd VimEnter * PlugInstall --sync | source $MYVIMRC endif call plug#begin('~/.vim/bundle') Plug 'junegunn/vim-plug' Plug 'Raimondi/delimitMate' " Plug 'yianwillis/vimcdoc' " Plug 'vim-scripts/VimIM' Plug 'mzlogin/vim-markdown-toc' Plug 'dhruvasagar/vim-table-mode' Plug 'ervandew/supertab' Plug 'mattn/emmet-vim' Plug 'Valloric/YouCompleteMe' # { 'do': './install.py --clang-completer --java-completer' } call plug#end()
-
进入Vim后输入
:PlugInstall
安装各种插件(包括YouCompleteMe
)。其实这个时候并没有成功安装YouCompleteMe
,只是把YouCompleteMe
的git
源克隆到了~/.vim/bundle
目录
4 安装并配置 YouCompleteMe
4.1 安装 YouCompleteMe
-
编译并安装YouCompleteMe(建议先让终端科学上网后再编译安装,否则极有可能会出现下述问题中的第二个问题,且其解决方案似乎已经失效,2018-11-28):
1 2 3
cd ~/.vim/bundle/YouCompleteMe/ python install.py --clang-completer --java-completer #可在此添加加的语言支持有C(--clang-completer), C#(--cs-completer), Go(--go-completer), Rust(--rust-completer), Java(--java-completer)
以上步骤的可能遇到的问题
-
如果在
git submodule update --init --recursive
这一步(隐含在python install.py --clang-completer --java-completer
中)中发现下载很慢,则可以参考我的另一篇博客Kali Linux科学上网配置好git部分后再下载。 -
如果在:
-- Downloading libclang 7.0.0 from https://dl.bintray.com/micbou/libclang/libclang-7.0.0-x86_64-unknown-linux-gnu.tar.bz2
这一步中卡住了
或者等待很长时间后错误如下(
--clang-completer
参数导致的问题):CMake Error at ycm/CMakeLists.txt:103 (file): file DOWNLOAD HASH mismatch for file: [/home/up_ding/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/../clang_archives/clang+llvm-3.7.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz] expected hash: [093a94ff8982ae78461f0d2604c98f6b454c15e2ef768d34c235c6676c336460] actual hash: [a12a54f4e937e521a5e9ff790db0bf7a358f6dbc6febebcddab62c798ffc4d51]
则可以手动下载 Clang archive(复制那个下载链接即可,记得要科学上网后再下载), 然后将它移动至
~/.vim/bundle/YouCompleteMe/third_party/ycmd/clang_archives
目录下,然后重新安装YouCompleteMe(即运行上面那个python intall.py……
命令),具体可参考https://github.com/Valloric/YouCompleteMe/issues/1711
-
-
编译YCM需要的
ycm_core
库:1 2 3 4
mkdir ~/.ycm_build cd ~/.ycm_build cmake -G "Unix Makefiles" -DEXTERNAL_LIBCLANG_PATH=/root/.vim/bundle/YouCompleteMe/third_party/ycmd/libclang.so.6.0 . ~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp cmake --build . --target ycm_core
-
(可选)为改善Unicode支持和更好的正则表达式性能构建正则表达式模块:
1 2 3 4 5
cd ~ mkdir .regex_build cd .regex_build cmake -G "Unix Makefiles" . ~/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/cregex cmake --build . --target _regex --config Release
-
Vim
配置(仅供参考):1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
" for ycm" let g:ycm_min_num_identifier_candidate_chars = 4 let g:ycm_min_num_of_chars_for_completion = 2 "set 99 to turn off identifiers completer" let g:ycm_max_num_identifier_candidates = 10 "identifier completion" let g:ycm_max_num_candidates = 30 "semantic completion" let g:ycm_auto_trigger = 1 let g:ycm_key_list_stop_completion = ['<C-y>'] let g:ycm_server_python_interpreter='/root/.pyenv/shims/python' let g:ycm_global_ycm_extra_conf='~/.vim/.ycm_extra_conf.py' "used for c-family language" let g:ycm_error_symbol = '>>' let g:ycm_warning_symbol = '>*' let g:ycm_key_invoke_completion = '<c-l>' nnoremap <leader>gl :YcmCompleter GoToDeclaration<CR> nnoremap <leader>gf :YcmCompleter GoToDefinition<CR> nnoremap <leader>gg :YcmCompleter GoToDefinitionElseDeclaration<CR> nmap <F4> :YcmDiags<CR>
4.2 配置 C 支持
-
复制并修改
.ycm_extra_conf.py
文件:1
cp ~/.vim/bundle/YouCompleteMe/third_party/ycmd/examples/.ycm_extra_conf.py ~/.vim/
-
然后在
~/.vimrc
中设置g:ycm_global_ycm_extra_conf
变量:1
let g:ycm_global_ycm_extra_conf='~/.vim/.ycm_extra_conf.py' "used for c-family language"
4.3 配置 JavaScript 支持
- 安装 TSServer 引擎(通过安装TypeScript SDK):
-
安装
nvm
(node version manager,安装它后再安装各种版本的node.js就非常简单了,因为后面要用到npm
):1
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
根据提示将如下内容添加至
~/.bashrc
:1 2 3 4
# node version manager export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
退出并重进终端(或者使用
source ~/.bashrc
命令),然后使用nvm --help
以确认是否安装成功 -
安装最新稳定版的node.js(会自动安装npm):
1
nvm install stable
-
安装
TypeScript SDK
:1
npm install -g typescript
-
-
(可选)为了获得语法检查的功能,可以在工程目录中的
jsconfig.json
文件里设置checkJs
选项:1 2 3 4 5
{ "compilerOptions": { "checkJs": true } }
5 使用
参见:h youcompleteme-commands
及:h youcompleteme-ycmcompleter-subcommands
5.1 通用
- Commands
youcompleteme-commands
- The
:YcmRestartServer
command - The
:YcmForceCompileAndDiagnostics
command - The
:YcmDiags
command - The
:YcmShowDetailedDiagnostic
command - The
:YcmDebugInfo
command - The
:YcmToggleLogs
command - The
:YcmCompleter
command
- The
- YcmCompleter Subcommands
youcompleteme-ycmcompleter-subcommands
- GoTo Commands
youcompleteme-goto-commands
- The
GoToInclude
subcommand - The
GoToDeclaration
subcommand - The
GoToDefinition
subcommand - The
GoTo
subcommand - The
GoToImprecise
subcommand - The
GoToReferences
subcommand - The
GoToImplementation
subcommand - The
GoToImplementationElseDeclaration
subcommand - The
GoToType
subcommand
- The
- Semantic Information Commands
youcompleteme-semantic-information-commands
- The
GetType
subcommand - The
GetTypeImprecise
subcommand - The
GetParent
subcommand - The
GetDoc
subcommand - The
GetDocImprecise
subcommand
- The
- Refactoring Commands
youcompleteme-refactoring-commands
- The
FixIt
subcommand - The
RefactorRename <new name>
subcommandRefactorRename-new-name
- Multi-file Refactor
youcompleteme-multi-file-refactor
- The
Format
subcommand - The
OrganizeImports
subcommand
- The
- Miscellaneous Commands
youcompleteme-miscellaneous-commands
- The
RestartServer
subcommand - The
ClearCompilationFlagCache
subcommand - The
ReloadSolution
subcommand
- The
- GoTo Commands
关于它们的用法请参见:h :<命令名>
,如:h :YcmRestartServer
输入字符超过2个,即会出现补全菜单,主要支持本文档内的补全(注释中的不会用于补全,如想补全注释中的内容,可以使用Ctrl+N和Ctrl+P)、语义补全(根据编程语言自动解析补全,精准度很高)、代码片断补全(和 vim-snippets 配合使用)
-
Ctrl+N
和Ctrl+P
:出现补全菜单后,使用Ctrl+N
向下选择(也可以使用Tab
),使用Ctrl+P
向上选择 -
\gd
(GetDoc):获取光标所在单词的帮助文档(主要是它的API) -
\gr
(GoToReferences):获取引用光标所在单词的所有位置 -
\gg
(GoTo): 先尝试跳转至声明处,若失败,则跳转至定义处 -
Ctrl+L
: 强制补全 -
Ctrl+Y
:在补全菜单出现时可以使用该快捷键关闭补全菜单(有时很有用)
5.2 C语言
normal | cmdline(:YcmCompleter <subcmd> ) |
Description | 备注 |
---|---|---|---|
\gi |
GoToInclude |
Looks up the current line for a header and jumps to it. | 和 Vim 自带的gf 命令类似 |
\gc |
GoToDeclaration |
Looks up the symbol under the cursor and jumps to its declaration. | 和 Vim 自带的gd 命令类似 |
\gf |
GoToDefinition |
Looks up the symbol under the cursor and jumps to its definition. | |
\gg |
GoTo |
Auto select from above | |
\gt |
GetType |
Echos the type of the variable or method under the cursor | |
\gp |
GetParent |
Echos the semantic parent of the point under the cursor. | |
\gd |
GetDoc |
Displays the preview window populated with quick info about the identifier under the cursor. | 可以使用K 或\K 命令查看man 手册,详情参见:h :Man
|
注意,上述命令需要配置文件~/.vimrc
如下:
1
2
3
4
5
6
7
nnoremap <leader>gi :YcmCompleter GoToInclude<CR>
nnoremap <leader>gc :YcmCompleter GoToDeclaration<CR>
nnoremap <leader>gf :YcmCompleter GoToDefinition<CR>
nnoremap <leader>gg :YcmCompleter GoTo<CR>
nnoremap <leader>gt :YcmCompleter GetType<CR>
nnoremap <leader>gp :YcmCompleter GetParent<CR>
nnoremap <leader>gd :YcmCompleter GetDoc<CR>
且其中的<leader>
没有被修改过,即为默认的\
。详情参见:h <leader>
6 参考链接
- Building-Vim-from-source
- vim-plug
- Why I choose vim-plug
- YouCompleteMe#linux-64-bit
- YouCompleteMe#full-installation-guide
- 一步一步带你安装史上最难安装的 vim 插件 —— YouCompleteMe