VIM 设置C++文本环境以及调式和编译

来源:互联网 发布:淘宝买个钻石店铺 编辑:程序博客网 时间:2024/06/06 05:57

1.设置VIM C++文本环境

.vimrc文件中写入:

 "2008年 09月 21日 星期日 01:11:28 CST

" 在处理未保存或只读文件的时候,弹出确认 set confirm " 带有如下符号的单词不要被换行分割
set iskeyword+=_,$,@,%,#,-

"Tlist 和 wm的设置
"命令模式输入wm打开Tlist和WM
set showcmd

"Taglist插件的设置
let g:Tlist_Use_Right_Window=1
let g:Tlist_Show_One_File=1
let g:Tlist_Compact_Format=1
let Tlist_Exit_OnlyWindow=1
let g:winManagerWindowLayout='FileExplorer|TagList'

"Tree explorer的设置
let g:treeExplVertical=1
let g:treeExplWinSize=30

"gvim打开以后最大化
"au GUIEnter * simalt ~x

"光标在窗口上下边界时距离边界7行即开始滚屏
set so=7

"配色
" Avoid clearing hilight definition in plugins
if !exists("g:vimrc_loaded")

  " color scheme
  if has("gui_running")
    set guioptions-=T "隐藏工具栏
    set guioptions-=m
    set guioptions-=L
    set guioptions-=r
    color blackboard
    "colorscheme professional
    "set guifont=YaHeiConsolasHybrid\ 13
    set guifont=Monaco\ 13
    "中文字体
    set guifontset=Microsoft\ YaHei\ 13
    "对于html,xml文件,通过ctrl+_来closetag
    if has("autocmd")
      autocmd FileType text,xml,html,perl,shell,bash,python,vim,php,ruby color blackboard
      autocmd FileType xml,html vmap <C-o> <ESC>'<i<!--<ESC>o<ESC>'>o-->
      autocmd FileType java,c,cpp,cs color desertEx
      autocmd FileType html,text,php,vim,c,java,xml,bash,shell,perl,python setlocal textwidth=100
      autocmd Filetype html,xml,xsl source ~/.vim/plugin/closetag.vim
    endif " has("autocmd")
  else
    color desert
    "colorscheme zellner
    "对于html,xml文件,通过ctrl+_来closetag
    if has("autocmd")
      autocmd FileType xml,html vmap <C-o> <ESC>'<i<!--<ESC>o<ESC>'>o-->
      autocmd FileType html,text,php,vim,c,java,xml,bash,shell,perl,python setlocal textwidth=100
      autocmd Filetype html,xml,xsl source ~/.vim/plugin/closetag.vim
    endif " has("autocmd")
  endif " has
endif " exists(...)
"这个是依赖终端的
"set background=dark

"显示行号
set number

"语法高亮度显示
syntax on

"检测文件的类型 开启codesnip
filetype on
filetype plugin on
filetype indent on
set completeopt=longest,menu
set runtimepath+=~/.vim/textmateOnly
set runtimepath+=/home/hunch/.vim/after
so ~/.vim/plugin/supertab.vim
let g:SuperTabDefaultCompletionType="<C-X><C-O>"

"鼠标支持
if has('mouse')
  set mouse=a
endif

"缩进相关
" 继承前一行的缩进方式,特别适用于多行注释
"set autoindent

" 为C程序提供自动缩进
"set smartindent

