Hoolev Linux, Network, Coding

七种利器之VIM

俗话说:“工欲善其事,必先利其器”。作为一名程序员来说,工具箱里必须得有的一件利器就是编辑器。 《程序员修炼之道——从小工到专家》里建议用好一种编辑器并精通它,书中认为一个好的编辑器应该具有可配置、可扩展和可编程三大特点。 Vim就是这样一个好的编辑器,精通Vim吧!

##基本命令

  • Ctrl + f : 屏幕往后移一页
  • Ctrl + u : 屏幕往前移一页
  • 字符$ : 移到光标所在行的行尾
  • 字符^ : 移到光标所在行的行首
  • 字符w : 光标跳到下个字的开头
  • 字符e : 光标跳到下个字的结尾
  • 字符b : 光标跳到上个字的开头
  • gg : 移动到文件的第一行
  • shift +g : 移动到文件的最后一行
  • :%s/A/B : 用B替换所有A

##基本配置 Vim的配置文件保存在vimrc中,这里就不一一列出每项配置了,完整的配置请参考vimrc

在Vim中,不论是窗口外观、显示字体,还是操作方式、快捷键、插件属性均可通过编辑配置文件将vim调教成最适合你的编辑器。 vim的全局配置文件位于/etc/vimrc,它控制着所有用户下的vim,局部配置文件位于~/.vimrc,如果调整了该文件,相关变动仅对当前用户有效。

要正常调用各项插件功能(甚至vim自身的很多快捷操作),先得输入一个“前缀键”,通过“前缀键”告诉vim说现在用户输入的是快捷键而非普通字符。 正因如此,“前缀键”是vim使用率较高的一个键,选一个最方便输入的键作为“前缀键”,将有助于提高编辑效率。 在vimrc中可以使用let mapleader = ";"来设置“前缀键”。

输入前缀键的时候,在右下脚位置可以看到回显,显示时间大概1秒左右。

##插件管理 Vim强大之处在于其可定制化,可定制化当然离不开形形色色的插件。在Git时代,使用Vundle来管理Vim的插件,堪称完美。

Vundle的逻辑是这样的:

  • Vim Scripts中挑选你喜欢的插件
  • Github中找到你选中的插件
  • 在Vim的配置文件中写一句 Plugin plugin_name
  • 执行一下Vundle的初始化命令(:PluginInstall),插件就装好了
  • 升级和卸载也是同样的简单 完美的世界!

Vundle

Vundle的安装很简单:

git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle

Vundle的基本配置

set nocompatible
 
filetype off
set rtp+=~/.vim/bundle/Vundle.vim/
call vundle#begin()

Plugin 'gmarik/Vundle.vim'
Plugin 'scrooloose/nerdtree'
Plugin 'fholgado/minibufexpl.vim'
Plugin 'winmanager'
Plugin 'vimwiki'
Plugin 'Valloric/YouCompleteMe'
Plugin 'marijnh/tern_for_vim'
Plugin 'scrooloose/syntastic'
Plugin 'pangloss/vim-javascript'
Plugin 'plasticboy/vim-markdown'

call vundle#end()            " required
filetype plugin indent on    " required

打开Vim之后,可以用:PluginInstal安装插件,用PluginClean卸载插件。

文件浏览

我们可以通过NERDtree插件查看文件列表,要打开哪个文件,光标选中后回车即可在新buffer中打开。

  • 插件名:NERDTree (scrooloose/nerdtree)
  • 常用操作:Enter—打开文件,r—刷新目录文件列表,fl—打开文件浏览
  • 基本配置
 nmap <Leader>fl :NERDTreeToggle<CR>
 "设置NERDTree子窗口宽度
 let NERDTreeWinSize=23

多文档编辑

