vim搭建C编程IDE

曾经在一篇关于vim技巧的文章里有一句话:“世界上只有三种编辑器,EMACS、VIM和其它。”
我不知道这是不是太过于绝对了,但是从我所看到的每一篇linux下编程以及文字编辑的文章中,都把vim比作是一款“神器”。一直都在windows下编程,有vc6.0++以及code::block这类的全能而且好用IDE,而这学期接触linux之后,逐渐接触了vim,开始使用vim进行一些C程序的编写,但是在命令行中除了一开始的不适应之外,还有一些快捷键和在windows下经常使用的小技巧的缺失确实不太好用。
借此实践的机会,我开始改造我的vim,让它变成我编程的有力工具。

一、中文帮助手册的安装

我们使用的虚拟机中的vim中除了主页面是中文外,帮助文档都是英文的,对于英语基础差的我实在是看不懂。

我们可以通过以下方式来进行汉化:
安装vim中文帮助vimcdoc

1. 下载:

下载页面:http://vimcdoc.sourceforge.net/
选择“Latest platform independent tarball, including an Linux/BSD installation script”【1】下载。

2. 安装:

网上好多人所说的“解压,把doc目录下的文件复制到~/.vim/doc下即可”是不起作用的。这里参考【2】中的步骤进行安装。

1. 解压tar.gz 包:

 tar -xzvf vimcdoc-1.9..tar.gz.tar.gz

2. 然后进入 vimcdoc-1.9.0 目录并执行

 ./vimcdoc. -i

该安装程序会自动识别 Vim 的安装路径,将中文的文档拷贝到相应的地方。原有的英文文档不受影响。
NOTE: 使用-i选项的话,缺省同时安装 vimcdoc.vim 全局插件,该插件会在.vim下生成一个plugin目录。
可是使用 -I选项来安装:

 ./vimcdoc. -I

如果没 vimcdoc.vim 插件(该插件设置缺省编码为 utf-8,使得每次使用:help 命令时都优先使用中文的帮助文档),但又想使用 :help 命令时都优先使用中文的帮助文档,可以在 vimrc 文件中配置:

 Set Vim help to Chinese and utf-8 encoding
 version >= 603
 set helplang=cn
 set encoding=utf-
 set fileencoding=utf-
 endif

3. 卸载:

Linux:
如果是使用的自动安装脚本安装的话,只要运行下面的命令即可:

 ./vimcdoc. -u

