从零开始搭建你的nvim ide
前言概述
vim由于其丰富的扩展性、出色的跨平台性、高效率的操作性深受一大批粉丝的追捧,甚至就连vim和emacs之间孰优孰劣的话题都能被引起一场编辑器之间的圣战,足以见vim是多么的优秀。
vim的灵魂在于高定制性,高可玩性,一个原生的vim没有任何插件加持的情况下还是非常难以上手的,但是我们可以通过一些插件的点缀让它变得熠熠生辉,甚至可以配置出一个只属于自己的IDE。
- 在观看本章节前,你应该熟悉vim的基本操作
- 此外,还应当对vim的插件化管理vim-plug有所了解
- 可参照之前的文章
vimcdoc 中文文档
vimcdoc提供了vim的中文文档,安装该插件后在命令模式中输入:help即可获取vim中文文档。
我们只需要把下面这一行放~/.config/nvim/init.vim文件中的call begin和call end之间即可:
Plug 'yianwillis/vimcdoc'
然后使用vim-plug进行下载,在vim命令模式中输入:PlugInstall,后续的插件安装我们将省略这一步骤:
:PlugInstall
效果如下:
indentLine 可视缩进
indentLine提供一个可视化的缩进服务(仅支持空格缩进):
" 可视化缩进
Plug 'Yggdroot/indentLine'
效果如下:
vim-monokai 主题配色
vim-monokai是我最喜欢的一款代码主题,之前在vscode上我也一直使用monokai主题:
" monokai主题
Plug 'crusoexia/vim-monokai'
然后需要再加上下面一行配置:
" 开启语法高亮
syntax on
" 主题选用monokai
colorscheme monokai
效果如下:
vim-airline 状态标签
vim-airline为vim提供了一个非常好看的状态栏以及标签栏:
" 加载vim-airline
Plug 'vim-airline/vim-airline'
" 使用的主题
Plug 'vim-airline/vim-airline-themes'
还需要做一些样式与按键上的调整:
" 关于标签栏的样式
" -- 启用标签栏
let g:airline#extensions#tabline#enabled = 1
" -- 设置标签栏分隔符
let g:airline#extensions#tabline#left_sep = ' '
let g:airline#extensions#tabline#left_alt_sep = '|'
" -- 设置标签栏格式
let g:airline#extensions#tabline#formatter = 'default'
" -- 设置标签栏样式
let g:airline_theme = 'desertink'
"-- 快捷键e切换到前一个标签
nmap e <Plug>AirlineSelectPrevTab
"-- 快捷键E切换到后一个标签
nmap E <Plug>AirlineSelectNextTab
效果如下:
nerdtree 资源管理
nerdtree为vim提供了一个文件资源管理器,我们可以通过h、j、k、l来进行文件的选择:
" nerdtree支持
Plug 'preservim/nerdtree'
" 显示nredtree中文件和目录的Git状态标志
Plug 'Xuyuanp/nerdtree-git-plugin'
" 支持nredtree中文件和目录的图标
Plug 'ryanoasis/vim-devicons'
" 支持高亮显示nredtree中的图标
Plug 'tiagofumo/vim-nerdtree-syntax-highlight'
默认的nerdtree是没有任何文件图标的,若想添加图标,请访问nerd-fonts下载字体图标。
需要按照不同的操作系统进行阅读自述文件,下面以MAC平台为例。
我们可以直接找到Droid Sans Mono Nerd这个字体,然后选择下载Droid Sans Mono Nerd Font Complete.otf,下载完成后双击即可安装字体。
安装字体完成后需要将Terminal的字体调整为Droid Sans Mono Nerd,下面是ITerm的设置:
接下来我们对nerdtree做一些基本的设置:
" nerdtree配置
" -- 为打开或关闭nerdtree设置一个快捷键
nnoremap 1 :NERDTreeToggle<CR>
" -- 自动开启nerdtree
autocmd vimenter * NERDTree
" -- 设定nerdtree的窗口大小
let g:NERDTreeWinSize = 25
" -- 打开nerdtree时自动显示bookmarks
let NERDTreeShowBookmarks=1
" -- 打开nvim时若没有任何文件,则自动打开nerdtree
autocmd vimenter * if !argc()|NERDTree|endif
" -- 当nerdtree为唯一视窗时,自动关闭
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
" -- 每次打开一个新的标签,都默认打开nerdtree
autocmd BufWinEnter * if getcmdwintype() == '' | silent NERDTreeMirror | endif
" -- 设置树的图标,以区分已打开或未打开
let g:NERDTreeDirArrowExpandable = '▸'
let g:NERDTreeDirArrowCollapsible = '▾'
" -- 是否显示行号
let g:NERDTreeShowLineNumbers=0
" -- 是否显示隐藏文件
let g:NERDTreeHidden=0
" -- 让nerdtree更漂亮
let NERDTreeMinimalUI = 1
let NERDTreeDirArrows = 1
" -- 过滤不显示的文件
let NERDTreeIgnore=['\.pyc','\~$','\.swp']
" -- nerdtree的git文件状设置
let g:NERDTreeGitStatusIndicatorMapCustom = {
\ 'Modified' :'✹',
\ 'Staged' :'✚',
\ 'Untracked' :'✭',
\ 'Renamed' :'➜',
\ 'Unmerged' :'═',
\ 'Deleted' :'✖',
\ 'Dirty' :'✗',
\ 'Ignored' :'☒',
\ 'Clean' :'✔︎',
\ 'Unknown' :'?',
\ }
" -- 为不同的文件进行不同的高亮上色
let s:brown = "905532"
let s:aqua = "3AFFDB"
let s:blue = "689FB6"
let s:darkBlue = "44788E"
let s:purple = "834F79"
let s:lightPurple = "834F79"
let s:red = "AE403F"
let s:beige = "F5C06F"
let s:yellow = "F09F17"
let s:orange = "D4843E"
let s:darkOrange = "F16529"
let s:pink = "CB6F6F"
let s:salmon = "EE6E73"
let s:green = "8FAA54"
let s:lightGreen = "31B53E"
let s:white = "FFFFFF"
let s:rspec_red = 'FE405F'
let s:git_orange = 'F54D27'
let g:NERDTreeExtensionHighlightColor = {} " this line is needed to avoid error
let g:NERDTreeExtensionHighlightColor['css'] = s:blue " sets the color of css files to blue
let g:NERDTreeExactMatchHighlightColor = {} " this line is needed to avoid error
let g:NERDTreeExactMatchHighlightColor['.gitignore'] = s:git_orange " sets the color for .gitignore files
let g:NERDTreePatternMatchHighlightColor = {} " this line is needed to avoid error
let g:NERDTreePatternMatchHighlightColor['.*_spec\.rb$'] = s:rspec_red " sets the color for files ending with _spec.rb
let g:WebDevIconsDefaultFolderSymbolColor = s:beige " sets the color for folders that did not match any rule
let g:WebDevIconsDefaultFileSymbolColor = s:blue " sets the color for files that did not match any rule
下面是nerdtree的一些操作方式:
?:获取帮助文档
h、j、k、l:移动方式
t:以tab形式打开文件,并将光标移动至打开的文件中
T:以tab形式打开文件,不将光标移动至打开的文件中
o:以buffer形式打开文件,并将光标移动至打开的文件中
O:以tab形式打开文件,不将光标移动至打开的文件中
e:以文件管理的方式打开选中的目录
q:关闭nerdtree
r:刷新nerdtree
m:增删改查子项目
效果如下:
caw.vim 自动注释
关于注释插件的选择,推荐caw.vim。
尽管网上有很多人都在推荐nerdcommenter这款注释插件,但我断言caw.vim比nerdcommenter更加优秀。
nredcommenter是根据文件类型来进行注释的,也就是说它无法做到单文件多语言的注释风格切换。
而caw.vim则是根据当前光标所在区域内容来自动切换语言注释风格,这依赖于context_filetype插件。
举一个简单的例子,在编写vim时我们会出现<template>、<script>、以及<style>等标签,这种情况下nredcommenter的注释总是//,而使用caw.vim,你在不同的标签区域内能就获得不同的注释方式,这是我选择它最关键的一点:
" 根据内容自动获取文件类型
Plug 'Shougo/context_filetype.vim'
" 自动进行注释
Plug 'tyru/caw.vim'
它的使用方式也非常简单,gcc即是注释、取消注释的快捷键。
由于我平常喜欢使用ctrl+/进行注释,所以这里修改一下它的映射:
" caw.vim注释快捷键修改
" -- ctrl+/设置为打开、关闭注释
" 注意!Unix操作系统中的ctrl+/会被认为是ctrl+_,所以下面有这样一条if判断
if has('win32')
nmap <C-/> gcc
vmap <C-/> gcc
else
nmap <C-_> gcc
vmap <C-_> gcc
endif
auto-pairs 括号补全
默认的vim中当你输入诸如{}、()、""、''等成对字符时,它是不会帮你进行补全的,因此我们需要使用auto-pairs来进行自动补全。
" 自动填充成对出现的符号
Plug 'jiangmiao/auto-pairs'
rainbow 括号高亮
默认的vim中当你选择上诸如{}、()等成对字符时,它是不会进行高亮显示另一半字符的,因此我们需要使用rainbow来进行高亮显示。
" 自动高亮成对出现的符号
Plug 'luochen1990/rainbow'
此外还需要做一些额外的配置项:
rainbow设置
" -- 开启rainbow
let g:rainbow_active = 0
" -- 解决与nerdtree/vim-devicons冲突的问题
let g:rainbow_conf = {
\ 'separately': {
\ 'nerdtree': 0,
\ }
\}
" -- rainbow匹配成对符号的颜色设置
let g:rainbow_conf = {
\ 'guifgs': ['darkorange3', 'seagreen3', 'royalblue3', 'firebrick'],
\ 'ctermfgs': ['lightyellow', 'lightcyan','lightblue', 'lightmagenta'],
\ 'operators': '_,_',
\ 'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'],
\ 'separately': {
\ '*': {},
\ 'tex': {
\ 'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/'],
\ },
\ 'lisp': {
\ 'guifgs': ['darkorange3', 'seagreen3', 'royalblue3', 'firebrick'],
\ },
\ 'vim': {
\ 'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/', 'start=/{/ end=/}/ fold', 'start=/(/ end=/)/ containedin=vimFuncBody', 'start=/\[/ end=/\]/ containedin=vimFuncBody', 'start=/{/ end=/}/ fold containedin=vimFuncBody'],
\ },
\ 'html': {
\ 'parentheses': ['start=/\v\<((area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)[ >])@!\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'|[^ '."'".'"><=`]*))?)*\>/ end=#</\z1># fold'],
\ },
\ 'css': 0,
\ }
\}
vim-easymotion 快速跳转
vim-easymotion为vim提供了快速查找并跳转到某个字符的功能。
" 快速跳转
Plug 'easymotion/vim-easymotion'
你只需要按下:
# 全局定位某个字符
<leader><leader>s<char>
即可完成搜索。当搜索完成后它会对搜索的字符进行高亮,此时只需按下高亮后的快捷键即可跳转到该字符上。
我们可以将它定义成快捷键ctrl+f:
" easymotion设置
" --将全局搜索修改成ctrl+f
nmap <C-f> <Plug>(easymotion-s)
其他的操作,可自行进行映射:
# 定位移动j、k、h、l
<leader><leader>j
# 跳转到前一个词上
<leader><leader>b
# 跳转到后一个词上
<leader><leader>w
# 重复上一动作
<leader><leader>.
vim-surround 包裹修改
vim-surround插件非常的方便,如果你想修改、或者删除单引号和双引号,它带给你的体验将是无与伦比的。
Plug 'tpope/vim-surround'
以下是它的语法:
ds<existing>
cs<existing><desired>
示例如下:
# 删除以下的[]
[1, 2, 3] -> ds[
# 将以下的[]修改为()
[1, 2, 3] -> cs[(
tagbar 大纲预览
tagbar为vim提供了当前文件下的类、函数预览功能。它依赖于ctags,所以我们需要先下载ctags。
$ wget http://prdownloads.sourceforge.net/ctags/ctags-5.8.tar.gz
$ tar -xvf ctags-5.8.tar.gz
$ cd ctags-5.8
$ ./configure --prefix=/usr/local/application
$ make -j
$ make install # 安装到完成后会在指定路径下创建一个bin目录
$ rm -rf ctags-5.8
$ rm -rf ctags-5.8.tar.gz
然后把安装路径添加到环境变量中,我目前使用的是bash,所以直接添加到/etc/profile里即可:
PATH=/usr/local/application/bin:$PATH
source /etc/profile
在终端输入ctags,如出现以下字样则按照成功:
ctags: No files specified. Try "ctags --help".
接下来我们就要安装tagbar了:
Plug 'majutsushi/tagbar'
下面再设置一下按键和tagbar的宽度就搞定了:
let g:tagbar_width=30
nnoremap 3 <F4> :TagbarToggle<CR>
效果图示:
SimpyFold 代码折叠
SimpyFold是一款非常好用的代码折叠工具,使用它能够让我们编辑代码时逻辑结果更加清楚。
" 代码折叠
Plug 'tmhedberg/simpylfold'
然后添加一些额外的配置:
" 自动按照缩进进行代码折叠
set foldmethod=indent
" 启用预览被折叠的代码
let g:SimpylFold_docstring_preview = 1
使用这个插件非常简单,你只需要遵循vim自带的代码折叠机制即可:
- zf:创建折叠
- zo:打开折叠
- zc:关闭折叠
- zR:打开所有
- zM:关闭所有
- zj:移动到下一个折叠
- zk:移动到上一个折叠
coc.nvim 智能补全
coc.nvim是只有nvim才能使用的智能补全插件平台。
了解它之前我们我们必须了解它的模式,它本身仅是一个平台,类似于vim-plug,我们可以在coc.nvim中安装很多我们需要的其他coc插件。
首先,coc.nvim必须基于Node.Js,所以请确保你的机器上安装了Node.js,如果没有安装或者你根本不知道Node.Js是啥,可以直接运行下面这段代码:
$ curl -sL install-node.now.sh/lts | bash
然后我们就需要使用vim-plug装上coc.nvim平台了:
" coc智能代码补全平台
Plug 'neoclide/coc.nvim', {'branch': 'release'}
安装完成之后,还需要使用npm安装一些2个东西:
$ npm install -g neovim yarn
此外,coc平台插件还需要依赖Python,所以我们需要在Python中安装neovim:
$ pip3 install neovim
$ pip2 install neovim
最后一步,必须让vim关联上Python,所以在init.vim配置文件中你需要设置:
" coc配置pythonx
if has('python3')
set pyx=3
elseif has('python2')
set pyx=2
endif
现在让我们打开vim,并在命令模式下执行:checkhealth命令,检查是否安装成功:
:checkhealth
主要查看health#nvim#check下面的这3个选项是否是ok,一般情况下只要按照上述步骤做了就没什么问题:
下面添加一些coc的配置项:
" 允许未保存文件时跳转文件
set hidden
" 增加响应
set updatetime=100
" 让弹窗栏更加简洁
set shortmess+=c
" 让我们的tab作为切换扩展的按键
inoremap <silent><expr> <TAB>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" 按下ctrl+space键跳出或关闭自动补全
if has('nvim')
inoremap <silent><expr> <c-space> coc#refresh()
else
inoremap <silent><expr> <c-@> coc#refresh()
endif
" 当使用enter键作为补全选择时,它将不会自动切换到下一行
inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
" 使用[g或者]g来查找上一个或者下一个代码报错
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
" 使用gd来跳转到函数定义处、gy获取类型定义,
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" 通过gh来显示文档
nnoremap gh :call <SID>show_documentation()<CR>
function! s:show_documentation()
if (index(['vim','help'], &filetype) >= 0)
execute 'h '.expand('<cword>')
elseif (coc#rpc#ready())
call CocActionAsync('doHover')
else
execute '!' . &keywordprg . " " . expand('<cword>')
endif
endfunction
" 高亮相同的词汇
autocmd CursorHold * silent call CocActionAsync('highlight')
" 符号重命名
nmap <leader>rn <Plug>(coc-rename)
" 格式化插件
xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected)
augroup mygroup
autocmd!
" Setup formatexpr specified filetype(s).
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
" Update signature help on jump placeholder.
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end
我们说过coc.nvim类似于vim-plug,所以他也有一套自己的命令:
- CocInstall:安装一个coc插件
- CocList:获取所有已安装的coc插件
- CocConfig:创建一份Coc配置文件
- CocCommand:运行一个coc插件命令
先安装一个coc-marketplace,通过它你可以发现很多coc插件:
:CocInstall coc-marketplace
下载完成后,输入以下命令即可选取你需要的coc插件:
:CocList marketplace
其实通过CocInstall来下载coc插件并不是一个比较好的选择,因为一旦切换了开发环境,那么所有的coc插件都需要重新下载一次。
因此我推荐将coc插件的下载存放在init.vim文件中:
" coc下载插件
let g:coc_global_extensions = [
\ 'coc-marketplace',
\ 'coc-json',
\ 'coc-vimlsp'
\ ]
下次当你打开vim时,它会自动对没有安装的coc插件进行下载。
通过CocList extensions来查看已经安装了哪些插件,其中*号是已启用,+号是未启用,它是自动根据文件类型来进行选择的。
按下tab键它会提示给你一些管理coc插件的选项:
Choose action:
[t]oggle, (c)onfiguration, (o)pen, (d)isable, (e)nable, (l)ock, (h)elp, (r)eload
, (f)ix, (u)ninstall:
下面是我安装的插件,其中*代表已加载的,+号代表未加载的。
其他的功能
现在一款IDE已经初具雏形,但是对于debug调试、git管理等相关功能还没有添加上,后续如果有时间还会继续进行更新。