" 使用C样式的缩进
set cindent
function! GnuIndent()
  setlocal cinoptions=>4,n-2,{2,^-2,:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1
  setlocal shiftwidth=2
  setlocal tabstop=8
endfunction

au FileType c,cpp setlocal cinoptions=:0,g0,(0,w1 shiftwidth=4 tabstop=4 softtabstop=4
au FileType diff  setlocal shiftwidth=4 tabstop=4
au FileType html  setlocal autoindent indentexpr=
au FileType changelog setlocal textwidth=76

" Recognize standard C++ headers
au BufEnter /usr/include/c++/*    setf cpp
au BufEnter /usr/include/g++-3/*  setf cpp

" Setting for files following the GNU coding standard
au BufEnter /usr/*                call GnuIndent()

function! RemoveTrailingSpace()
  if $VIM_HATE_SPACE_ERRORS != '0' &&
        \(&filetype == 'c' || &filetype == 'cpp' || &filetype == 'vim')
    normal m`
    silent! :%s/\s\+$//e
    normal ``
  endif
endfunction
" Remove trailing spaces for C/C++ and Vim files
au BufWritePre *                  call RemoveTrailingSpace()

if &term=="xterm"
  set t_Co=8
  set t_Sb=^[[4%dm
  set t_Sf=^[[3%dm
endif
"set shiftwidth=2
"set tabstop=4
"set softtabstop=4
"set expandtab
" ambiwidth 默认值为 single。在其值为 single 时,
" 若 encoding 为 utf-8,gvim 显示全角符号时就会
" 出问题,会当作半角显示。
set ambiwidth=double
set autoread                " 自动重新加载外部修改内容
set autochdir               " 自动切换当前目录为当前文件所在的目录

"No bell settings {{{
set noerrorbells
set visualbell
if has('autocmd')
  autocmd GUIEnter * set vb t_vb=
endif
"No bell settings End }}}

"在编辑过程中,在右下角显示光标位置的状态行
set ruler
"set rulerformat=%20(%2*%<%f%=\ %m%r\ %3l\ %c\ %p%%%)

" 启动的时候不显示那个援助索马里儿童的提示
set shortmess=atI

set nolinebreak             " 在单词中间断行
" 在状态栏显示目前所执行的指令,未完成的指令片段亦
" 会显示出来
set showcmd
set wrap                    " 自动换行显示
"CmdLine settings {{{
set cmdheight=1             " 设定命令行的行数为 1
set laststatus=2            " 显示状态栏 (默认值为 1, 无法显示状态栏)
:set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [ASCII=\%03.3b]\ [HEX=\%02.2B]\ [POS=%04l,%04v][%p%%]\ [LEN=%L]
"
" 高亮字符,让其不受100列限制
":highlight OverLength ctermbg=red ctermfg=white guibg=grey guifg=white
":match OverLength '\%101v.*'

" 状态行颜色
highlight StatusLine guifg=SlateBlue guibg=Yellow
highlight StatusLineNC guifg=Gray guibg=White

"显示匹配括号
set showmatch

"默认无备份
set nobackup
set nowritebackup

"在insert模式下能用删除键进行删除
set backspace=indent,eol,start

"去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限
set nocp
" 增强模式中的命令行自动完成操作
set wildmenu

"文字编码加入utf8
" 设定默认解码
set fenc=utf-8
set fencs=utf-8,usc-bom,euc-jp,gb18030,gbk,gb2312,cp936
set enc=utf-8
let &termencoding=&encoding

" 使用英文菜单,工具条及消息提示
set langmenu=none

"自动缩排
set ai

"搜索不分大小写
set ic

"标识关键字
set hls

" 不要闪烁
set novisualbell

"设置语法折叠
set foldmethod=syntax
set foldcolumn=3 "设置折叠区域的宽度
set foldclose=all "设置为自动关闭折叠

" 用空格键来开关折叠
set foldenable
nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR>


"设置帮助语言
if version >= 603
  set helplang=cn
  set encoding=utf-8
endif

"编辑状态保存
au BufWinLeave * mkview
au BufWinEnter * silent loadview

" Line highlight 設此標整行會標註顏色
set cursorline
" Column highlight 設此是遊標整列會標註顏色
set cursorcolumn
"highlight CursorLine cterm=none ctermbg=2 ctermfg=0

"ctags设置
set tags=/home/hunch/.vim/stltags
"set tags+=/home/hunch/.vim/sgitag
"set tags+=/home/hunch/.vim/ctags
"set tags+=/home/hunch/.vim/glibctag
"智能补全ctags -R --c++-kinds=+p --fields=+iaS --extra=+q
let OmniCpp_DefaultNamespaces = ["std"]
let OmniCpp_GlobalScopeSearch = 1  " 0 or 1
let OmniCpp_NamespaceSearch = 1   " 0 ,  1 or 2
let OmniCpp_DisplayMode = 1
let OmniCpp_ShowScopeInAbbr = 0
let OmniCpp_ShowPrototypeInAbbr = 1
let OmniCpp_ShowAccess = 1
let OmniCpp_MayCompleteDot = 1
let OmniCpp_MayCompleteArrow = 1
let OmniCpp_MayCompleteScope = 1
highlight Pmenu ctermbg=13 guibg=LightGray
highlight PmenuSel ctermbg=7 guibg=DarkBlue guifg=White
highlight PmenuSbar ctermbg=7 guibg=DarkGray
highlight PmenuThumb guibg=Black

"打开自己工程的时候自动加载的脚本
if getfsize(".vimscript")>0
  source .vimscript
endif

"rails.vim
runtime! macros/matchit.vim
augroup myfiletypes
  " Clear old autocmds in group
  autocmd!
  " autoindent with two spaces, always expand tabs
  autocmd FileType ruby,eruby,yaml set ai sw=2 sts=2 et
augroup END

"autocmd FileType ruby,eruby set omnifunc=rubycomplete#Complete
autocmd FileType ruby,eruby set omnifunc=rubycomplete#Complete
"if you want buffer/rails/global completion you must add the following:
autocmd FileType ruby,eruby let g:rubycomplete_buffer_loading = 1
"if you want rails support add the following in addition
autocmd FileType ruby,eruby let g:rubycomplete_rails = 1
"if you want classes included in global completions add the following
autocmd FileType ruby,eruby let g:rubycomplete_classes_in_global = 1

"valgrind 相关
let g:valgrind_arguments='--leak-check=yes --num-callers=5000'

"字典完成
:set dictionary-=/usr/share/dict/words dictionary+=/usr/share/dict/words

"cscope
if has("cscope")
  set csprg=/usr/bin/cscope
  set csto=0
  set nocst
  set nocsverb
  " add any database in current directory
  if filereadable("cscope.out")
    cs add cscope.out
    " else add database pointed to by environment
  elseif $CSCOPE_DB != ""
    cs add $CSCOPE_DB
  endif
  set csverb
endif
map <C-_> :cstag <C-R>=expand("<cword>")<CR><CR>
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>

" Using 'CTRL-spacebar' then a search type makes the vim window
" split horizontally, with search result displayed in
" the new window.

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

" Hitting CTRL-space *twice* before the search type does a vertical
" split instead of a horizontal one

nmap <C-Space><C-Space>s
      \:vert scs find s <C-R>=expand("<cword>")<CR><CR>
nmap <C-Space><C-Space>g
      \:vert scs find g <C-R>=expand("<cword>")<CR><CR>
nmap <C-Space><C-Space>c
      \:vert scs find c <C-R>=expand("<cword>")<CR><CR>
nmap <C-Space><C-Space>t
      \:vert scs find t <C-R>=expand("<cword>")<CR><CR>
nmap <C-Space><C-Space>e
      \:vert scs find e <C-R>=expand("<cword>")<CR><CR>
nmap <C-Space><C-Space>i
      \:vert scs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
nmap <C-Space><C-Space>d
      \:vert scs find d <C-R>=expand("<cword>")<CR><CR>
"runtime ftplugin/man.vim
let Vimplate = "$HOME/bin/vimplate"
fun! ReadMan()
  " Assign current word under cursor to a script variable:
  let s:man_word = expand('<cword>')

  " Open a new window:
  :exe ":wincmd n"

  " Read in the manpage for man_word (col -b is for formatting):
  :exe ":r!man " . s:man_word . " | col -b"

  " Goto first line...
  :exe ":goto"

  " and delete it:
  :exe ":delete"
endfun

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Autocommands
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"加上日期 对应F2
:map <F2> gg:read !date<CR>

" bind :CD to :cd %:h, then change cwd to the dir that includes current file
sil! com -nargs=0 CD exe 'cd %:h'

" F5编译和运行C程序,F6编译和运行C++程序
" 请注意,下述代码在windows下使用会报错
" 需要去掉./这两个字符

" C的编译和运行
map <F5> :call CompileRunGcc()<CR>
func! CompileRunGcc()
  exec "w"
  exec "!gcc -Wall -g % -o %<"
  exec "! ./%<"
endfunc

" C++的编译和运行
map <F6> :call CompileRunGpp()<CR>
func! CompileRunGpp()
  exec "w"
  exec "!g++ -Wall -g % -o %<"
  exec "! ./%<"
endfunc

" 能够漂亮地显示.NFO文件
set encoding=utf-8
function! SetFileEncodings(encodings)
  let b:myfileencodingsbak=&fileencodings
  let &fileencodings=a:encodings
endfunction
function! RestoreFileEncodings()
  let &fileencodings=b:myfileencodingsbak
  unlet b:myfileencodingsbak
endfunction

au BufReadPre *.nfo call SetFileEncodings('cp437')|set ambiwidth=single
au BufReadPost *.nfo call RestoreFileEncodings()

" 高亮显示普通txt文件(需要txt.vim脚本)
"au BufRead,BufNewFile *  setfiletype txt

" Map the M key to the ReadMan function:
map M :call ReadMan()<CR>

"csupport
let g:alternateNoDefaultAlternate = 1

"a.vim
nnoremap <silent> <F12> :A<CR>

nmap wm :WMToggle<cr>

" 双反斜杠\\即可打开bufexplorer
map <leader><leader> \be
" Ctrl+Enter也可以切换buffer
map C-Enter C-Tab
nnoremap <silent> <F4> :tabprevious<CR>

:set cscopequickfix=s-,c-,d-,i-,t-,e-
nnoremap <silent> <F3> :Grep<CR>

":inoremap ( ()<ESC>i
":inoremap ) <c-r>=ClosePair(')')<CR>
":inoremap { {}<ESC>i
":inoremap } <c-r>=ClosePair('}')<CR>
":inoremap [ []<ESC>i
":inoremap ] <c-r>=ClosePair(']')<CR>
":inoremap < <><ESC>i
":inoremap > <c-r>=ClosePair('>')<CR>

function ClosePair(char)
  if getline('.')[col('.') - 1] == a:char
    return "\<Right>"
  else
    return a:char
  endif
endf

" mapping
" 如果下拉菜单弹出,回车映射为接受当前所选项目,否则,仍映射为回车;
"
" 如果下拉菜单弹出,CTRL-J映射为在下拉菜单中向下翻页。否则映射为CTRL-X CTRL-O;
"
" 如果下拉菜单弹出,CTRL-K映射为在下拉菜单中向上翻页,否则仍映射为CTRL-K;
"
" 如果下拉菜单弹出,CTRL-U映射为CTRL-E,即停止补全,否则,仍映射为CTRL-U;
inoremap <expr> <CR>       pumvisible()?"\<C-Y>":"\<CR>"
inoremap <expr> <C-J>      pumvisible()?"\<PageDown>\<C-N>\<C-P>":"\<C-X><C-O>"
inoremap <expr> <C-K>      pumvisible()?"\<PageUp>\<C-P>\<C-N>":"\<C-K>"

inoremap <expr> <C-U>      pumvisible()?"\<C-E>":"\<C-U>"a

inoremap <expr> <cr>       pumvisible() ? "\<c-y>" : "\<c-g>u\<cr>"
inoremap <expr> <c-n>      pumvisible() ? "\<c-n>" : "\<c-n>\<c-r>=pumvisible() ? \"\\<down>\" : \"\\<cr>\""
inoremap <expr> <m-;>      pumvisible() ? "\<c-n>" : "\<c-x>\<c-o>\<c-n>\<c-p>\<c-r>=pumvisible() ? \"\\<down>\" : \"\\<cr>\""

" minibufexpl插件的一般设置
"let g:miniBufExplMapWindowNavArrows = 1
"let g:miniBufExplModSelTarget = 1
"实现<C-Tab>     向前循环切换到每个buffer上,并在当前窗口打开
"let g:miniBufExplMapCTabSwitchBufs = 1
"<C-S-Tab>     向后循环切换到每个buffer上,并在当前窗口打开
"可以用<C-h,j,k,l>切换到上下左右的窗口中去
"let g:miniBufExplMapWindowNavVim = 1

"选中一段文字并全文搜索这段文字
:vnoremap <silent> ,/ y/<C-R>=escape(@", '\\/.*$^~[]')<CR><CR>
:vnoremap <silent> ,? y?<C-R>=escape(@", '\\/.*$^~[]')<CR><CR>

" 只在下列文件类型被侦测到的时候显示行号,普通文本文件不显示

:runtime! ftplugin/man.vim
set keywordprg=dicty
ab ssh #!/bin/bash<CR><CR>
ab ppy #!/usr/bin/python<CR><CR>
ab ppl #!/usr/bin/perl<CR><CR><{}>
ab rru #!/usr/bin/ruby<CR><CR><{}>

2.在VIM查看man帮助文档:

VIM本身就提供了快捷键,让我们很方便的查看光标所在位置的函数的帮助文档──只需在正常模式下将光标放到待查函数位置,然后输入K(大写)即可。
但是这样的做法,会将当前打开的窗口关闭,等看完退出才能重新打开。

 

3.在VIM上进行直接编译:
             先在源代码上生成一个Makefile文件,然后直接在VIM上执行Make命令

 

4.在VIM上进行直接调式:

本节所用命令的帮助入口:

:help vimgdb 

在UNIX系统最初设计时,有一个非常重要的思想:每个程序只实现单一的功能,通过管道等方式把多个程序连接起来,使之协同工作,以完成更强大的功能。程序只实现单一功能,一方面降低了程序的复杂性,另一方面,也让它专注于这一功能,把这个功能做到最好。就好像搭积木一样,每个积木只提供简单的功能,但不同的积木垒在一起,就能搭出大厦、汽车等等复杂的东西。

从UNIX系统(及其变种,包括Linux)的命令行就可以看出这一点,每个命令只专注于单一的功能,但通过管道、脚本等把这些命令揉合起来,就能完成复杂的任务。

vi/vim的设计也遵从这一思想,它只提供了文本编辑功能(与Emacs的大而全刚好相反),而且正如大家所看到的,它在这一领域做的是如此的出色。

也正因为如此,vim自身并不提供集成开发环境所需的全部功能(它也不准备这样做,vim只想成为一个通用的文本编辑器)。它把诸如编译、调试这样功能,交给更专业的工具去实现,而vim只提供与这些工具的接口。

我们在前面已经介绍过vim与编译器的接口(即quickfix),vim也提供了与调试器的接口,这一接口就是netbeans。除此之外,还可以给vim打一个补丁,以使其支持gdb调试器。

由于netbeans接口只能在gvim中使用,而使用vimgdb补丁,无论在终端的vim,还是gvim,都可以调试。所以我更喜欢打补丁的方式,我首先介绍这种方法。

打补丁的方式,需要重新编译vim,刚好借这个机会,介绍一下vim的编译方法。我只介绍Linux上编译方法,如果你想在windows上编译vim,可以参考这篇文档:Vim: Compiling HowTo: For Windows。

[ 下载vim源代码 ]

首先我们需要下载vim的源码。到vim主页下载当前最新的vim 7.1的源代码,假设我们把代码放到~/install/目录,文件名为vim-7.1.tar.bz2。

[ 下载vimgdb补丁 ]

接下来,我们需要下载vimgdb补丁,下载页面在:

http://sourceforge.net/project/showfiles.php?group_id=111038&package_id=120238

在这里,选择vim 7.1的补丁,把它保存到~/install/vimgdb71-1.12.tar.gz。

[ 打补丁 ]

运行下面的命令,解压源码文件,并打上补丁:

cd ~/install/tar xjf vim-7.1.tar.bz2tar xzf vimgdb71-1.12.tar.gzpatch -d vim71 --backup -p0 < vimgdb/vim71.diff 

[ 定制vim的功能 ]

缺省的vim配置已经适合大多数人,但有些时候你可能需要一些额外的功能,这时就需要自己定制一下vim。定制vim很简单,进入~/install/vim71/src文件,编辑Makefile文件。这是一个注释很好的文档,根据注释来选择:

  • 如果你不想编译gvim,可以打开–disable-gui选项;
  • 如果你想把perl, python, tcl, ruby等接口编译进来的话,打开相应的选项,例如,我打开了–enable-tclinterp选项;
  • 如果你想在vim中使用cscope的话,打开–enable-cscope选项;
  • 我们刚才打的vimgdb补丁,自动在Makefile中加入了–enable-gdb选项;
  • 如果你希望在vim使用中文,使能–enable-multibyte–enable-xim选项;
  • 可以通过–with-features=XXX选项来选择所编译的vim特性集,缺省是–with-features=normal
  • 如果你没有root权限,可以把vim装在自己的home目录,这时需要打开prefix = $(HOME)选项;

编辑好此文件后,就可以编辑安装vim了。如果你需要更细致的定制vim,可以修改config.h文件,打开/关闭你想要的特性。

[ 编译安装 ]

编译和安装vim非常简单,使用下面两个命令:

makemake install 

你不需要手动运行./configure命令,make命令会自动调用configure命令。

上面的命令执行完后,vim就安装成功了。

我在编译时打开了”prefix = $(HOME)”选项,因此我的vim被安装在~/bin目录。这时需要修改一下PATH变量,以使其找到我编辑好的vim。在~/.bashrc文件中加入下面这两句话:

PATH=$HOME/bin:$PATHexport PATH 

退出再重新登录,现在再敲入vim命令,发现已经运行我们编译的vim了。

[ 安装vimgdb的runtime文件 ]

运行下面的命令,解压vimgdb的runtime文件到你的~/.vim/目录:

cd ~/install/vimgdb/tar zxf vimgdb_runtime.tgz –C~/.vim/ 

现在启动vim,在vim中运行下面的命令以生成帮助文件索引:

:helptags ~/.vim/doc 

现在,你可以使用”:help vimgdb“命令查看vimgdb的帮助了。

至此,我们重新编译了vim,并为之打上了vimgdb补丁。下面我以一个例子来说明如何在vim中完成”编码—编译—调试”一条龙服务。

[ 在vim中调试 ]

首先确保你的计算机上安装了gdb ,vimgdb支持5.3以上的gdb版本,不过最好使用gdb 6.0以上的版本。

我使用下面这个简单的例子,来示例一下如何在vim中使用gdb调试。先来看示例代码:

文件~/tmp/sample.c内容如下,这是主程序,调用函数计算某数的阶乘并打印:

/* ~/tmp/sample.c */#include <stdio.h>extern int factor(int n, int *rt);int main(int argc, char **argv){    int i;    int result = 1;    for (i = 1; i < 6; i++)    {        factor(i, &result);        printf("%d! = %d\n", i, result);    }    return 0;}  

文件~/tmp/factor/factor.c内容如下,定义了子函数factor()。之所以把它放到子目录factor/,是为了演示vimgdb可以根据调试位置自动打开文件,不管该文件在哪个目录下:

/* ~/tmp/factor/factor.c */int factor(int n, int *r){    if (n <= 1)        *r =  n;    else    {        factor(n - 1, r);        *r *= n;    }    return 0;}  

Makefile文件,用来编译示例代码,最终生成的可执行文件名为sample。

# ~/tmp/Makefilesample: sample.c factor/factor.cgcc -g -Wall -o sample sample.c factor/factor.c  

假设vim的当前工作目录是~/tmp(使用”:cd ~/tmp“命令切换到此目录)。我们编辑完上面几个文件后,输入命令”:make“,vim就会根据Makefile文件进行编译。如果编译出错,vim会跳到第一个出错的位置,改完后,用”:cnext“命令跳到下一个错误,以此类推。这种开发方式被称为quickfix,我们已经在剑不离手 – quickfix一文中讲过,不再赘述。

现在,假设已经完成链接,生成了最终的sample文件,我们就可以进行调试了。

vimgdb补丁已经定义了一些键绑定,我们先加载这些绑定:

:run macros/gdb_mappings.vim 

加载后,一些按键就被定义为调试命令(vimgdb定义的键绑定见”:help gdb-mappings“)。按<F7>可以在按键的缺省定义和调试命令间切换。

好了,我们现在按空格键,在当前窗口下方会打开一个小窗口(command-line窗口),这就是vimgdb的命令窗口,可以在这个窗口中输入任何合法的gdb命令,输入的命令将被送到gdb执行。现在,我们在这个窗口中输入”gdb“,按回车后,command-line窗口自动关闭,而在当前窗口上方又打开一个窗口,这个窗口是gdb输出窗口。现在vim的窗口布局如下(我又按空格打开了command-line窗口):

点击查看大图

小技巧: command-line窗口是一个特殊的窗口,在这种窗口中,你可以像编辑文本一样编辑命令,完成编辑后,按回车,就会执行此命令。你要重复执行某条命令,可以把光标移到该命令所在的行,然后按回车即可;你也可以对历史命令进行修改后再执行。详见”:help cmdline-window“。

接下来,在command-line窗口中输入以下命令:

cd ~/tmpfile sample 

这两条命令切换gdb的当前工作目录,并加载我们编译的sample程序准备调试。

现在使用vim的移动命令,把光标移动到sample.c的第7行和14行,按”CTRL-B“在这两处设置断点,然后按”R“,使gdb运行到我们设置的第一个断点处(“CTRL-B“和”R“都是gdb_mappings.vim定义的键绑定,下面介绍的其它调试命令相同)。现在vim看起来是这样:

点击查看大图

断点所在的行被置以蓝色,并在行前显示标记1和2表明是第几个断点;程序当前运行到的行被置以黄色,行前以”=>”指示,表明这是程序执行的位置(显示的颜色用户可以调整)。

接下来,我们再按”C“,运行到第2个断点处,现在,我们输入下面的vim命令,在右下方分隔出一个名为gdb-variables的窗口:

:bel 20vsplit gdb-variables 

然后用”v“命令选中变量i,按”CTRL-P“命令,把变量i加入到监视窗口,用同样的方式把变量result也加入到监视窗口,这里可以从监视窗口中看到变量i和result的值。

点击查看大图

现在我们按”S“步进到factor函数,vim会自动打开factor/factor.c文件并标明程序执行的位置。我们再把factor()函数中的变量n加入到监视窗口;然后按空格打开command-line窗口,输入下面的命令,把变量*r输入到变量窗口:

createvar *r 

现在,vim看起来是这样的:

点击查看大图

现在,你可以用”S“、”CTRL-N“或”C“来继续执行,直至程序运行结束。

如果你是单步执行到程序结束,那么vim最后可能会打开一个汇编窗口。是的,vimgdb支持汇编级的调试。这里我们不用进行汇编级调试,忽略即可。

如果你发现程序有错误,那么可以按”Q“退出调试(gdb会提示是否退出,回答y即可),然后修改代码、编译、调试,直到最终完成。在修改代码时,你可能并不喜欢vimgdb的键映射(例如,它把CTRL-B映射为设置断点,而这个键又是常用的翻页功能),你可以按<F7>取消vimgdb的键映射,或者你直接修改gdb_mappings.vim文件中定义的映射。

看,vim + gdb调试是不是很简单?!

我们可以再定制一下,使调试更加方便。

打开~/.vim/macros/ gdb_mappings.vim文件,在”let s:gdb_k = 0“这一行下面加上这段内容:

" easwy addif ! exists("g:vimgdb_debug_file")    let g:vimgdb_debug_file = ""elseif g:vimgdb_debug_file == ""    call inputsave()    let g:vimgdb_debug_file = input("File: ", "", "file")    call inputrestore()endifcall gdb("file " . g:vimgdb_debug_file)" easwy end 

在”let s:gdb_k = 1“这一行下面加上这段内容:

" easwy addcall gdb("quit")" end easwy 

注释掉最后一行的”call s:Toggle()“。

然后在你的vimrc中增加这段内容:

""""""""""""""""""""""""""""""" vimgdb setting""""""""""""""""""""""""""""""let g:vimgdb_debug_file = ""run macros/gdb_mappings.vim 

现在,在启动vim后,按<F7>,就进入调试模式以及设定调试的键映射。在第一次进入调试模式时,会提示你输入要调试的文件名,以后就不必再输入了。再按一次<F7>,就退出调试模式,取消调试的键映射。

利用vim的键映射(map)机制,你可以把你喜欢的gdb命令映射为vim的按键,方便多了。映射的例子可以参照~/.vim/macros/ gdb_mappings.vim。

再附上一张抓图,这是使用putty远程登录到linux上,在终端vim中进行调试。这也是我为什么喜欢vimgdb的原因,因为它可以在终端vim中调试,而clewn只支持gvim:

点击查看大图

因为我不常使用gdb调试,所以本文仅举了个简单的例子,以抛砖引玉。欢迎大家共享自己的经验和心得。

我在文章vimgdb调试时的常见问题及解决中列出了一些常见问题及其解决方法,希望对大家有帮助。

最后,让我们感谢vimgdb作者xdegaye的辛勤劳动,我们后续文章会介绍pyclewn,这是vim与gdb结合的另外一种形式,它和vimgdb同属一个项目。