一个EXCEL文档可以有多个SHEET,你可以在不同SHEET间来回切换,同样,编程时也需要类似功能,即,同时打开多个文件,可以自由自在地在不同代码文件间游历。 这种需求,vim是通过buffer来实现的。每打开一个文件vim就对应创建一个buffer,多个文件就有多个buffer。

  • 插件名:MiniBufExplorer (fholgado/minibufexpl.vim)
  • 常用操作:打开多个文档时,vim在窗口顶部自动创建buffer列表窗口。 光标在任何位置时,CTRL-TAB正向遍历buffer,CTRL-k,j,h,l,分别进入当前窗口周围的上下左右窗口。 光标在MiniBufExplorer窗口内,输入d删除光标所在的buffer
  • 基本配置
 nmap <Leader>fl :NERDTreeToggle<CR>
" 设置NERDTree子窗口宽度                                                                                                                 
let NERDTreeWinSize=23
" 设置最大高度
let g:miniBufExplMaxSize = 1
let g:miniBufExplSplitBelow = 0
let g:miniBufExplorerMoreThanOne = 0
noremap <C-J> <C-W>j
noremap <C-K> <C-W>k
noremap <C-H> <C-W>h
noremap <C-L> <C-W>l

代码补全

本编辑器”这种东西一般都不真正的理解程序语言。 很多 Emacs 和 vi 的用户以为用 etags 和 ctags 这样的工具就能让他们“跳转到定义”,然而这些 tags 工具其实只是对程序的“文本”做一些愚蠢的正则表达式匹配。 它们根本没有对程序进行 parse,所以其实只是在进行一些“瞎猜”。 简单的函数定义它们也许能猜对位置,但是对于有重名的定义,或者局部变量的时候,它们就力不从心了。

	[《编辑器与IDE》]: http://www.yinwang.org/blog-cn/2013/04/20/editor-ide/

但是YouCompleteMe让Vim理解了C/C++。YCM基于clang为C/C++代码提供代码提示,借助clang的强大功能,YCM对C/C++的补全效率和准确性极高,而且可以模糊匹配。

YCM的安装

YCM需要最新版本Vim(7.3.584)的支持 使用Vundle安装YouCompleteMe后,需要编译才能使用。

cd ~/.vim/bundle/YouCompleteMe
./install.sh --clang-completer

语意补全要正确工作,需要配置好.ycm_extra_conf.py文件,模板在这里。在vimrc文件中加入

let g:ycm_global_ycm_extra_conf = '~/.vim/.ycm_extra_conf.py'
let g:ycm_error_symbol = '>>'
let g:ycm_warning_symbol = '>*'
nnoremap <leader>gdl :YcmCompleter GoToDeclaration<CR>
nnoremap <leader>gdf :YcmCompleter GoToDefinition<CR>
nnoremap <leader>gd :YcmCompleter GoToDefinitionElseDeclaration<CR>                                                                      
nmap <F4> :YcmDiags<CR>

quickfix模式

所谓quickfix模式,它和Normal模式、Insert模式没什么关系,它只是一种加快你开发速度的工作方式。 Quickfix模式的主要思想是保存一个位置列表,然后提供一系列命令,实现在这个位置列表中跳转。

利用vim的quickfix模式和make命令,可以大大加快编码,编译,修改编译错误的过程。

在quickfix模式里经常用到的命令有:

	:cc        显示详细错误信息 ( :help :cc )
	:cp        跳到上一个错误 ( :help :cp )
	:cn        跳到下一个错误 ( :help :cn )
	:cl        列出所有错误 ( :help :cl )
	:cw        如果有错误列表,则打开quickfix窗口 ( :help :cw )
	:col       到前一个旧的错误列表 ( :help :col )
	:cnew      到后一个较新的错误列表 ( :help :cnew )

对于经常用到的命令,最好提供更方便的使用方法,我们可以在vimrc中定义:

	nmap <leader>cc :cc<cr>
	nmap <leader>cn :cn<cr>
	nmap <leader>cp :cp<cr>
	nmap <leader>cw :cw 10<cr>