最后更新于 .

之前已经详细的介绍了在 vim中使用ctags ,这篇文章我们就来详细介绍一下如何在vim中使用cscope。

首先,我们还是了解一下什么是cscope。

简单来讲,cscope主要用来协助浏览C/C++语言,他的功能要强大于ctags,不仅支持变量/函数的定义查询,还记录了函数的调用处查询等功能,所以也有说法称cscope的诞生就是为了取代ctags。

无论这个说法是否有据可依,对使用方来说,当然是希望功能越强大方便越好啦,所以这也是我们为什么讲ctags和cscope都装上的原因啦。

第二,我们来说一下vim的支持。

cscope没有ctags那么幸运,cscope在大部分的linux下的vim中是没有提供支持的(但是在windows下的gvim都提供了支持),所以,如果你打算要在linux下面使用vim+cscope,那么1,你要下载安装cscope。2,你要重新编译vim,加上支持选项: --enable-cscope 。

当然,cscope也提供了windows版(否则windows下gvim怎么和cscope搭配嘛...),分别下载地址如下:

cscope(linux):http://cscope.sourceforge.net/
cscope(windows):http://sourceforge.net/projects/mslk/files/

当然,安装的最后一步就是,不要忘记讲cscope放进的环境变量里!

第三,好了,假设你已经搭建好了vim+cscope的环境,那么现在就是我们学习怎么用的时候了

function Do_CsTag()
    if(executable("cscope") && has("cscope") )
        if(has('win32'))
            silent! execute "!dir /b *.c,*.cpp,*.h,*.java,*.cs >> cscope.files"
        else
            silent! execute "!find . -name "*.h" -o -name "*.c" -o -name "*.cpp" -o -name "*.m" -o -name "*.mm" -o -name "*.java" -o -name "*.py" > cscope.files"
        endif
        silent! execute "!cscope -b"
        if filereadable("cscope.out")
            execute "cs add cscope.out"
        endif
    endif
endf

调用这个函数就可以用cscope生成数据库,并添加到vim中,具体每个命令意义如下:

if(has('win32'))
    silent! execute "!dir /b *.c,*.cpp,*.h,*.java,*.cs >> cscope.files"
else
    silent! execute "!find . -name "*.h" -o -name "*.c" -o -name "*.cpp" -o -name "*.m" -o -name "*.mm" -o -name "*.java" -o -name "*.py" > cscope.files"

上面的函数,通过操作系统的不同,用不同的命令实现,将当前目录的源码文件导入到一个叫做cscope.files的文件中。这个文件是cscope用来生成数据库时的默认存储文件列表的文件。 不理解dir命令?看看这篇文章吧

http://hi.baidu.com/moodmusic/blog/item/888856ed309605d7b21cb141.html
silent! execute "!cscope -b"

这个命令就是csope在生成数据库,你会发现生成了一个cscope.out的文件,这个就是生成数据库,实际上如果加上参数-q来加快索引速度的话,还会生成cscope.in.out, cscope.po.out这两个文件,各个参数意义如下: -b : 默认情况下,cscope在生成数据库后,会进入cscope自己的界面,我们在vim中使用他,当然不希望有这样的界面,就可以用-b来屏蔽掉。

execute "cs add cscope.out"

最后这一步,就是在vim中添加了cscope.out这个数据库。 下面列出cscope的常用生成数据库选项:

-R: 在生成索引文件时,搜索子目录树中的代码,因为我们已经在cscope.files中把所有的文件都打印入了列表中,所以 -b: 只生成索引文件,不进入cscope的界面 -q: 生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度 -k: 在生成索引文件时,不搜索/usr/include目录 -i: 如果保存文件列表的文件名不是cscope.files时,需要加此选项告诉cscope到哪儿去找源文件列表。可以使用"-",表示由标准输入获得文件列表。 -I dir: 在-I选项指出的目录中查找头文件 -u: 扫描所有文件,重新生成交叉索引文件 -C: 在搜索时忽略大小写 -P path: 在以相对路径表示的文件前加上的path,这样,你不用切换到你数据库文件所在的目录也可以使用它了。

