使用vim + cscope/ctags


 

使用vim + cscope/ctags,就能夠實現Source Insight的功能,可以很方便地查看分析源代碼。


關鍵詞: vim, cscope, ctags, tags

1. 查看vim是否支持cscope
    $ vim --version | grep cscope 

2. 編譯支持cscope的VIM(--enable-cscope)
    # USE="bash-completion cscope nls perl python -acl -gpm -minimal -ruby -vim-pager -vim-with-x" emerge vim 
    # emerge -av dev-util/cscope
    # emerge -av dev-util/ctags
    $ which cscope
    $ which ctags

3. 查看幫助
    $ man cscope
    $ man ctags
    :help cscope (vim command)
    參考[1]  http://vimcdoc.sourceforge.net/doc/if_cscop.html

4. 使用cscope[2]
    當前目錄有main.c,其中調用了cstest.c中的print(),此函數在cstest.h中進行了聲明。
    使用下面的命令生成代碼的符號索引文件:
    $ cscope -Rbkq
    這個命令會生成三個文件:cscope.out, cscope.in.out, cscope.po.out。

    其中cscope.out是基本的符號索引,后兩個文件是使用"-q"選項生成的,可以加快cscope的索引速度。上面命令的參數含義如下:
    -R: 在生成索引文件時,搜索子目錄樹中的代碼
    -b: 只生成索引文件,不進入cscope的界面
    -d: 只調出cscope gui界面,不跟新cscope.out
    -k: 在生成索引文件時,不搜索/usr/include目錄
    -q: 生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度
    -i: 如果保存文件列表的文件名不是cscope.files時,需要加此選項告訴cscope到哪兒去找源文件列表。可以使用"-",表示由標准輸入獲得文件列表。
    -I dir: 在-I選項指出的目錄中查找頭文件
    -u: 掃描所有文件,重新生成交叉索引文件
    -C: 在搜索時忽略大小寫
    -P path: 在以相對路徑表示的文件前加上的path,這樣,你不用切換到你數據庫文件所在的目錄也可以使用它了。    

    在缺省情況下,cscope在生成數據庫后就會進入它自己的查詢界面,一般不用這個界面,所以使用了"-b"選項。如果已經進入了這個界面,按CTRL-D退出。 

    接下來可以在vim里瀏覽代碼了
    $ vim main.c
    在vim里命令狀態下添加符號索引庫
    : cscope add cscope.out
    然后可以查看相應的函數定義或文件,ctrl+t返回。
    : cscope find g print
    : cscope find f cstest.h
    
    #注意# 所生成的cscope.out和tags文件要在打開VIM所在的文件夾,否則VIM無法找到相關符號信息。

5. 創建相應的快捷鍵
    將以下內容添加到~/.vimrc中,vim會自動加載當前目錄下的符號索引cscope.out,可以使用ctrl+t、ctrl+]等。
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" cscope setting

if has("cscope")
  set csprg=/usr/bin/cscope              "指定用來執行 cscope 的命令
  set csto=1                             "先搜索tags標簽文件,再搜索cscope數據庫
  set cst                                "使用|:cstag|(:cs find g),而不是缺省的:tag
  set nocsverb                           "不顯示添加數據庫是否成功
  " add any database in current directory
  if filereadable("cscope.out")
 cs add cscope.out                   "添加cscope數據庫
  endif
  set csverb                             "顯示添加成功與否
endif

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是先同時按ctrl+@鍵,之后再按一個g。功能就是查看當前光標所在符號的定義。

6. vim閱讀代碼
    添加cscope符號索引數據庫后,可以調用"cscope find"命令進行查找,vim支持8種cscope的查詢功能。如在代碼中查找調用work()函數的函數,可以在vim命令狀態下輸入":cs find c work",回車即可。還可以進行字符串查找,它會對雙引號或單引號括起來的內容查找。還可以輸入一個正則表達式,這類似於egrep程序的功能。
    :cs help (vim command下查詢)

    s: 查找C語言符號,即查找函數名、宏、枚舉值等出現的地方
    g: 查找函數、宏、枚舉等定義的位置,類似ctags所提供的功能
    d: 查找本函數調用的函數
    c: 查找調用本函數的函數
    t: 查找指定的字符串
    e: 查找egrep模式,相當於egrep功能,但查找速度快多了
    f: 查找並打開文件,類似vim的find功能
    i: 查找包含本文件的文件

7. 查看閱讀c++代碼[3]
    cscope缺省只解析C文件(.c和.h)、lex文件(.l)和yacc文件(.y),雖然它也可以支持C++以及Java,但它在掃描目錄時會跳過C++及Java后綴的文件。如果希望cscope解析C++或Java文件,需要把這些文件的名字和路徑保存在一個名為cscope.files的文件。當cscope發現在當前目錄中存在cscope.files時,就會為cscope.files中列出的所有文件生成索引數據庫。
    下面的命令會查找當前目錄及子目錄中所有后綴名為".h", ".c", "cc"和".cpp"的文件,並把查找結果重定向到文件cscope.files中。然后cscope根據cscope.files中的所有文件,生成符號索引文件。最后一條命令使用ctags命令,生成一個tags文件,在vim中執行":help tags"命令查詢它的用法。它可以和cscope一起使用。

    $ find . -name "*.h" -o -name "*.c" -o -name "*.cc" -o "*.cpp" > cscope.files
    $ cscope -bkq -i cscope.files
    $ ctags -R

