2009/02/17

打造自己的VIM: 源碼追蹤(ctags+cscope)及預覽視窗SrcExpl

Windows上重量級的源碼追蹤程式Source Insight,其最重要的功能之一就是他能依據程式內的函式名、結構名或其他源碼內使用之關鍵字,快速跳躍至該關鍵字的宣告或定義處。

超強編程軟體 - VIM - 也有這種能力。我們用VIM doc裡的文件來解釋一下什麼叫根據源碼關鍵字跳到定義處。如下圖:





我 們在write_block函式內用到write_line,若我們想看一下write_line的定義,在VIM裡只需將游標移到write_line 上,按下Ctrl+]就可以跳到該函式處。更進一步,在write_line裡頭用到write_char,我們也只需在write_char上按下 Ctrl+],又能再跳到write_char定義處。這樣的功能在追蹤大型的程式時是很方便的功能,在VIM要有這樣的能力只需一些小小的設定就能達 到。

本文參考2份VIM document,分別為[usr_29]及[tagsrch]。


ctags安裝及使用


要使用源碼追蹤的功能預設是必需在工作目錄下存在一個檔名為tags的檔案,該檔案會紀錄源碼內所有的關鍵字出現位置,tags file的產生可藉由ctags這支程式,ctags的安裝方法我在之前的文章[TagList]已經有介紹過了,所以這裡不再累述,需要安裝的人請參考那篇文章。

產生tags方式,必需先切換工作目錄至源碼根目錄下,並輸入下面指令(在命令提示字元下則不要輸入:!喔):

:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .

如此就會產生一名為tags的檔案在此目錄下,是不是很容易呀。

另 外,還有一種情形值得一提,有時源碼庫是很大一包,每次執行ctags產生tags file可能會需要一段不短的時間,而我們維護的程式可能只是這一大包源碼庫的其中一個小小的資料匣,因此我們有時會只希望更新我們維護的資料匣,而不是 一大包的源碼庫。這種情形可以只在源碼的所在位置產生一個local tags file,並且再藉著tags option將local tag file加入tag搜尋檔案中。

首先在目前編輯檔案所在位置產生tags:

:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q -f "%:p:h\\tags" "%:p:h"

因 為tags option預設為./tags,tags (輸入:set tags即會顯示出來),因此只要產生local tags file即會自動被加入tag搜尋檔案中,不需再做設定tag搜尋檔案的工作。在網路上可以查到許多教各位如何將STL的header加入tags搜尋檔 案中,它的方法也是先在STL源碼庫內使用ctags產生tags file,接著再設定tag option。

有了tags files我們便可以開始追蹤源碼了,追蹤源碼我較常用到這幾個功能,當然這些功能有不少被後後的快速鍵給取代掉了:

Ctrl+] " 根據游標所在位置的字串常做關鍵字,跳進去(快速鍵:tj)。
Ctrl+t " 跳出來。
:tselect " 當有多個關鍵字在tags file中被找到時,可用tselect來選。
:tags " 查看現跳到那裡了快速鍵:ta)。
:tnext " 跳到下一個被找到的tag(快速鍵:tn)。
:tprev "跳到前一個被找到的tag(快速鍵:tp)。



cscope安裝及使用


cscope與ctags十分類似,只是它有些功能是ctags所沒有的(cscope似乎可以完全取代ctags ??),所以我在這裡就稍微提下它的安裝及用法。

首先要安裝cscope.exe跟之前安裝ctags一樣,也是使用cygwin即可安裝它的windows版本,這裡我就不再贅述。另外對於VIM有人已經製作了它的keymapping及自動載入cscope reference file(cscope.out)的script [cscope_maps.vim],將它下載後放至vim72\plugin裡即可。

如同ctags,cscope也要建立一個cscope.out的參考檔。建立方式如下:

cscope -Rbkq

除了讓它自己去搜尋所有檔案,你也可以自己指定一份檔案列表,我們可以先用find(cygwin, NOT windows find)找出所有.cpp及.h的檔案再讓cscope.exe去讀取。如下:

find . -name "*.h" -o -name "*.c" -o -name "*.cc" > cscope.files
cscope -Rbkq cscope.files


以下為cscope_maps.vim提供的功能及對應的按鍵:

Ctrl+\ s "s表Symbol,列出所有參考到游標所在字串的地方,包含定義和呼叫。
ctrl+\ g "g表Global,與ctags的Ctrl+]相同。
ctrl+\ c "c表Call,列出所有以游標所在字串當函數名的地方。
ctrl+\ t "t表Text,列出專案中所有出現游標所在字串的地方。
ctrl+\ f "f表File,以游標所在字串當檔名,開啟之。
ctrl+\ i "i表Include,以游標所在字串當檔名,列出所有include此檔的檔案。
ctrl+\ d "d表calleD,以游標所在字串當函式名,列出所有此函式呼叫的函式。


若想知道其他更詳細的用法可以參考:cs內的內容。

ps. 若是出現"沒有cscope連線",這應該是你的工作目錄下沒有cscope.out檔案,若是想不想關掉VIM卻想自行加入cscope連線,可以參考:cs connect指令。

參考資料: http://www.yuanma.org/data/2006/0908/article_1487.htm

快速鍵設定

我設定了2個快速鍵來建立global and local tags file,分別為Ctrl+F12及F12。以及多個快速鍵來來方便tag的使用,其設定如下:

map :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q -f "%:p:h\\tags" "%:p:h"
map :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
map :!cscope -Rbkq
nmap :exec "tjump ".expand("")
nmap :exec "ts ".expand("")<>CR>
nmap :exec "tnext"
nmap :exec "tprevious"


預覽視窗 SrcExpl

狂熱於使用VIM的開發人員至此還不是很滿意,他們想為什麼我們不分割一個視窗來做源碼預覽的效果,[SrcExpl]也就因此誕生了。它的截圖如下:



呼 叫SrcExpl預覽視窗為指令:SrcExplToogle,以上圖為例原先在編輯init/main.c,在叫出SrcExpl預覽視窗後,當我們移 到任意的關鍵字上,SrcExpl預覽視窗就會自動將查詢到的tags顯示在視窗內。上圖為游標在boot_cpu_init()後,預覽視窗即馬上顯示 函式定義。

說老實話,我大部份的時候很喜歡這個套件,但對於大project我很討厭它。主要原因是對於很大的project時,它tag檔很大,如果我開著這個功能我整個VIM都頓頓的,整個用起來很煩。各位看倌還是自己視情形用它吧

另外,呼叫SrcExpl預覽視窗,我也定義快速鍵F7

map :SrcExplToggle

1 comment:

Xerothermic said...

Cscope好像不能連到在header裡的inline function,ctags就行。我本來也都是用cscope的,就因為這點才換去用ctags