好了,到了这里,cscope的原理大家应该都清楚了,那么在vim中怎么使用呢? "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 查找包含本文件的文件

但是谁也不想敲这么多命令吧,所以我在vimrc中建了这样一个映射:

nmap <C-@>s :cs find s <C-R>=expand("<cword>")<CR><CR>:copen<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>:copen<CR>
nmap <C-@>t :cs find t <C-R>=expand("<cword>")<CR><CR>:copen<CR>
nmap <C-@>e :cs find e <C-R>=expand("<cword>")<CR><CR>:copen<CR>
nmap <C-@>f :cs find f <C-R>=expand("<cfile>")<CR><CR>:copen<CR>
nmap <C-@>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>:copen<CR>
nmap <C-@>d :cs find d <C-R>=expand("<cword>")<CR><CR>:copen<CR>

实际上就是参考 cscope_maps.vim 这个文件,大家可以去下载他,然后直接放到plugin目录就行。 最后,我们来说一下cscope和ctags的兼容问题。我在vimrc中配置了一段代码:

if has("cscope")
    set cscopequickfix=s-,c-,d-,i-,t-,e-
    set csto=0
    set cst
    set csverb
endif

官方解释如下:

http://vimcdoc.sourceforge.net/doc/if_cscop.html

简单来说,主要功能就是同时搜索ctags和cscope的标签,并且cscope优先扫描。

好啦,在vim(gvim)中使用cscope的介绍就到这里啦,有兴趣的朋友可以赶紧试一下啦~~