8. 在vim中使用tags查找符號

    查看ctags幫助
    $ man ctags
    :help ctags  (vim command)
    :help tags   (vim command)
    
    在源代碼根目錄下執行 ctags -R 命令用來為程序源代碼生成標簽文件,其-R選項表示遞歸操作,同時為子目錄也生成標簽文件。vim利用生成的標簽文件,可以進行相應檢索、並在不同的文件C語言元素之間來回切換。
    $ ctags -R

    A) vim中使用":tag xxx"跳到函數或數據結構xxx處。使用tag命令時,可以使用TAB鍵進行匹配查找,繼續按TAB鍵向下切換。
    某個函數有多個定義時 
    :tag
    跳到第一個定義處,優先跳轉到當前文件
    :tnext
    跳到第一個
    :tfirst
    跳到前count個
    :[count]tprevious
    跳到后count個
    :[count]tnext
    跳到最后一個
    :tlast
    你也可以在所有tagname中選擇:
    :tselect tagname 
    如果想跳到包含block的標識符":tag /block" 然后用TAB鍵來選擇。這里'/'就是告訴vim 'block'是一個語句塊標簽。

    B) 用"ctrl+]"快捷鍵,跳轉到光標所在函數標識符的定義處。

    C) 使用"ctrl+t"退回上層。 如果想在以write_開頭的標識符中選擇一下, :tselect /^write_ 這里,'^'表示開頭,同理,'$'表示末尾。

    D) 運行vim的時候,必須在"tags"文件所在的目錄下運行。否則,運行vim的時候還要用":set tags=xxx"命令設定"tags"文件的路徑,這樣vim才能找到"tags"文件(這兒我們已經設置過了"set tags=tags;",在子目錄中也可以使用)。

    E) 在函數中移動光標的快捷鍵:
    [{ 轉到上一個位於第一列的"{"
    }] 轉到下一個位於第一列的"{"
    { 轉到上一個空行
    } 轉到下一個空行
    gd 轉到當前光標所指的局部變量的定義
    * 轉到當前光標所指的單詞下一次出現的地方
    # 轉到當前光標所指的單詞上一次出現的地方

9. taglist插件使用[4]
    該插件可以像Source Insight那樣將當前文件中的宏、全局變量、函數等tag顯示在Symbol窗口,用鼠標點上述tag,就跳到該tag定義的位置;可以按字母序、該tag所屬的類或scope,以及該tag在文件中出現的位置進行排序;如果切換到另外一個文件,Symbol窗口更新顯示這個文件中的tag。taglist依賴於ctags。

    要使用taglist插件,必須滿足:
    1).打開VIM的文件類型自動檢測功能;
    2).系統中裝了Exuberant ctags工具,並且taglist能夠找到此工具(因為taglist需要調用它來生成tag文件);
    3).你的VIM支持system()調用;

    安裝taglist插件
    # emerge -av app-vim/taglist

    查看幫助
    :help helptags
    :help taglist
    :help taglist-intro

    打開tag窗口
    :TlistToggle 

    .vimrc中配置如下
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" ctags setting
set tags=./tags,./../tags,./*/tags;

" Tag list (ctags)

filetype on                            "文件類型自動檢測

if MySys() == "windows"                "設定windows系統中ctags程序的位置
  let Tlist_Ctags_Cmd = 'ctags'
elseif MySys() == "linux"              "設定linux系統中ctags程序的位置
  let Tlist_Ctags_Cmd = '/usr/bin/ctags'
endif

let Tlist_Show_One_File = 1            "不同時顯示多個文件的tag,只顯示當前文件的
let Tlist_Exit_OnlyWindow = 1          "如果taglist窗口是最后一個窗口,則退出vim
let Tlist_Use_Right_Window = 1         "在右側窗口中顯示taglist窗口 
 
map <silent> <F8> :TlistToggle<cr>     "在映射F8鍵打開tags窗口
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

10. 建立索引數據庫、查看內核源碼[5]
liuby@liuby ~/git/kernel/linux-2.6.30.5 $ make cscope
 GEN     cscope
liuby@liuby ~/git/kernel/linux-2.6.30.5 $ make tags
 GEN     tags
liuby@liuby ~/git/kernel/linux-2.6.30.5 $ ls tags -l
-rw-r--r-- 1 liuby liuby 89648962 03-12 06:12 tags
liuby@liuby ~/git/kernel/linux-2.6.30.5 $ ls cscope.* -l 
-rw-r--r-- 1 liuby liuby    403901 03-12 06:02 cscope.files
-rw-r--r-- 1 liuby liuby 182562815 03-12 06:04 cscope.out
-rw-r--r-- 1 liuby liuby  23011328 03-12 06:04 cscope.out.in
-rw-r--r-- 1 liuby liuby 133571208 03-12 06:04 cscope.out.po

參考文獻:
[1] http://vimcdoc.sourceforge.net/doc/if_cscop.html
[2] http://easwy.com/blog/archives/advanced-vim-skills-cscope/
[3] http://easwy.com/blog/archives/vim-cscope-ctags/
[4] http://easwy.com/blog/archives/advanced-vim-skills-taglist-plugin/
[5] http://www.kongove.cn/web/doc/vim-ctags-cscope-source.html

感謝易水博客 [ http://easwy.com/blog/ ] 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM