標籤:style io ar os 使用 java for sp strong
背景在我平時用Emacs編寫C代碼時,經常需要進行代碼的跳轉,主要需求為函數定義的跳轉,某個具體函數的調用尋找,某個結構體的定義跳轉以及結構體中具體某一項的跳轉等,GNU Global就能完全滿足我的這個需求,所以習慣了Emacs的人可以將Source Insight扔開了。
GNU Global簡介GNU Global全稱為GNU Global source code tagging system,官方定義為GNU Global是一個可以跨越各種環境的代碼標記系統,例如在Emacs,VI,Less Viewer,Bash Shell甚至在Web瀏覽器中使用。可以通過GNU Global尋找局部變數,函數,宏,結構體,類並且方便的跳轉到你想要的位置,在進行大型項目開發時,GNUL Global可以包含許多子目錄,#ifdef語句和許多main函數,它有點向平時經常使用的ctags和etags,但是有和這兩個tag工具比起來GNU Global有以下兩點更為強大:
- 和編輯器不具有強綁定關係,所以可以很方便的將其用於各種編輯環境,無論是Emacs的忠實使用者還是Vim的粉絲都可以盡情的使用它來進行代碼跳轉
- 具有比較強大的尋找定義和引用的能力,對於代碼閱讀來說這個能力已經足夠了
GNU Global具有強大的跨平台能力,無論是在Linux還是在BSD系統還是Windows都可以使用。GNU Global具有以下功能:
- 內建6種文法剖析器(定義和引用)C,C++,Yacc,Java,PHP4和彙編
- 通過Ctags的文法解析外掛程式可以支援25中語言(定義和引用)Awk, Dos batch, COBOL, C, C++, C#, Erlang,Fortran, Java, JavaScript, Lisp, Lua, Pascal, Perl, PHP, Python, Ruby, Matlab, OCaml, Scheme, Tcl, TeX, Verilog, Vhdl and Vim
- Shell命令列
- Bash Shell
- Vi編輯器(Vim)
- Less Viewer
- Emacs編輯器(Emacs,Mule,XEmacs)
- Web瀏覽器
- Doxygen文檔系統
- 通過特殊的符號錶快速尋找局部變數
- 不僅能夠尋找定義還可以尋找引用
- 允許重複的tags
- 給出匹配的路徑
- 預設分層尋找
- 不僅僅實在代碼層級尋找,還可以在庫中尋找
- 產生補全列表
- 支援多種格式輸出
- 允許指定標記檔案
- 支援POSIX 1003.2Regex
- 支援idutils作為外部搜尋引擎
- 產生的tag檔案獨立於各種體繫結構
- 支援隨時更新tag檔案
- 支援新語言的文法解析外掛程式
- 支援自訂gtags.conf
- 使用壓縮格式來節省空間的
- 支援C/S環境(TRAMP)
- 預設忽略可執行檔,隱藏檔案和特殊檔案
- 內建cscope程式(gtags-cscope)
- 內建grep命令(使用-g)
- 能夠很好的處理迴圈符號鏈
GNU Global使用命令列下使用GLOBAL,在開始使用之前可以看一下FAQ
| $more /your/gtags/path/FAQ |
首先我們需要使用gtags命令來產生代碼樹的tag檔案,例如當我想要瀏覽核心2.4的代碼時,只需要執行以下命令
| $cd ~/code/kernel/$gtags -v |
執行完之後會發現,在kernel目錄下產生了3個tag檔案分別是GPATH,GRTAGS,GTAGS,GTAGS是定義的資料庫,GRTAGS是引用的資料庫,GPATH是路徑的資料庫。 基本用法,加入下面的是我們的分類樹
/home/user/ | |-ROOT/ <- the root of source tree (GTAGS,GRTAGS,...) | |- README ..... +---------------+ | |The function of| | +---------------+ |- DIR1/ | | | |- fileA.c ..... +---------------+ | | |main(){ | | | | func1();| | | | func2();| | | |} | | | +---------------+ | | | |- fileB.c ..... +---------------+ | |func1(){ ... } | | +---------------+ |- DIR2/ | |- fileC.c ..... +---------------+ |#ifdef X | |func2(){ i++; }| |#else | |func2(){ i--; }| |#endif | |func3(){ | | func1();| |} | +---------------+ |
此時我們在ROOT目錄下執行gtags命令產生tag檔案,可以使用global命令在代碼中搜尋相關函數,需要注意的是只能在產生TAG檔案的目錄及其子目錄中搜尋:
$ cd /home/user/ROOT$ global func1DIR1/fileB.c # func1() is defined in fileB.c$ cd DIR1$ global func1fileB.c # relative path from DIR1$ cd ../DIR2$ global func1../DIR1/fileB.c # relative path from DIR2 |
使用global的-r選項擷取相關引用:
$ global -r func2../DIR1/fileA.c # func2() is referred from fileA.c |
global支援使用Regex來進行搜尋:
$ cd /home/user/ROOT$ global ‘func[1-3]‘DIR1/fileB.c # func1, func2 and func3 are matchedDIR2/fileC.c |
global使用-x選項來擷取更多細節:
$ global func2DIR2/fileC.c$ global -x func2func2 2 DIR2/fileC.c func2(){ i++; }func2 4 DIR2/fileC.c func2(){ i--; } |
global使用-a選項時可以擷取絕對路徑:
$ global -a func1/home/user/ROOT/DIR1/fileB.c |
global使用-s選項可以搜尋沒有在GTAGS中定義的符號:
$ global -xs XX 1 DIR2/fileC.c #ifdef X |
global使用-g選項可以搜尋指定的模式:
$ global -xg ‘#ifdef‘#ifdef 1 DIR2/fileC.c #ifdef X |
global的-O選項表明只在文字檔中搜尋,-o在源檔案和文字檔中搜尋,-l選項只在目前的目錄搜尋,使用-P選項可以搜尋特定模式的路徑; 如果想在庫中搜尋相關符號,則需要在每一個GTAGSLIBPATH中執行gtags命令:
$ pwd/develop/src/mh # this is a source project$ gtags$ ls G*TAGSGRTAGS GTAGS$ global mhluip/mhlsbr.c # mhl() is found$ global strlen # strlen() is not found$ (cd /usr/src/lib; gtags) # library source$ (cd /usr/src/sys; gtags) # kernel source$ export GTAGSLIBPATH=/usr/src/lib:/usr/src/sys$ global strlen../../../usr/src/lib/libc/string/strlen.c # found in library$ global access../../../usr/src/sys/kern/vfs_syscalls.c # found in kernel $ ln -s /usr/src/lib .$ ln -s /usr/src/sys .$ gtags$ global strlenlib/libc/string/strlen.c$ global accesssys/kern/vfs_syscalls.c |
如果忘記了搜尋的符號名,可以使用-c選項來補全:
| $ global -c kmem # maybe k..k.. kmem..kmem_allockmem_alloc_pageablekmem_alloc_waitkmem_freekmem_free_wakeupkmem_initkmem_mallockmem_suballoc # This is what I need!$ global kmem_suballoc../vm/vm_kern.c $ funcs()> {> local cur> cur=${COMP_WORDS[COMP_CWORD]}> COMPREPLY=(`global -c $cur`)> }$ complete -F funcs global$ global kmem_<TAB><TAB>kmem_alloc kmem_alloc_wait kmem_initkmem_alloc_nofault kmem_free kmem_mallockmem_alloc_pageable kmem_free_wakeup kmem_suballoc$ global kmem_s<TAB>$ global kmem_suballoc../vm/vm_kern.c |
GNU Global在Emacs中的使用
$HOME/.emacs+------------------------------------------------------|(setq load-path (cons "/home/owner/global" load-path))|(autoload ‘gtags-mode "gtags" "" t) (global-set-key (kbd "M-<f1>") ‘gtags-find-file) (global-set-key (kbd "M-<f2>") ‘gtags-find-tag) (global-set-key (kbd "M-<f3>") ‘gtags-find-rtag) (global-set-key (kbd "M-<f4>") ‘gtags-find-symbol) (global-set-key (kbd "M-<f5>") ‘gtags-find-with-grep) |
- 安裝好之後在emacs中可以通過M-x使用如下命令
在瀏覽器中顯示當前螢幕 跳轉到輸入的檔案處 通過grep命令搜尋 在tag檔案中搜尋引用 在tag檔案中搜尋符號 在tag檔案中搜尋定義 從當前運算式獲得tag名並跳轉 以當前位置作為tag跳轉 在另一個視窗中開啟tag跳轉 搜尋檔案並查詢
tag名字補全 開啟gtags mode 顯示當前檔案的tag 從棧中移動到上一個點 從tag列表中選擇一個tag 選擇一個tag 通過某個事件選擇tag 在其他window中選擇tag 訪問tag檔案根目錄 |
gtags-display-browser gtags-find-filegtags-find-pattern gtags-find-rtaggtags-find-symbolgtags-find-taggtags-find-tag-by-event gtags-find-tag-from-heregtags-find-tag-other-window gtags-find-with-grepgtags-find-with-idutils gtags-make-complete-listgtags-mode gtags-parse-filegtags-pop-stack gtags-select-modegtags-select-tag gtags-select-tag-by-eventgtags-select-tag-other-window gtags-visit-rootdir |
在Emacs中使用GNU Global