Pingbacks

  1. Vim中使用cscope | wangkangluo1 on #

    [...] 在Vim(gvim)中使用cscope | Vimer的程序世界. Related Posts 其他 &larr; vim ctags Leave a comment ?0 Comments. /* [...]

Pingbacks已打开。

Trackbacks

引用地址

评论

  1. lyndonjiang

    lyndonjiang on #

    有个疑问,您在IDE(2)里的这段代码
    if has("cscope")
    silent! execute "cs kill -1"
    endif
    和您这里的代码
    if has("cscope")
    set cscopequickfix=s-,c-,d-,i-,t-,e-
    set csto=0
    set cst
    set csverb
    endif
    都是调整cscope和ctags的兼容问题的,两者有什么区别?

    Reply

    1. Dante

      Dante on #

      呃,这个不是调整他们俩的兼容性……而是判断vim是否编译时加入了cscope支持……

      Reply

      1. lyndonjiang

        lyndonjiang on #

        那我是不是应该自己加上调整兼容性那段语句呢?

        Reply

        1. Dante

          Dante on #

          汗,我一开始以为你是说
          if has(”cscope”)这句,
          if has("cscope")
          set cscopequickfix=s-,c-,d-,i-,t-,e-
          set csto=0
          set cst
          set csverb
          endif
          这整个一段确实是调整兼容性的~~~在vimrc里面加上就可以啦

          Reply

  2. lyndonjiang

    lyndonjiang on #

    博主你好,请问一下,vim有没有什么插件或者其他手段可以实现这个功能:
    我拿一个C工程举例,
    把一个工程的所有相关头文件和C文件的文件名以及他们的目录这些信息保存成一个文件;这样下次打开这个文件,我们就可以选择打开这个工程的某些文件了,对这个工程的结构也有个很清楚的了解。

    有了这个功能再配合ctag,VIM就变得更像IDE了。

    Reply

    1. Dante

      Dante on #

      尝试一下project这个插件,应该能满足你的需求。
      http://www.vim.org/scripts/script.php?script_id=69

      Reply

      1. lyndonjiang

        lyndonjiang on #

        博主,谢谢你的提示,在你的提示下我找到了这个插件winwkspaceexplorer,这个更能满足我的要求。
        可是我水平有限,目前是Taglist和Workspace这两栏水平并列显示。
        本来我是用winmanager把Taglist和netrw(或bufexplorer)上下显示在一栏里,可是用了这个Workspace插件后就不行了。
        我的目标是可以把Workspace,Taglist,netrw(bufexplorer)显示在上下一栏里。我尝试了let g:winManagerWindowLayout='Workspace|TagList|FileExplorer,BufExplorer',这句不行。

        Reply

      2. lyndonjiang

        lyndonjiang on #

        多谢楼主了,上面那个问题我自己搞定了,
        因为winwkspaceexplorer这个插件的关键字是WKSpaceExplorer,不是Workspace,所以用这句话就好了nmap wk :WKSpace%
        let g:winManagerWindowLayout = 'WKSpaceExplorer|TagsExplorer|FileExplorer|BufExplorer'。
        没有用竖直一起显示,那样太浪费空间,用了ctrl+n来切换了,这样看起来舒服。
        还在_vimrc里加了这句话nmap wk :WKSpace%
        这样我可以直接打开编辑好的.vimwks文件,按wk就能直接生成工程目录了。
        嘿嘿,把这些插件和vimrc备份起来去。

        Reply

  3. lyndonjiang

    lyndonjiang on #

    我爱死这个插件了,现在我的Vim真是比IDE好用多了,但是有个美中不足。就是这个工程被打开后,工程下每个Group(这个插件里是叫filter)是默认完全展开的,这样的话如果大工程的话会很悲剧。
    我想要实现默认不展开的话只能修改下插件文件本身了。
    我看了一下恐怕可以在下一段代码前加个if语句,但是我不知道怎么加。我把下段代码全部注释了,可以“实现”无论怎么点,该filter都不能被展开。
    for lll in sort(keys(s:wksDict[l]['filters'][ll]['files']))
    let l:temp = s:spacesString[0:l:spaces].lll
    put=l:temp
    endfor
    博主有空的话指导我一下吧,谢谢!

    Reply

    1. Dante

      Dante on #

      这个插件我之前还真没用过……我研究一下哦,等有消息就给你留言~~

      Reply

      1. lyndonjiang

        lyndonjiang on #

        好,反正这一页现在是我的浏览器首页

        Reply

        1. Dante

          Dante on #

          受宠若惊,受宠若惊啊……,哈哈,放心哦,我给你留言你会收到邮件的~~

          Reply

    2. grassofhust

      grassofhust on #

      那段代码我感觉是加空格缩进的

      关闭的话应该是fold
      set fdm=indent

      还没有看那个插件,只是根据描述猜测的。

      Reply

      1. lyndonjiang

        lyndonjiang on #

        "Lets display all the files under the filter
        for lll in sort(keys(s:wksDict[l]['filters'][ll]['files']))
        let l:temp =s:spacesString[0:l:spaces].lll
        put=l:temp
        endfor
        那你应该是猜错了:)这段代码上面有注释的。

        Reply

  4. pwangeng

    pwangeng on #

    function Do_CsTag()
    这个函数如何使用? 在vim内用:function Do_CsTag()没有作用

    Reply

  5. vimBenginer

    vimBenginer on #

    太棒了,真没想到能用dir生成cscope.files

    Reply

    1. 依云

      依云 on #

      我一般是用 find 来生成的 :-P

      Reply

      1. Dante

        Dante on #

        find是windows原生的命令吗?装了个mingw,结果都知道是谁的命令了。。。

        Reply

        1. 依云

          依云 on #

          不是。不过这里 http://unxutils.sourceforge.net/ 有Windows版的。

          Reply

    2. 可可火山

      可可火山 on #

      今天想用cscope for windows,找怎么生成list文件,又找到这里来了。

      dir帮助瞄了遍,就发现已经google出结果了~ nice

      Reply

      1. Dante

        Dante on #

        呵呵,cscope确实不错,就是基于他的插件有点少~~

        Reply

  6. 可可火山

    可可火山 on #

    C:\workspace\jdk6source&gt;cscope -Rbkq -i cscope.files
    cscope: -q option mismatch between command line and old symbol database

    Input file specified two times.

    cscope: cannot create inverted index; ignoring -q option
    cscope: removed files ncscope.in.out and ncscope.po.out

    奇怪,-q参数不支持还是啥的,没有生成index,工作的超慢,我jdk6的cscope.out有70M左右,find一下要卡一会儿,好像哪里有瞄到windows版-q参数的问题,现在找不着了,额~

    Reply

    1. Dante

      Dante on #

      呃,没尝试用他来生成java的呢,我在windows版本下加上-q的时候也会报错,据说会加快索引速度

      Reply

      1. ssddn

        ssddn on #

        出错是由于它找不到对应的sort命令(windows带的sort.exe不行,得用GNU的sort)导致的,如果在cygwin环境下执行这个命令就应该没有问题了。

        Reply

        1. Dante

          Dante on #

          原来如此,多谢指教~~~~

          Reply

  7. 是否应该要修改一下

    是否应该要修改一下 on #

    你好,首先非常感谢你的博文,的确让我获益非浅呀,但是我发现:
    silent! execute "!dir /b *.c,*.cpp,*.h,*.java,*.cs &gt;&gt; cscope.files"
    这句是否应该将“&gt;&gt;”改为“&gt;”,因为如果我在一个目录下多次生成数据库时,cscope.files里面的内容会多次复制,最后导致find出来的数据也是多次重复的。

    Reply

    1. Dante

      Dante on #

      呵呵,多谢多谢,确实该改一下~

      Reply

  8. ssddn

    ssddn on #

    用dir只能生成当前目录的文件列表,使用for命令可以像Linux下的find一样遍历目录树。
    请将下面两行命令copy到bat文件中,并执行,如想在命令行上直接执行,请将命令中两处%%a改为%a。
    del cscope.files
    for /r . %%a in (*.c,*.cpp,*.h,*.hpp) do echo %%a &gt;&gt; cscope.files

    Reply

    1. Dante

      Dante on #

      这样啊~对windows下的命令不熟,呵呵~~多谢~~

      Reply

  9. 吴叔

    吴叔 on #

    弱弱的问一下nmap s :cs find s =expand(""):copen这个里面的@什么键?谢谢博主

    Reply

    1. Dante

      Dante on #

      呃,@就是键盘左上的2。。。。

      Reply

  10. iroger

    iroger on #

    我很想用这个,但不知道好不好用,你给建意一下吧! 呵呵!

    Reply

  11. 奥西里斯

    奥西里斯 on #

    博主你好……我现在用的cscope,查找到结果却无法跳转……

    如果在命令行里面输入的话就会提示
    处理 BufEnter 自动命令 "*" 时发生错误:
    E344: cdpath 中找不到目录 "funcs"
    E472: 命令执行失败

    感觉上应该是当前目录不是根目录,而cscope却是从当前目录进行跳转的,这个要怎么处理呢

    Reply

  12. 小杨

    小杨 on #

    在源代码根目录上执行Do_CsTag(),
    根目录下有很多目录, 生成的cscope.files包含所有目录的文件, 但在子目录里查找函数定义时, 会出现
    E429: File 'agent/xxx.cpp" does not exist, 怎么办吖?

    Reply

    1. Dante

      Dante on #

      :set tags,看一下加载的tags路径是否正确

      Reply

      1. 小杨

        小杨 on #

        直接在子目录再生成一次Do_CsTag()就行了,
        cscope + ctag, 生成后自动补全插件omnicomplete下打左括号时会打开相应的文件(preview), set completeopt=menu时仍无效, 且光标会跳到taglist的函数列表那....引结吖 

        Reply

  13. jwkljh

    jwkljh on #

    if has("cscope")
    set csto=0
    set cst
    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

    我想根据项目或代码的路径选择对应的cscope.out数据库,但是上面的脚本好像不起作用,我用的windows下的gvim,跪求大师指导。

    Reply

  14. 月下幽杳

    月下幽杳 on #

    问下用vim调用java编译器,怎么把编译错误信息收集到quickfix窗口

    Reply

    1. Dante

      Dante on #

      :help quickfix,是有办法的,文档的实例代码里就有java的。

      Reply

  15. HelloKitty

    HelloKitty on #

    请问楼主你最下面介绍的快捷键映射分别代表哪几个快捷键啊?

    Reply

  16. 火冷

    火冷 on #

    按说明修改了_vimrc文件,现在打开空白的gvim,也会先闪下cmd窗口生成cscope.files,怎么增加格式判断?

    Reply

发表评论