但必须用与安装时同样的用户名 。
参考:
【1】Download Links(https://sourceforge.net/projects/vimcdoc/files/vimcdoc/vimcdoc-1.9.0.tar.gz/download)
【2】【学习笔记-VIM】Vim初学 - Vim中文帮助文档安装(http://blog.csdn.net/wo0621/article/details/12956173)
安装完成之后就可以查看中文的帮助文档了,对于不擅长英语的使用者确实方便了很多。

二、vim编程常用命令

% 跳转到配对的括号去
[[ 跳转到代码块的开头去(但要求代码块中'{'必须单独占一行)
gD 跳转到局部变量的定义处
'' 跳转到光标上次停靠的地方, 是两个', 而不是一个"
mx 设置书签,x只能是a-z的26个字母
x 跳转到书签处(""是1左边的键)

增加缩进,"x>"表示增加以下x行的缩进
< 减少缩进,"x<"表示减少以下x行的缩进

三、语法高亮

首先查看你的 home 目录下有没有.vimrc 这个文件,没有就新建一个,这就是配置文件了,从大牛那复制过来的,每条的功能具体解释看注释,可以自行选择自己所需要的功能

~/arm$ cd ~
~$ gedit .vimrc

注:使用gedit主要是为了方便大段大段的文字粘贴!

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" 显示相关  

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"set shortmess=atI   " 启动的时候不显示那个援助乌干达儿童的提示  

"winpos 5 5          " 设定窗口位置  

"set lines=40 columns=155    " 设定窗口大小  

"set nu              " 显示行号  

set go=             " 不要图形按钮  

"color asmanian2     " 设置背景主题  

set guifont=Courier_New:h10:cANSI   " 设置字体  

"syntax on           " 语法高亮  

autocmd InsertLeave * se nocul  " 用浅色高亮当前行  

autocmd InsertEnter * se cul    " 用浅色高亮当前行  

"set ruler           " 显示标尺  

set showcmd         " 输入的命令显示出来,看的清楚些  

"set cmdheight=1     " 命令行(在状态行下)的高度,设置为1  

"set whichwrap+=<,>,h,l   " 允许backspace和光标键跨越行边界(不建议)  

"set scrolloff=3     " 光标移动到buffer的顶部和底部时保持3行距离  

set novisualbell    " 不要闪烁(不明白)  

set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")}   "状态行显示的内容  

set laststatus=1    " 启动显示状态行(1),总是显示状态行(2)  

set foldenable      " 允许折叠  

set foldmethod=manual   " 手动折叠  

"set background=dark "背景使用黑色 

set nocompatible  "去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限  

" 显示中文帮助

if version >= 603

set helplang=cn

set encoding=utf-8

endif

" 设置配色方案

"colorscheme murphy

"字体 

"if (has("gui_running")) 

"   set guifont=Bitstream\ Vera\ Sans\ Mono\ 10 

"endif 



set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936

set termencoding=utf-8

set encoding=utf-8

set fileencodings=ucs-bom,utf-8,cp936

set fileencoding=utf-8



"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"""""新文件标题""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"新建.c,.h,.sh,.java文件,自动插入文件头 

autocmd BufNewFile *.cpp,*.[ch],*.sh,*.java exec ":call SetTitle()" 

""定义函数SetTitle,自动插入文件头 

func SetTitle() 

"如果文件类型为.sh文件 

if &filetype == 'sh' 

    call setline(1,"\#########################################################################") 

    call append(line("."), "\# File Name: ".expand("%")) 

    call append(line(".")+1, "\# Author: ma6174") 

    call append(line(".")+2, "\# mail: ma6174@163.com") 

    call append(line(".")+3, "\# Created Time: ".strftime("%c")) 

    call append(line(".")+4, "\#########################################################################") 

    call append(line(".")+5, "\#!/bin/bash") 

    call append(line(".")+6, "") 

else 

    call setline(1, "/*************************************************************************") 

    call append(line("."), "    > File Name: ".expand("%")) 

    call append(line(".")+1, "    > Author: ma6174") 

    call append(line(".")+2, "    > Mail: ma6174@163.com ") 

    call append(line(".")+3, "    > Created Time: ".strftime("%c")) 

    call append(line(".")+4, " ************************************************************************/") 

    call append(line(".")+5, "")

endif

if &filetype == 'cpp'

    call append(line(".")+6, "#include<iostream>")

    call append(line(".")+7, "using namespace std;")

    call append(line(".")+8, "")

endif

if &filetype == 'c'

    call append(line(".")+6, "#include<stdio.h>")

    call append(line(".")+7, "")

endif

"新建文件后,自动定位到文件末尾

autocmd BufNewFile * normal G

endfunc 

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"键盘命令

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""



nmap <leader>w :w!<cr>

nmap <leader>f :find<cr>



" 映射全选+复制 ctrl+a

map <C-A> ggVGY

map! <C-A> <Esc>ggVGY

map <F12> gg=G

" 选中状态下 Ctrl+c 复制

vmap <C-c> "+y

"去空行  

nnoremap <F2> :g/^\s*$/d<CR> 

"比较文件  

nnoremap <C-F2> :vert diffsplit 

"新建标签  

map <M-F2> :tabnew<CR>  

"列出当前目录文件  

map <F3> :tabnew .<CR>  

"打开树状文件目录  

map <C-F3> \be  

"C,C++ 按F5编译运行

map <F5> :call CompileRunGcc()<CR>

func! CompileRunGcc()

    exec "w"

    if &filetype == 'c'

        exec "!g++ % -o %<"

        exec "! ./%<"

    elseif &filetype == 'cpp'

        exec "!g++ % -o %<"

        exec "! ./%<"

    elseif &filetype == 'java' 

        exec "!javac %" 

        exec "!java %<"

    elseif &filetype == 'sh'

        :!./%

    endif

endfunc

"C,C++的调试

map <F8> :call Rungdb()<CR>

func! Rungdb()

   exec "w"

    exec "!g++ % -g -o %<"

exec "!gdb ./%<"

endfunc

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

""实用设置

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" 设置当文件被改动时自动载入

set autoread

" quickfix模式

autocmd FileType c,cpp map <buffer> <leader><space> :w<cr>:make<cr>

"代码补全 

set completeopt=preview,menu 

"允许插件  

filetype plugin on

"共享剪贴板  

set clipboard+=unnamed 

"从不备份  

set nobackup

"make 运行

:set makeprg=g++\ -Wall\ \ %

"自动保存

set autowrite

set ruler                   " 打开状态栏标尺

set cursorline              " 突出显示当前行

set magic                   " 设置魔术

set guioptions-=T           " 隐藏工具栏

set guioptions-=m           " 隐藏菜单栏

"set statusline=\ %<%F[%1*%M%*%n%R%H]%=\ %y\ %0(%{&fileformat}\ %{&encoding}\ %c:%l/%L%)\

" 设置在状态行显示的信息

set foldcolumn=0

set foldmethod=indent 

set foldlevel=3 

set foldenable              " 开始折叠

" 不要使用vi的键盘模式,而是vim自己的

set nocompatible

" 语法高亮

set syntax=on

" 去掉输入错误的提示声音

set noeb

" 在处理未保存或只读文件的时候,弹出确认

set confirm

" 自动缩进

set autoindent

set cindent

" Tab键的宽度

set tabstop=4

" 统一缩进为4

set softtabstop=4

set shiftwidth=4

 不要用空格代替制表符

set noexpandtab

" 在行和段开始处使用制表符

set smarttab

" 显示行号

set number

" 历史记录数

set history=1000

"禁止生成临时文件

set nobackup

set noswapfile

"搜索忽略大小写

set ignorecase

"搜索逐字符高亮

set hlsearch

set incsearch

"行内替换

set gdefault

"编码设置

set enc=utf-8

set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936

"语言设置

set langmenu=zh_CN.UTF-8

set helplang=cn

" 我的状态行显示的内容(包括文件类型和解码)

"set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")}

"set statusline=[%F]%y%r%m%*%=[Line:%l/%L,Column:%c][%p%%]

" 总是显示状态行

set laststatus=2

" 命令行(在状态行下)的高度,默认为1,这里是2

set cmdheight=2

" 侦测文件类型

filetype on

" 载入文件类型插件

filetype plugin on

" 为特定文件类型载入相关缩进文件

filetype indent on

" 保存全局变量

set viminfo+=!

" 带有如下符号的单词不要被换行分割

set iskeyword+=_,$,@,%,#,-

" 字符间插入的像素行数目

set linespace=0

" 增强模式中的命令行自动完成操作

set wildmenu

" 使回格键(backspace)正常处理indent, eol, start等

set backspace=2

" 允许backspace和光标键跨越行边界

set whichwrap+=<,>,h,l

" 可以在buffer的任何地方使用鼠标(类似office中在工作区双击鼠标定位)

set mouse=a

set selection=exclusive

set selectmode=mouse,key

" 通过使用: commands命令,告诉我们文件的哪一行被改变过

set report=0

" 在被分割的窗口间显示空白,便于阅读

set fillchars=vert:\ ,stl:\ ,stlnc:\

" 高亮显示匹配的括号

set showmatch

" 匹配括号高亮的时间(单位是十分之一秒)

set matchtime=1

" 光标移动到buffer的顶部和底部时保持3行距离

set scrolloff=3

" 为C程序提供自动缩进

set smartindent

" 高亮显示普通txt文件(需要txt.vim脚本)

au BufRead,BufNewFile *  setfiletype txt

"自动补全

:inoremap ( ()<ESC>i

:inoremap ) <c-r>=ClosePair(')')<CR>

:inoremap { {<CR>}<ESC>O

:inoremap } <c-r>=ClosePair('}')<CR>

:inoremap [ []<ESC>i

:inoremap ] <c-r>=ClosePair(']')<CR>

:inoremap " ""<ESC>i

:inoremap ' ''<ESC>i

function! ClosePair(char)

    if getline('.')[col('.') - 1] == a:char

        return "\<Right>"

    else

        return a:char

    endif

endfunction

filetype plugin indent on 

"打开文件类型检测, 加了这句才可以用智能补全

set completeopt=longest,menu

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" CTags的设定  

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let Tlist_Sort_Type = "name"    " 按照名称排序  

let Tlist_Use_Right_Window = 1  " 在右侧显示窗口  

let Tlist_Compart_Format = 1    " 压缩方式  

let Tlist_Exist_OnlyWindow = 1  " 如果只有一个buffer,kill窗口也kill掉buffer  

let Tlist_File_Fold_Auto_Close = 0  " 不要关闭其他文件的tags  

let Tlist_Enable_Fold_Column = 0    " 不要显示折叠树  

autocmd FileType java set tags+=D:\tools\java\tags  

"autocmd FileType h,cpp,cc,c set tags+=D:\tools\cpp\tags  

"let Tlist_Show_One_File=1            "不同时显示多个文件的tag,只显示当前文件的

"设置tags  

set tags=tags  

"set autochdir 



""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"其他东东

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"默认打开Taglist 

let Tlist_Auto_Open=1 

"""""""""""""""""""""""""""""" 

" Tag list (ctags) 

"""""""""""""""""""""""""""""""" 

let Tlist_Ctags_Cmd = '/usr/bin/ctags' 

let Tlist_Show_One_File = 1 "不同时显示多个文件的tag,只显示当前文件的 

let Tlist_Exit_OnlyWindow = 1 "如果taglist窗口是最后一个窗口,则退出vim 

let Tlist_Use_Right_Window = 1 "在右侧窗口中显示taglist窗口

" minibufexpl插件的一般设置

let g:miniBufExplMapWindowNavVim = 1

let g:miniBufExplMapWindowNavArrows = 1

let g:miniBufExplMapCTabSwitchBufs = 1
let g:miniBufExplModSelTarget = 1

当修改结束后,就会由自己想要的结果

四、在程序中跳来跳去: Ctags 的使用

【ctags功能】:

   为源码的变量/对象、结构体/类、函数/接口、宏等产生索引文件,以便快速定位。目前支持41种语言,这里仅以C/C++为例:ctags可以产生c/c++语言所有类型的索引文件,具体如下:

-> class names(类名)
-> macro definitions(宏定义)
-> enumeration names(枚举名)
-> enumerators(枚举变量)
-> function definitions(函数定义)
-> function prototypes/declarations(函数定义/声明)
-> class, interface, struct, and union data members(类,接口,结构体,联合体)
-> structure names(结构体名)
-> typedefs(别名)
-> union names(联合体名)
-> variables (definitions and external declarations)变量

【ctags的安装】
1)在线安装:

sudo apt-get install ctags (ubuntu)

(RedHat系列使用:yum install ctags)
若不成功,可能是因为源的问题,换一下软件源update后重新执行上述命令即可。
2)手动下载安装:
下载地址

Official site: http://ctags.sourceforge.net/
VIM online: http://www.vim.org/scripts/script.php?script_id=610

参考步骤(以5.8版本ctags-5.8.tar.gz为例)
解压后

$ cd ctags-5.8
$ ./configure
$ make
# make install

安装结束后,使用ctags命令测试是否成功
或whatis ctags, whereis ctags等

【生成tags文件】
安装成功后,首先要为源码文件生成tags文件。

$ ctags -R

递归的为当前目录及子目录下的所有代码文件生成tags文件
为某些源码生成tags文件,使用如下命令

$ ctags filename.c filename1.c file.h

$ ctags *.c *.h

为了使得字段补全有效,在生成tags时需要一些额外的参数,如:
ctags -R --c++-kinds=+px --fields=+iaS --extra=+q
其中:
选项c++-kinds 用于指定C++语言的tags记录类型,
--c-kinds用于指定c语言的, 通用格式是 --{language}-kinds
选项 fileds 用于指定每条标记的扩展字段域
extra 选项用于增加额外的条目: f表示为每个文件增加一个条目, q为每个类增加一个条目

【使用方法】
在vim打开源码时,指定tags文件,才可正常使用,偶然使用时可以手动指定,在vim命令行输入:

:set tags=./tags(当前路径下的tags文件)

若要引用多个不同目录的tags文件,可以用逗号隔开
或者,设置 ~/.vimrc,加入一行,则不用手动设置tags路径:

set tags=~/path/tags

若要加入系统函数或全局变量的tag标签,则需执行:

ctags -I __THROW –file-scope=yes –langmap=c:+.h –languages=c,c++ –links=yes –c-kinds=+p --fields=+S -R -f ~/.vim/systags /usr/include /usr/local/include

并且在~/.vimrc中添加(亦可用上面描述的手动加入的方式):

set tags+=~/.vim/systags

这样,便可以使用系统库函数名补全、原型预览等功能了。

如果经常在不同工程里查阅代码,那么可以在~/.vimrc中添加:

set tags=tags;
set autochdir

设置好了tags文件,在定位变量/函数的定义时,最常用的快捷键是:

Ctrl + ]

跳转到变量或函数的定义处,或者用命令

:ta name

而使用快捷组合键

Ctrl + o/t

返回到跳转前的位置。
另外,ctags不会生成局部变量的索引,不过可以使用gd组合键(对光标所在处的word进行快捷查找定位)来定位,也是相当快捷的。

$ vim -t myAdd

用vim打开文件时,添加参数-t funcName会自动打开定义该函数的文件并定位到定义首行,上面这句就是找到myAdd定义的文件打开并将光标置于定义的第一行处。

:tags

会列出查找/跳转过程(经过的标签列表)
另外,还有一些vim环境中其他较为好用的快捷键:

-> * 定位至当前光光标所指单词的下一次出现的地方
-> # 定位至当前光光标所指单词的上一次出现的地方
-> n 定位至跳至已被标记出的单词下一次出现的地方
-> shift+n 定位至跳至已被标记出的单词上一次出现的地方

可以在help中得到更详细的ctags用法,vim中使用

:help tags


五、高效地浏览源码 -- 插件: TagList

我已经习惯了在vc++6.0中使用参数列表以及导航栏之类的工具,那里面列出了当前文件中的所有宏, 全局变量, 函数名等, 在查看代码时用这个窗口总揽全局, 切换位置相当方便, 因此,如果在linux下vim中也可以同样实现这个功能,就再方便不过了。
Taglist用于列出了当前文件中的所有标签(宏, 全局变量, 函数名等)

安装Taglist

:~$ vim-addons install taglist

配置Taglist

在vim配置文件/home/user/.vimrc中加入如下的配置:

"-- Taglist setting --
let Tlist_Ctags_Cmd='ctags' "因为我们放在环境变量里,所以可以直接执行
let Tlist_Use_Right_Window=1 "让窗口显示在右边,0的话就是显示在左边
let Tlist_Show_One_File=0 "让taglist可以同时展示多个文件的函数列表
let Tlist_File_Fold_Auto_Close=1 "非当前文件,函数列表折叠隐藏
let Tlist_Exit_OnlyWindow=1 "当taglist是最后一个分割窗口时,自动推出vim
"是否一直处理tags.1:处理;0:不处理
let Tlist_Process_File_Always=1 "实时更新tags
let Tlist_Inc_Winwidth=0

进入vim后用命令":Tlist"打开/关闭taglist窗口

帮助文档

:help taglist.txt


右边的窗口就是前面介绍的TagList窗口, 其中列出了c文件中的tag, 并且按照"typedef", "variable", "function"等进行了分类. 将光标移到VimMain上,按下回车后, 源程序会自动跳转到左边函数的定义处, 这就是TagList最基本也是最常用的操作.
还有一个常用的操作, 在浏览TagList窗口时, 如果还不想让源码跳转, 但是想看看tag在源码中完整的表达, 可以将光标移到想要看的tag上,然后按下空格键, 在下面的命令栏中, 会显示该tag在源码中完整的写法, 而不会跳转到源码处.

六、文件浏览器和窗口管理器 -- 插件: WinManager


在图标识的地方是一个文件浏览器, 里面列出了当前目录中的文件, 可以通过这个浏览器来浏览工程中的源文件, 当光标停在某个文件或文件夹的时候, 按下回车, 可以打开该文件或文件夹。
1、准备winmanger插件,从下面网址下即可:

http://www.vim.org/scripts/script.php?script_id=95

2、解压后得到两个文件夹plugin和doc,将它们拷贝到类似C:\Program Files\Vim\vim73目录下,与那个目录下已有的plugin和doc合并
3、修改_vimrc文件,增加以下配置:

" 设置winmanager
" 设置界面分割
let g:winManagerWindowLayout = "TagList|FileExplorer"
"设置winmanager的宽度,默认为25
let g:winManagerWidth = 30
"定义打开关闭winmanager快捷键为F8
nmap <silent> <F8> :WMToggle<cr>
"在进入vim时自动打开winmanager
let g:AutoOpenWinManager = 1

4、打开某个文件夹下的某个文件(最好文件夹下有多个文件,便于观察效果),按F8,出现上图,红色方框标记的就是winmanger区域了:

七、Cscope 的使用

安装好了前文介绍的中文帮助手册, 用下面的命令可以看介绍:

:help if_cscop.txt

在这里简单摘抄一点:
Cscope 是一个交互式的屏幕下使用的工具,用来帮助你:

  • 无须在厚厚的程序清单中翻来翻去就可以认识一个 C 程序的工作原理。
  • 无须熟悉整个程序就可以知道清楚程序 bug 所要修改的代码位置。
  • 检查提议的改动 (如添加一个枚举值) 可能会产生的效果。
  • 验证所有的源文件都已经作了需要的修改;例如给某一个现存的函数添加一个参数。
  • 在所有相关的源文件中对一个全局变量改名。
  • 在所有相关的位置将一个常数改为一个预处理符号。

因此我们可以了解到,cscope绝对是加强版的ctags

安装Cscope:

如果系统中有cscope命令, 则可以跳过这一小段, 如果没有, 就先跟着我一起安装一个吧.
在Cscope的主页: http://cscope.sourceforge.net 下载一个源码包, 解压后编译安装:

./configure
make
make install       // 需要root权限

先在~/vimrc中增加一句:

:set cscopequickfix=s-,c-,d-,i-,t-,e-

这个是设定是否使用 quickfix 窗口来显示 cscope 结果, 用法在后面会说到。

跟Ctags一样, 要使用其功能必须先为代码生成一个cscope的数据库, 在项目的根目录运行下面的命令:

$ cd /home/wooin/vim71/
$ cscope -Rbq

此后会生成三个文件

$ ll cscope.*
-rw-rw-r-- 1 wooin wooin 1.1M 2007-09-30 10:56 cscope.in.out
-rw-rw-r-- 1 wooin wooin 6.7M 2007-09-30 10:56 cscope.out
-rw-rw-r-- 1 wooin wooin 5.1M 2007-09-30 10:56 cscope.po.out

打开文件, 开始Coding

$ cd src
$ vi main.c

进入vim后第一件事是要把刚才生成的cscope文件导入到vim中来, 用下面的命令:

:cs add /home/wooin/vim71/cscope.out /home/wooin/vim71

上面这条命令很重要, 必须写全, 不能只写前半句:

:cs add /home/wooin/vim71/cscope.out

因为源码是多级目录的, 如果这样写, cscope是无法在子目录中的源码中工作的, 当然, 如果源码都在同一级目录中就无所谓了. 如果要经常用cscope的话, 可以把上面那句加到~/.vimrc中去.
cscope的主要功能是通过同的子命令"find"来实现的
"cscope find"的用法:

cs find c|d|e|f|g|i|s|t name
0 或 s 查找本 C 符号(可以跳过注释)
1 或 g 查找本定义
2 或 d 查找本函数调用的函数
3 或 c 查找调用本函数的函数
4 或 t 查找本字符串
6 或 e 查找本 egrep 模式
7 或 f 查找本文件
8 或 i 查找包含本文件的文件

如果每次查找都要输入一长串命令的话还真是件讨人厌的事情, Cscope的帮助手册中推荐了一些快捷键的用法, 下面是其中一组, 也是我用的, 将下面的内容添加到~/.vimrc中, 并重启vim:

nmap <C-_>s :cs find s <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>g :cs find g <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>c :cs find c <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>t :cs find t <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>e :cs find e <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>f :cs find f <C-R>=expand("<cfile>")<CR><CR>
nmap <C-_>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
nmap <C-_>d :cs find d <C-R>=expand("<cword>")<CR><CR>

当光标停在某个你要查找的词上时, 按下<C->g, 就是查找该对象的定义, 其他的同理.
按这种组合键有一点技巧,按了<C-
>后要马上按下一个键,否则屏幕一闪就回到nomal状态了
<C-_>g的按法是先按"Ctrl+Shift+-", 然后很快再按"g"

八、QuickFix 窗口

学习QuickFix 窗口的使用一般会用到一下帮助,稍稍看一下就会对QuickFix 窗口的使用方法有所了解:

:help quickfix
:help :make
:help 'makeprg'
:help 'errorformat'
:help 'switchbuf'
:help location-list
:help grep
:help :vimgrep
:help :grep
:help starstar-wildcard 

所谓quickfix模式,它和Normal模式、Insert模式没什么关系,它只是一种加快开发速度的工作方式。

[编译]

通常,我们在编程过程中,经常要写代码,编译,修改编译错误,这个过程会数十遍上百遍的重复。如果你是根据编译器输出的错误信息,打开出错的文件,找到出错的行,然后再开始修改,那效率未免太低下了。

利用vim的quickfix模式,可以大大加快这一过程,你可以在vim启动编译,然后vim会根据编译器输出的错误信息,自动跳到第一个出错的地方,让你进行修改;修改完后,使用一个快捷键,跳到下一个错误处,再进行修改。

为了做到这一点,你首先要定义编译时所使用的程序,对大多数使用Makefile的项目来说,vim的缺省设置”make“已经可以满足要求了。如果你的项目需要用一个特殊的程序进行编译,就需要修改’makeprg‘选项的值。

我们以”hello world”程序这个简单的例子为例,讲一下quickfix模式的用法。

该程序的内容如下,里面包含了三个小小的错误:

/* hello world demo */
#include <stdio.h"
int main(int argc, char **argv)
{
    int i;
    print("hello world\n");
    return 0;
} 

我们可以为这个程序写个小小的Makefile文件,不过为了演示’makeprg‘的设置方法,我们并不用Makefile,而直接设置’makeprg‘选项,如下:

:set makeprg=gcc\ -Wall\ -ohello\ hello.c 

上面的命令会把hello.c编译为名hello的可执行文件,并打开了所有的Warnning。如果编译命令中有空格,需要使用’\‘对空格进行转义,上面的例子就使用了’\‘转义空格。

我们设置好’makeprg‘选项后,输入下面的命令就可以编译了:

:make 

在使用”:make“时,vim会自动调用’makeprg‘选项定义的命令进行编译,并把编译输出重定向到一个临时文件中,当编译出现错误时,vim会从上述临时文件中读出错误信息,根据这些信息形成quickfix列表,并跳转到第一个错误出现的地方。
对于我们上面的程序来说,光标会停在第三行,也就是第一个出错的位置,vim同时会提示出错信息。如果你没看清出错信息,可以输入”:cc“命令,vim会更次显示此信息,或者干脆使用”:cw“命令,打开一个quickfix窗口,把所有的出错信息显示出来,见下图:

现在知道错在哪儿了,修正一下,然后使用”:cn“命令(或者在Quickfix List对应行上输入回车)跳到下一个出错的地方,以此类推,直到修正全部错误。

vim可以同时记住最新的10个错误列表,也就是说你最近10次使用”:make“命令编译所遇到的错误都保存着,可以使用”:colder“和”:cnewer“命令,回到旧的错误列表,或者到更新的错误列表。

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

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

更多的命令,以及这些命令更详细的解释,请参见手册。

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

autocmd FileType c,cpp  map <buffer> <leader><space> :w<cr>:make<cr>
nmap <leader>cn :cn<cr>
nmap <leader>cp :cp<cr>
nmap <leader>cw :cw 10<cr> 

现在使用”,“(先按,再按空格)就可以编译,使用”,cp“和”,cn“跳到上一个和下一个错误,使用”,cw“来打开一个quickfix窗口。这下顺手多了!
如果希望跳转到出错的文件时,使用一个分隔的窗口打开,可以参阅’switchbuf‘选项的值。
在vim7中,每个窗口都可以拥有自己的位置列表,这样,你就能够同时打开多个位置列表了,而quickfix列表在整个vim中只有一个。也可以使用位置列表来显示编译错误信息,具体命令可以参考手册:”

:help location-list“以及”:help :lmake“。

九、快速浏览和操作Buffer -- 插件: MiniBufExplorer

使用方法:

重新启动vim, 当你只编辑一个buffer的时候MiniBufExplorer派不上用场, 当你打开第二个buffer的时候, MiniBufExplorer窗口就自动弹出来了,
狭长的窗口就是MiniBufExplorer窗口, 其中列出了当前所有已经打开的buffer, 当把光标置于这个窗口时, 有下面几个快捷键可以用:

<Tab> 	向前循环切换到每个buffer名上
<S-Tab> 	向后循环切换到每个buffer名上
<Enter> 	在打开光标所在的buffer
d 	删除光标所在的buffer

以下的两个功能需要在~/.vimrc中增加:

let g:miniBufExplMapCTabSwitchBufs = 1

<C-Tab> 	向前循环切换到每个buffer上,并在但前窗口打开
<C-S-Tab> 	向后循环切换到每个buffer上,并在但前窗口打开

如果在~/.vimrc中设置了下面这句:

let g:miniBufExplMapWindowNavVim = 1

则可以用<C-h,j,k,l>切换到上下左右的窗口中去,就像:
C-w,h j k l 向"左,下,上,右"切换窗口.
在~/.vimrc中设置:

let g:miniBufExplMapWindowNavArrows = 1

是用<C-箭头键>切换到上下左右窗口中去

十、c/h文件间相互切换 -- 插件: A

浏览/编辑代码的时候,常常需要在头文件(.h)和源文件(.c,.cpp,.cc...)之间切换,或者打开某个包含文件(如#include ...),a.vim正是用来满足以上需求的一款Vim插件。

官方下载网址:a.vim : Alternate Files Quickly。当前最新版本:v2.18。

a.vim的安装相当简单,下载a.vim后复制进Vim插件目录(一般为~/.vim/plugin),必要时再重启一下Vim就可以使用了。

头/源文件切换命令

:A 头文件/源文件切换
:AS 分割窗后并切换头/源文件(切割为上下两个窗口)
:AV 垂直切割窗口后切换头/源文件(切割为左右两个窗口)
:AT 新建Vim标签式窗口后切换
:AN 在多个匹配文件间循环切换

将光标所在处单词作为文件名打开

:IH 切换至光标所在文件
:IHS 分割窗口后切换至光标所在文件(指将光标所在处单词作为文件名打开)
:IHV 垂直分割窗口后切换
:IHT 新建标签式窗口后切换
:IHN 在多个匹配文件间循环切换

快捷键操作

<Leader>ih 切换至光标所在文件*
<Leader>is 切换至光标所在处(单词所指)文件的配对文件(如光标所在处为foo.h,则切换至foo.c/foo.cpp...)
<Leader>ihn 在多个匹配文件间循环切换

*指Vim所定义的映射(map)前缀,在Vim配置文件中可过变量'mapleader'进行设置,缺省为''。

十一、在工程中查找 -- 插件: Grep

下载地址
http://www.vim.org/scripts/script.php?script_id=311
版本: 1.8
安装: 把grep.vim 文件丢到 ~/.vim/plugin 文件夹就好了
用法:
在grep.vim脚本的前部可以找到一些说明文档:

:Grep 	按照指定的规则在指定的文件中查找
:Rgrep 	同上, 但是是递归的grep
:GrepBuffer 	在所有打开的缓冲区中查找
:Bgrep 	同上
:GrepArgs 	在vim的argument filenames (:args)中查找
:Fgrep 	运行fgrep
:Rfgrep 	运行递归的fgrep
:Egrep 	运行egrep
:Regrep 	运行递归的egrep
:Agrep 	运行agrep
:Ragrep 	运行递归的agrep

上面的命令是类似这样调用的:

:Grep   [<grep_options>] [<search_pattern> [<file_name(s)>]]
:Rgrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
:Fgrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
:Rfgrep [<grep_options>] [<search_pattern> [<file_name(s)>]]
:Egrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
:Regrep [<grep_options>] [<search_pattern> [<file_name(s)>]]
:Agrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
:Ragrep [<grep_options>] [<search_pattern> [<file_name(s)>]]
:GrepBuffer [<grep_options>] [<search_pattern>]
:Bgrep [<grep_options>] [<search_pattern>]
:GrepArgs [<grep_options>] [<search_pattern>]

但是敲这些代码实在是太长了,完全可以在~/.vimrc中增加了下面这句:
nnoremap :Grep
比如想在/home/wooin/vim71/src/main.c中查找"FEAT_QUICKFIX", 则将光标移到"FEAT_QUICKFIX"上, 然后按下F3键,
在最下面的命令行会显示:
Search for pattern: FEAT_QUICKFIX
此时还可以编辑该行, grep支持正则表达式, 想全词匹配的话可以改成:
Search for pattern: /<FEAT_QUICKFIX/>
然后按下回车:
在最下面的命令行会显示:
Search in files: *
这是问搜索范围, 默认是该目录下的所有文件, 此时你还可以编辑该行, 比如你只想搜索源码文件:
Search in files: *.c *.h
然后在按下回车, 会在弹出的QuickFix窗口中列出所有符合条件的搜索结果, 你可以在其中查找你想要的结果。
如下图,我的vim中已经配好了此插件,按f3后会出现以下界面:

十二、高亮的书签 -- 插件: VisualMark

下载地址:
http://www.vim.org/scripts/script.php?script_id=1026

用法:
vim也和其他编辑器一样有"书签"概念, 在vim中叫"Mark", 可以用下面的命令查看相关说明:

:help Mark

该"书签"有个缺点: 不可见.
按照上面的方法安装好Visual Mark后, 你什么也不用设置, 如果是gvim, 直接在代码上按下Ctrl+F2, 发现光标所在的行变高亮了。
如果你设置了多个书签, 你可以用F2键正向在期间切换, 用Shift+F2反向在期间切换.

十三、自动补全

对于Microsoft Visual Studio此类IDE的代码补全功能当然是在喜欢不过了, 输入一个对象名后再输入"."或者"->", 则其成员名都可以列出来。
这里要使用的功能叫"new-omni-completion(全能补全)", 可以用下面的命令看看介绍:

:help new-omni-completion

你还需要在~/.vimrc文件中增加下面两句:

filetype plugin indent on

打开文件类型检测, 加了这句才可以用智能补全

set completeopt=longest,menu

关掉智能补全时的预览窗口

请确定你的Ctags 5.6已经安装好, 并且生成的tags文件已经可以用了
用vim打开源文件

$ vi /home/wooin/vim71/src/main.c

设置tags文件

:set tags=/home/wooin/vim71/tags

随便找一个有成员变量的对象, 比如"parmp", 进入Insert模式, 将光标放在"->"后面,
然后按下"Ctrl+X Ctrl+O", 此时会弹出一个下列菜单, 显示所有匹配的标签, 如下图:

此时有一些快捷键可以用:
|:------| -----------------😐
|Ctrl+P | 向前切换成员|
|Ctrl+N | 向后切换成员|
|Ctrl+E | 表示退出下拉窗口, 并退回到原来录入的文字|
|Ctrl+Y | 表示退出下拉窗口, 并接受当前选项|

如果增加了一些成员变量, 全能补全还不能马上将新成员补全, 需要重新生成一下tags文件, 但是不用重启vim, 只是重新生成一下tags文件就行了, 这时全能补全已经可以自动补全了.

vim中的其他补全方式还有:
|:--------------| ----------------------------😐
|Ctrl+X Ctrl+L | 整行补全|
|Ctrl+X Ctrl+N |根据当前文件里关键字补全|
|Ctrl+X Ctrl+K |根据字典补全|
|Ctrl+X Ctrl+T |根据同义词字典补全|
|Ctrl+X Ctrl+I |根据头文件内关键字补全|
|Ctrl+X Ctrl+] |根据标签补全|
|Ctrl+X Ctrl+F |补全文件名|
|Ctrl+X Ctrl+D |补全宏定义|
|Ctrl+X Ctrl+V |补全vim命令|
|Ctrl+X Ctrl+U |用户自定义补全方式|
|Ctrl+X Ctrl+S |拼写建议|

结语

搭建C语言IDE的工作就在这里结束了,实在是感叹vim的强大。但是基本上的工作分为三部分:
1、安装Vim和Vim基本插件
2、Vim配置文件
3.安装自己所需的插件
使用vim来进行C语言编程,进行插件的选择以及快捷键的配置,除了各个插件所定义的快捷键外,都可以根据自己的要求定制。
而插件的安装使用过程都是按照以下模式进行的:
1.如果是常用插件,vim是自带的,也可以在线自动安装
2.专用插件可以通过在插件网络主页下载一个源码包, 解压后编译安装:

# ./(插件名)
# make
# make install       // 需要root权限

然后在~/vimrc中增加一句,重启vim即可以使用。
文章最后,写一点题外话,@Help poor children in Uganda!这句话每次直接打开vim都可以看到,却从没有仔细思考过到底是什么情况。
可以用命令:hlep kcc查看详细的内容。也许会对于vim的作者有全新的认识。

参考文档:

1.跟我一起学习VIM - The Life Changing Editor - 为程序员服务
http://ju.outofmemory.cn/entry/79671
2.Vim试水之三:winmanager(文件管理器)安装 - feichexia - 博客园
http://www.cnblogs.com/feichexia/archive/2012/11/06/vim_WinManager.html
3.vi/vim使用进阶
http://easwy.com/blog/archives/advanced-vim-skills-catalog/
4.将Vim改造为强大的IDE—Vim集成Ctags/Taglist/Cscope/Winmanager/NERDTree/OmniCppComplete(有图有真相) - 凌峰布衣 - 博客园
http://www.cnblogs.com/zhangsf/archive/2013/06/13/3134409.html
5.如何将 Vim 打造成一个成熟的 IDE - 开源中国社区
http://www.oschina.net/news/53381/turn-vim-full-fledged-ide
6.跟我一起学习VIM - The Life Changing Editor - 为程序员服务
http://ju.outofmemory.cn/entry/79671
7.手把手教你把Vim改装成一个IDE编程环境(图文) - 吴垠的专栏 - 博客频道 - CSDN.NET
http://blog.csdn.net/wooin/article/details/1858917

posted @ 2015-12-04 01:50  苏儿  阅读(482)  评论(0编辑  收藏  举报