介绍一下gnu global,比cscope更方便更快速的索引工具

http://forum.ubuntu.org.cn/viewtopic.php?f=68&t=343460

貌似vim众很少用gnu global啊,都只见着emacs众在用,我觉得有必要在vim众中推广一下。

gnu global是一个类似cscope的工具,也能提供源文件之间的交叉索引。

其独到之处在于,当你生成索引文件以后,再修改整个项目里的一个文件,然后增量索引的过程非常快。

安装过程就不说了,根据各自发行版不同,自个儿装吧。

安装好以后,有global、gtags、gtags-cscope三个命令。global是查询,gtags是生成索引文件,gtags-cscope是与cscope一样的界面。

example:
代码:
$ cd project/
$ gtags


这样就生成了整个目录的索引文件,包括GTAGS、GRTAGS、GPATH三个文件。

你也可以先用find命令生成一个文件列表,叫gtags.files,然后再执行gtags,就会只索引gtags.files里的文件。

example:
代码:
$ cd project/
$ find . -name "*.[ch]" > gtags.files
$ gtags


查询使用的命令是global和gtags-cscope。前者是命令行界面,后者是与cscope兼容的ncurses界面。这里就不多介绍了,重点是如何在vim里查询:

首先进入vim,然后:

example
代码:
:set cscopeprg=gtags-cscope
:cs add GTAGS


然后就可以像cscope一样,用cs find g等命令进行查询了。

当我们更改了某个文件以后,比如project/subdir1/subdir2/file1.c,想更新索引文件(索引文件是project/GTAGS),只消这样:

example:
代码:
$ cd project/subdir1/subdir2/
$ vim file1.c
$ global -u


global -u这个命令会自动向上找到project/GTAGS,并更新其内容。而gtags相对于cscope的优势就在这里:增量更新单个文件的速度极快,几乎是瞬间完成。有了这个优势,我们就可以增加一个autocmd,每次:w的时候自动更新索引文件。

我的设置如下:
代码:
" settings of cscope.
" I use GNU global instead cscope because global is faster.
set cscopetag
set cscopeprg=gtags-cscope
set cscopequickfix=c-,d-,e-,f-,g0,i-,s-,t-
nmap <silent> <leader>j <ESC>:cstag <c-r><c-w><CR>
nmap <silent> <leader>g <ESC>:lcs f c <c-r><c-w><cr>:lw<cr>
nmap <silent> <leader>s <ESC>:lcs f s <c-r><c-w><cr>:lw<cr>
command! -nargs=+ -complete=dir FindFiles :call FindFiles(<f-args>)
au VimEnter * call VimEnterCallback()
au BufAdd *.[ch] call FindGtags(expand('<afile>'))
au BufWritePost *.[ch] call UpdateGtags(expand('<afile>'))

function! FindFiles(pat, ...)
let path = ''
for str in a:000
let path .= str . ','
endfor

if path == ''
let path = &path
endif

echo 'finding...'
redraw
call append(line('$'), split(globpath(path, a:pat), '\n'))
echo 'finding...done!'
redraw
endfunc

function! VimEnterCallback()
for f in argv()
if fnamemodify(f, ':e') != 'c' && fnamemodify(f, ':e') != 'h'
continue
endif

call FindGtags(f)
endfor
endfunc

function! FindGtags(f)
let dir = fnamemodify(a:f, ':p:h')
while 1
let tmp = dir . '/GTAGS'
if filereadable(tmp)
exe 'cs add ' . tmp . ' ' . dir
break
elseif dir == '/'
break
endif

let dir = fnamemodify(dir, ":h")
endwhile
endfunc

function! UpdateGtags(f)
let dir = fnamemodify(a:f, ':p:h')
exe 'silent !cd ' . dir . ' && global -u &> /dev/null &'
endfunction


解释几句:

1. 我增加了一个命令叫FindFiles,是用来生成gtags.files文件的,用法如下:

代码:
:FindFiles {pattern} subdir1 subdir2 ...


然后找到的文件就会都添加到当前buffer的最后。

比如,我们用git刚下下来一整套kernel的源码,放在linux-2.6目录下,然后我想生成列表文件,就可以这样:

代码:
:e gtags.files
:FindFiles **/*.[ch] arch/x86 arch/arm block crypto ...
:w


只增加自己想要的目录,而不要的就不增加。

2. 我添加了三条autocmd,其中:

代码:
au VimEnter * call VimEnterCallback()
au BufAdd *.[ch] call FindGtags(expand('<afile>'))


这两条命令会在你打开一个c文件的时候,自动向上查找GTAGS文件,找到以后就会执行:cs add命令添加这个GTAGS文件。

代码:
au BufWritePost *.[ch] call UpdateGtags(expand('<afile>'))


这条命令会在你修改一个c文件并:w以后,自动进入c文件所在目录并执行"global -u"更新索引文件。

最后,还有一个问题,cscope有一个-f参数,这个参数可以指定cscope.out文件的路径。而gtags-cscope的哲学不一样,它是自己一路向上寻找GTAGS文件,所以没有-f参数。而vim调用:cs add的时候,是会使用-f参数的。这样,当:cs add GTAGS文件的时候,就不能指定当前目录的子目录以外的路径。这也导致:cs add命令只能使用一个GTAGS文件。

针对这个问题,我写了一个vim的patch http://forum.ubuntu.org.cn/viewtopic.php?f=68&t=342099,在fork出gtags-cscope子进程以后会把子进程chdir()到GTAGS文件所在的目录,这样就OK了。




diff -r f33296ed67ea src/if_cscope.c --- a/src/if_cscope.c Wed Aug 17 20:33:23 2011 +0200 +++ b/src/if_cscope.c Thu Aug 18 10:13:26 2011 +0800 @@ -960,7 +960,27 @@ /* run the cscope command; is there execl for non-unix systems? */ #if defined(UNIX) - (void)sprintf(cmd, "exec %s -dl -f %s", prog, csinfo[i].fname); +#include <unistd.h> +#include <libgen.h> + + if (strcmp(prog, "gtags-cscope") == 0) + { + char *fname = NULL, *dname = NULL; + + fname = strdup(csinfo[i].fname); + if (fname) + { + dname = dirname(fname); + (void)chdir(dname); + free(fname); + } + + (void)sprintf(cmd, "exec %s -dl", prog); + } + else + { + (void)sprintf(cmd, "exec %s -dl -f %s", prog, csinfo[i].fname); + } #else /* WIN32 */ (void)sprintf(cmd, "%s -dl -f %s", prog, csinfo[i].fname);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值