第一節:
本節所用命令的幫助入口:
:help ‘tags’
:help :tag
:help :tags
:help CTRL-]
:help CTRL-T
:help vimgrep
:help cw
:help pattern
盡管相關的文章已經很多了,但tag文件實在是太有用了,所以還是啰嗦一次。
Tag文件(標簽文件)無疑是開發人員的利器之一,有了tag文件的協助,你可以在VIM查看函數調用關系,類、結構、宏等的定義,可以在任意標簽中跳轉、返回……相信使用過Source Insight的人對這些功能并不陌生,而在VIM中,此功能的實現依賴于tag文件。
對于程序來說,Tag文件中保存了諸如函數、類、結構、宏等的名字,它們所處的文件,以及如何通過Ex命令跳轉到這些標簽。它是一個純文本文件,因此你可以手工的編輯它,也可以使用腳本對其進行操作。
通常我們使用名為ctags的程序來生成這樣的tag文件。VIM能直接使用ctags程序所生成的tag文件。在UNIX系統下的ctags功能比較少,所以一般我們使用Exuberant Ctags(在大多數Linux系統上,它是缺省的ctags程序),它能夠支持多達33種程序語言,足以滿足我們開發的需要了。如果你的系統上未安裝此程序,請到http://ctags.sourceforge.net下載。
EMACS則使用etags來生成tag文件,如果希望VIM也能支持etags的tag文件格式,需要在編譯VIM時加入” +emacs_tags”選項。
Tag文件需要遵循一定的格式,由Exuberant Ctags生成的tag文件,缺省是如下格式:
{tagname} {TAB} {tagfile} {TAB} {tagaddress} {term} {field} ..
{tagname} 標識符名字,例如函數名、類名、結構名、宏等。不能包含制表符。
{tagfile} 包含 {tagname} 的文件。它不能包含制表符。
{tagaddress} 可以定位到 {tagname}光標位置的 Ex 命令。
{term} 設為“;"”。這是為了兼容Vi編輯器,使Vi忽略后面的{field}字段。
{field} .. 此字段可選,通常用于表示此{tagname}的類型是函數、類、宏或是其它。
在{tagname}、{tagfile}和{tagaddress}之間,采用制表符(TAB符,即C語言中的”\t”)分隔,也就是說{tagname}、{tagfile}中不能包含制表符。
Tag文件的開頭可以包含以“!_TAG_”開頭的行,用來在tag文件中加入其它信息。VIM能夠識別兩種這樣的標記,經常用到的是“_TAG_FILE_SORTED”標記,例如:
!_TAG_FILE_SORTED<Tab>1<Tab>{anything}
上面這個標記說明tag文件是經過排序的,并且排序時區分了大小寫,對排序的tag,VIM會使用二分法來進行查找,大大加快了查找速度;如果值為0,則表示tag文件未經排序;如果值為2,則表示tag文件是忽略大小寫排序的。
之所以在這里介紹tag文件的格式,是因為我們在后面提到的lookupfile插件中,會自己生成tag文件。
雖然ctags有為數眾多的選項,但通常我們所使用的非常簡單。還是以VIM 7.0的代碼為例,我們執行:
cd ~/src/vim70
ctags –R src
上面這條命令會在~/src/vim70/目錄下生成一個名為tags的文件,這個文件中包含~/src/vim70/src/目錄下所有.c、.h文件中的標簽。它一個文本文件,你可以用VIM打開它看一下。此文件缺省按區分字母大小寫排序,所以直接可以被VIM使用。
現在我們進入VIM,執行下面的命令:
:cd ~/src/vim70 "切換當前目錄為~/src/vim70
:set tags=tags "設置tags選項為當前目錄下的tags文件
現在,我們設置好了tags選項,接下來我們使用它:
:tag VimMain
你會看到VIM打開了src/main.c文件,并把光標定位到第167行VimMain上。
我們知道,一般主程序的函數名為main,如果你嘗試下面的命令:
:tag main
# pri kind tag file
1 F f main src/xxd/xxd.c
main(argc, argv)
2 FS d main src/if_python.c
46
Choice number (<Enter> cancels):
這里并沒有src/main.c文件,怎么回事呢?這是因為ctags并不是編譯器,它在處理編譯預處理指令受到局限,因此并沒有生成src/main.c中main()函數的標簽。你可以在生成tag文件時給ctags指定參數來解決這個問題。
或者你可以用”:grep”或”:vimgrep”來查找main(這已經超出本文的范圍了,因此只給出例子,在后續的文章再做講解):
:cd ~/src/vim70
:vimgrep /\<main\>/ src/*.c
:cw
這時下面的窗口將顯示出來,在quickfix窗口中找到我們想跳轉的位置(本例中是src/main.c),按回車,就可以跳到對應的位置了。

如果你只記得部分的標簽名,那么可以使用“tag”命令的搜索模式,你可以輸入一個VIM正則表達式來表示你所查找的名字,如:
:tag /\C\<\k\+ain\>
# pri kind tag file
1 F f VimMain src/main.c
VimMain
2 F d bindtextdomain src/vim.h
483
3 F d bindtextdomain src/vim.h
502
4 F d bindtextdomain src/vim.h
504
5 F f main src/xxd/xxd.c
main(argc, argv)
6 F d textdomain src/vim.h
488
7 F d textdomain src/vim.h
510
8 F d textdomain src/vim.h
512
9 FS d bindtextdomain src/gui_gtk.c
54
10 FS d bindtextdomain src/gui_gtk_x11.c
37
11 FS f cmdsrv_main src/main.c
cmdsrv_main(argc, argv, serverName_arg, serverStr)
12 FS d main src/if_python.c
46
13 FS d textdomain src/gui_gtk.c
51
14 FS d textdomain src/gui_gtk_x11.c
34
Choice number (<Enter> cancels):
這表示我想查找一個以一個或多個keyword開始的標簽,此標簽以ain做為結尾,在查找時區分大小寫。要讀懂這個正則表達式,請“:help pattern”。
VIM會保存一個跳轉的標簽棧,以允許你在跳轉到一個標簽后,再跳回來,可以使用“:tags”命令查找你處于標簽棧的哪個位置。
我們經常用到的tag跳轉命令見下(一般只需要知道CTRL-]和CTRL-T就可以了):
:tag {ident} "跳轉到指定的標簽
:tags "顯示標簽棧
CTRL-] "跳轉到當前光標下的標簽
CTRL-T "跳到標簽棧中較早的標簽
如果想了解更多命令,可以“:help 29.1”(強烈建議程序員完整的閱讀usr_29.txt和usr_30.txt)。
如果想更深入了解tag命令和相關知識,可以“:help tagsrch”。
我之前寫的一篇關于ctags和cscope的文章,參見:Vim + Cscope/Ctags
第二節:
本節所用命令的幫助入口:
:help helptags
:help taglist.txt
上篇文章介紹了在VIM中如何使用tag文件,本文主要介紹如何使用taglist插件。
想必用過Source Insight的人都記得這樣一個功能:SI能夠把當前文件中的宏、全局變量、函數等tag顯示在Symbol窗口,用鼠標點上述tag,就跳到該tag定義的位置;可以按字母序、該tag所屬的類或scope,以及該tag在文件中出現的位置進行排序;如果切換到另外一個文件,Symbol窗口更新顯示這個文件中的tag。
在VIM中的taglist插件所實現的就是上述類似的功能,有些功能比SI弱,有些功能比SI更強。而且,taglist插件仍在不斷完善中!
要使用taglist插件,必須滿足:
1. 打開VIM的文件類型自動檢測功能;
2. 系統中裝了Exuberant ctags工具,并且taglist能夠找到此工具(因為taglist需要調用它來生成tag文件);
3. 你的VIM支持system()調用;
在本系列第3篇文章(vimrc初步)中,我們使用了VIM自帶的示例vimrc,這個vimrc中已經打開了文件類型檢測功能;在上篇文章中,我們也已用到了Exuberant ctags;system()調用在一般的VIM版本都會支持(只有suse Linux發行版中出于安全考慮,關閉了此功能),所以我們已經滿足了這三個條件。
現在我們到http://www.vim.org/scripts/script.php?script_id=273下載最新版本的taglist plugin,目前版本是4.3。
下載后,把該文件在~/.vim/目錄中解壓縮,這會在你的~/.vim/plugin和~/.vim/doc目錄中各放入一個文件:
plugin/taglist.vim – taglist插件
doc/taglist.txt - taglist幫助文件
注:windows用戶需要把這個插件解壓在你的$VIM/vimfiles或$HOME/vimfiles目錄。
使用下面的命令生成幫助標簽(下面的操作在VIM中進行):
:helptags ~/.vim/doc
生成幫助標簽后,你就可以用下面的命令查看taglist的幫助了:
:help taglist.txt
Taglist提供了相當多的功能,我的vimrc中這樣配置:
""""""""""""""""""""""""""""""
" Tag list (ctags)
""""""""""""""""""""""""""""""
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窗口
這樣配置后,當你輸入“:TlistOpen”時,顯示如下窗口:

在屏幕右側出現的就是taglist窗口,你從中可以看到在main.c文件中定義的所有tag:宏、定義、變量、函數等;你也可以雙擊某個tag,跳到該tag定義的位置;你還可以把某一類的tag折疊起來(使用了VIM的折行功能),方便查看,就像圖中macro和variable那樣。更多的功能,請查看taglist的幫助頁,本文也會介紹一些常用功能。
下面介紹常用的taglist配置選項,你可以根據自己的習慣進行配置:
- Tlist_Ctags_Cmd選項用于指定你的Exuberant ctags程序的位置,如果它沒在你PATH變量所定義的路徑中,需要使用此選項設置一下;
- 如果你不想同時顯示多個文件中的tag,設置Tlist_Show_One_File為1。缺省為顯示多個文件中的tag;
- 設置Tlist_Sort_Type為”name”可以使taglist以tag名字進行排序,缺省是按tag在文件中出現的順序進行排序。按tag出現的范圍(即所屬的namespace或class)排序,已經加入taglist的TODO List,但尚未支持;
- 如果你在想taglist窗口是最后一個窗口時退出VIM,設置Tlist_Exit_OnlyWindow為1;
- 如果你想taglist窗口出現在右側,設置Tlist_Use_Right_Window為1。缺省顯示在左側。
- 在gvim中,如果你想顯示taglist菜單,設置Tlist_Show_Menu為1。你可以使用Tlist_Max_Submenu_Items和Tlist_Max_Tag_Length來控制菜單條目數和所顯示tag名字的長度;
- 缺省情況下,在雙擊一個tag時,才會跳到該tag定義的位置,如果你想單擊tag就跳轉,設置Tlist_Use_SingleClick為1;
- 如果你想在啟動VIM后,自動打開taglist窗口,設置Tlist_Auto_Open為1;
- 如果你希望在選擇了tag后自動關閉taglist窗口,設置Tlist_Close_On_Select為1;
- 當同時顯示多個文件中的tag時,設置Tlist_File_Fold_Auto_Close為1,可使taglist只顯示當前文件tag,其它文件的tag都被折疊起來。
- 在使用:TlistToggle打開taglist窗口時,如果希望輸入焦點在taglist窗口中,設置Tlist_GainFocus_On_ToggleOpen為1;
- 如果希望taglist始終解析文件中的tag,不管taglist窗口有沒有打開,設置Tlist_Process_File_Always為1;
- Tlist_WinHeight和Tlist_WinWidth可以設置taglist窗口的高度和寬度。Tlist_Use_Horiz_Window為1設置taglist窗口橫向顯示;
在taglist窗口中,可以使用下面的快捷鍵:
<CR> 跳到光標下tag所定義的位置,用鼠標雙擊此tag功能也一樣
o 在一個新打開的窗口中顯示光標下tag
<Space> 顯示光標下tag的原型定義
u 更新taglist窗口中的tag
s 更改排序方式,在按名字排序和按出現順序排序間切換
x taglist窗口放大和縮小,方便查看較長的tag
+ 打開一個折疊,同zo
- 將tag折疊起來,同zc
* 打開所有的折疊,同zR
= 將所有tag折疊起來,同zM
[[ 跳到前一個文件
]] 跳到后一個文件
q 關閉taglist窗口
<F1> 顯示幫助
可以用“:TlistOpen”打開taglist窗口,用“:TlistClose”關閉taglist窗口?;蛘呤褂?#8220;:TlistToggle”在打開和關閉間切換。在我的vimrc中定義了下面的映射,使用“,tl”鍵就可以打開/關閉taglist窗口:
map <silent> <leader>tl :TlistToogle<cr>
Taglist插件還提供了很多Ex命令,你甚至可以用這些命令創建一個taglist的會話,然后在下次進入VIM時加載此會話。
來自:http://blog.csdn.net/easwy/archive/2007/03/01/1518468.aspx