TAGS::Vim進階索引[7]

helloxchen發表於2010-10-22

TAGS::Vim進階索引[7]



Vim進階索引[7]::TAGS

tags最廣為人知的應用是taglist。但大家對tags本身的關注卻少得多。我希望這一篇文章能幫你懂得使用tags、生成tags和擴充套件tags的應用範圍。與之前的幾篇不一樣的是這一篇的指令碼使用了許多Vim7的新特性——大部分是關於List的。

這幾個是相關的文件:

:h tagsrch
:h taglist()

當我們在檢視Vim文件時,只要在關鍵字(即兩邊帶有"|"的字)上按CTRL-]就可以跳轉到指定的位置——Vim是如何做到這一點的呢?它怎麼會知道目標位置在哪呢?

其實在進行跳轉時,Vim藉助了一個叫"tags"的檔案。tags檔案是一個表格,表格中的記錄以行為單位。每一條記錄包含一個tag(標籤)及一條對應該標籤的位置資訊。當我們按CTRL-]時,Vim在"tags"中查詢相應的標籤——即當前游標下的字。如果找到則讀取該條記錄的位置資訊。並根據該資訊轉到相應的位置。標籤就相當於HTML的連結文字,而tags檔案則記錄了每個連結的連結文字(標籤)及其對應的href資訊(位置資訊)。在任意檔案的任意位置,都可以使用透過標籤跳轉到該標籤所對應的位置——只要該標籤存在於某個Vim可以找到的tags檔案中。

通常Vim會在當前目錄下(:pwd)查詢tags檔案。但你可以指定某個目錄下的特定檔案為tags檔案——不一定要命名為tags,但無論你為它取什麼檔名,為了指代方便這裡我們還是叫它為tags檔案。當你需要為它指定其他名字或位置時,你可能用得著modeline或filetype功能。

如果你還沒見過tags檔案,現在開啟Vim文件所用的tags檔案看一下:

:e $VIMRUNTIME/doc/tags




1 基本的tags用法

如果你沒用過Vim中的相關功能,你可以透過這一節的例子瞭解tags的基本用法。如果你用過——看下一章。
新建一個工作目錄,我們會在這個目錄下建三個檔案做實驗。

先建立如下檔案,命名為“file.txt”:

第一行
第二行
第三行
第四行
vim:tags=./tags

接下來建立一個tags檔案。tags檔案有三欄,第一欄是標籤,第二欄是檔名,第三欄表示在檔案中的第幾行。我們先建立四個標籤:A,B,C,"A B"(這個例子中標籤名不重要,可以隨便取。)分別用來表示上面檔案中的第一、二、三、四行。新建名為“tags”的檔案,並輸入如下內容——注意欄與欄之間用製表符(tab)分隔:

A	file.txt	1
A B	file.txt	4
B	file.txt	2
C	file.txt	3

最後,在新建一個檔案,並在任意位置輸入"A B C"並儲存——字元之間要留有空格。將游標移到字母B上按CTRL-],現在你應該在file.txt的第二行了也就是我們在tags檔案中設定的位置上了。現在按CTRL-T可以回到原來的位置。然後再按CTRL-]又跳到file.txt的第二行了。現在,你可以反覆地按CTRL-OCTRL-I後退前進。還有一個問題,怎麼使用 "A B"這個標籤呢?方法是先選中再按CTRL-]——也就是先將游標放到字母A上,指令序列如下:vfB

中文字與字之間沒有空格,所有在中文環境中也經常要使用選中再按CTRL-]的方式跳轉。




2 tags檔案格式

:h 'tags'
:h tags-file-format

讓我們從上面的例子總結一下tags檔案的格式:共有三欄(一般也都是三欄),欄與欄之間用一個製表符(Tab)分隔。最前面一欄是標籤,後面是具體的位置資訊——為表示方便我們估且稱之為錨點。第二欄用於定位到特定檔案,第三欄將位置具體到特定的行。

B file.txt 2

可解讀為標籤“B”所指代的位置是“file.txt”檔案的第2行(或者說標籤“B”對應的錨點在“file.txt”的第2行。)

但上面例子使用最簡單的tag格式。實際上,你可能會遇到下面這樣子的tags檔案:

A	file3.txt	10
ANSWER	file3.txt	norm 30G4|
B	file2.txt	2;"	kind:f	kkk:vvv
C	file3.txt	32
C	file7.txt	/somewhere

我們看一下跟原來的tags檔案有什麼不一樣:

  • 這個tags檔案,包含的位置資訊分屬不同的檔案。這意味著透過tags檔案,你不僅可以轉到同一檔案的不同位置,還可以在一堆檔案中跳轉。
  • 它包含了不只一種定位的方式。在原來的例子中,行的位置是直接用數字表示的。但實際上Vim可以懂Ex命令。所以遇到"norm 30G4|"Vim會將游標定位到第30行的第4列。而遇到“/somewhere”,Vim會在file7.txt中查詢第一個somewhere出現的位置。透過正規表示式的字元就可以進行更復雜的定位。對於不需要修改的文件可以使用行號而需要編輯的文件可以使用正則表示式,這樣即使做了修改也能定位到正確的位置。
  • 有兩個同樣的標籤C指向了不同位置。這種情形當你使用C標籤時,Vim會提示有多個匹配,可以:tn跳到下一個匹配。
  • 標籤B的行號後面有“尾巴”。Vi或其他編輯器中“;"”後的內容被視為註釋。但Vim可以讀取這部分的內容,所以我們可以通常這一部分為tags新增額外的資訊。看下面的解釋。

只要遵循一定的規範就可以讓註釋變為有用的資訊。我們一起再做個實驗,將上面的示例文字,用Vim儲存為"tags"。然後在Vim中輸入如下命令,觀察結果:

:echo taglist("^")
:echo taglist("^B")
:echo taglist("^B")[0]['kind']
:echo taglist("^B")[0]['kkk']

可以看到在返回的字典列表中,多了一個kkk項,可以透過它取得kkk的值vvv。我們可以繼續往tags裡增加“鍵:值”對。只要記住,每一項之間要用製表符分開(包括;"與第一項之間),鍵與值之間用冒號(:)分隔。 另外,Vim支援中文鍵值但不支援中文鍵名。如果需要遍歷列表可使用:for(:h :for)語句。而且每個tag都有kind項,不論有無給出kind的值,它的值可以是任意的單個字母。為kind賦值時“kind:”也可以省略。所以,標籤B也可寫為:B file2.txt 2;" f kkk:vvv

注意:tags檔案的編碼(encoding)要與Vim的預設編碼一致,不然可能會出現中文文字工作不正常的情況。




3 相關命令

就像往常一樣,Vim提供了非常多的命令——但本文的目的不在幫使用者背命令。關於這些命令可翻看文件。

:h tag-commands

下面這幾個命令是一定要掌握的:

     :h tag
     :h CTRL-]
     :h CTRL-T
     :h CTRL-O
     :h CTRL-I

提示:在使用:tag時是可以使用tab鍵補全的,此外還可以使用正規表示式搜尋標籤。如::tag /agname

現在我們已經瞭解它的原理、它的格式,也知道怎麼樣使用這些tags檔案了。現在我們要進入進階的部分了——我們要根據需要定製自己的tags。




4 tags進階

可以使用的tag命令是固定的,就是Vim提供的那些命令。但生成什麼樣的tags檔案使用者是可以控制的。因而用好這個功能的關鍵也在於怎麼生成tags、生成什麼什麼樣的tags。生成什麼樣的tags取決於使用者的意圖,怎麼生成則依賴於我們的工具。使用ctags程式無疑是最方便的選擇,對於每種語言基本上都可以找到對應的ctags工具。只是生成程式設計用的tags相對使用者的多樣需求來講稍嫌不足。下面的內容將透過例子演示怎麼根據自己的意圖生成合適的tags,也會涉及如何擴充套件ctags的功能。

Vim本身就可以生成tags(:h :helptags)。但是大多數情況下你用ctags類工具生成tags檔案。但是你也可以藉助sed,awk,perl……等工具,甚至是手工編輯。:h tags-file-format





4.1 編寫/轉換為Vim文件

我們已經知道tags可以在文件間建立關聯。這樣既方便使用者查詢又可以方便地在文件間切換。如果你希望為自己的文件增加tags,你只需要定義好錨點和標籤的樣式(其實就是為錨點和標籤增加獨特的標識或分隔符,這樣工具才能分辨關鍵字與普通字詞)。好的樣式可方便工具找到生成tags的規則,減少除錯正規表示式的時間。在標籤樣式中儘量不在要標籤中使用空格,使用命令才方便。對於中文我們可能需要定義一個可以將標籤與其他文字分隔的樣式。這樣才能方便地使用CTRL-]

我們的第一個例子是基於大家都已經熟悉Vim線上文件系統。在這個系統中大家使用:help命令找到相關主題的文件,還能在關鍵字之間方便地跳轉。現在我們知道這個系統的幕後英雄就是tags。

這一節就要講怎麼用Vim文件格式製作出自己的文件(準確地說是使用Vim的tags約定寫自己的文件)。當然,先回答個問題——為什麼要製作Vim格式的文件呢?

  • 重用已有設計是省時省力的方案。
  • Vim文件的格式很簡單。
  • 有現在的tags工具——:helptags。
  • 可以使用Vim的文件系統。除了在開發外掛的時候用得著外,你可曾想過透過輸入:h 01082007檢視自己2007年8月1日的日記呢?額……我承認這個想法有點“非常規”。那你有沒有想過在Vim中輸入:h Best-Tips呢?:)

這是製作Vim文件的步驟:

  1. 寫作並在適當的地方加入錨點和標籤。寫Vim文件的惟一要求就是對標籤和錨點應用特定的樣式:
    • 錨點樣式:在關鍵字兩邊加上“*”號和空格表示一個錨點;另外,關鍵字不能包含空格;如: *vim:*
    • 標籤樣式:在關鍵字兩邊加上“|”。如:|vim:|
  2. 在文件的最後插入modeline。這是可選步驟。
  3. 在文件中使用了上面的規則後,用:helptags .生成tags檔案。
  4. 使用:tag等命令訪問文件

下面是一個完整的(但無用的)Vim格式文件,看完大家就知道怎麼一回事了。

*花花幼兒園班級手冊.txt*
	
*小明*
是個很乖的小孩。他跟|小強|是好朋友。
	
*小強*
是個聰明的小孩。他跟|小麗|是同桌。
	
*小麗*
是個可愛的小女孩。她跟|小明|是鄰居。
	
vim:set ft=help: 使用Vim文件的高亮配置

將上面的文字儲存.txt檔案。現在使用這條命令生成tags
:helptags .

使用tag命令開啟檔案(不知道為啥使用中文標籤有時會失敗——雖然補全可以補出來。使用正則語法,也就是標籤前加一個“/”可以增加成功率)
:tag /小強

需要的話,你還可以將這個檔案整合到Vim的文件中,這樣你可以透過:h命令訪問自己的文件。方法一是直接將你的文件複製到vimfiles下面的doc目錄下,然後重新執行:helptags。這種方法簡單但是你可能不想讓自己的文件跟其他的文件混在一起,這時候你需要用方法二:首先新建一個名為“doc”的目錄——必須命名為doc,將你的文件放進去,doc目錄可放在任何你覺得合適的位置。假設目錄的位置是:/foo/bar/doc。使用:helptags生成tags。最後在vimrc中加入一行:

let &rtp=&rtp . ',/foo/bar'

上面這一行指令碼將doc的上級目錄加進Vim的runtimepath中(:h 'rtp'),只有這樣:h命令才找得到你的文件。如果你的路徑中有空格記得加上“”。

你當然不會將“花花幼兒園班級手冊.txt”整成Vim的幫助——我也不會。這個技巧的價值依賴於應用的場合。我用Vim寫gawk指令碼,所以我想如果gawk的文件也能用Vim的線上文件系統開啟的話那會方便得多。當然這是完全可以做到的,只要依照Vim的格式,在gawk文件中插入適當的錨點。這隻需要一些自動替換加上少量手工調整。這樣我可以在任何時候輸入:h GWK-dcngettext()查詢gawk函式dcngettext的細節。如圖所示:

這樣做的好處是你在寫awk指令碼時可以隨時檢視gawk文件——就像檢視Vim文件一樣。





4.2 exuberant ctags

說到tags的應用當然要談到ctags工具。ctags工具預先定義了一組用來抓tags的規則。這樣我們在寫程式時可以使用tags的便利特性,而不用花時間收集tags——ctags會幫我們做。ctags類軟體的操作方式大同小異,exuberant ctags1是最流行的版本。接下來講的ctags指的就是exuberant ctags。我們將擴充ctags使之支援我們的應用。

ctags支援的語言非常多可以使用下面命令檢視:ctags –list-languages2最常見的用法是:ctags -R *。這條命令在在當前目錄及子目錄中找檔案並生成tags。ctags根據副檔名判斷所使用的語言。但即便ctags支援眾多的語言,還是有許多語言,如 Smalltalk, D, Rebol, Haskell, Basic或者你新開發的語言等不在ctags的支援之列。因此,你需要學會擴充套件ctags的語言以便讓Vim(或者其他用到tags的工具)的功能可以被利用起來。

關於ctags的祥細資訊可以在下面的連結中找到:
裡面包含有使用這個工具的祥細資訊。
裡面介紹瞭如何擴充套件ctags的語言支援(包括從原始碼上增加語言)。

步入正題,讓我們先了解一些定義新的語言需要用到的“選項”:

`–langdef=
告訴ctags,你要定義一種新的語言。如: –langdef=texinfo
`–langmap=:[][,:]
將該語言與特定的副檔名關聯起來。如:–langmap=texinfo:.texi.texinfo將副檔名“.texi”與“.texinfo”都關聯到新定義的語言“texinfo”
`–regex-=/regexp/replacement/[kind-spec/][flags]
部分放上新定義的語言的名稱。“regexp”是用來抓錨點的正規表示式,而“replacement”部分定義了與錨點對應的標籤。這一部分的語法與Vim的:s命令一樣,只是正則語法上有些區別。比如, 用這個正則 /classW(foobar)/1/ 抓錨點“class foobar”後,可用標籤foobar引用該錨點。“kind-spec”可以設定該tag的“kind”項,See kind, Taglist外掛用kind項的值對tag進行分類。“flags”指定所使用的正則版本及是否區分大小寫。預設使用擴充套件的正規表示式(Extended Regular Expression)即egrep所使用的正則語法。加上b可使用基本的正則語法——grep的預設的正則語法。加上i,則不區分大小寫。如:–regex-texinfo=/^@chapterW+(.+)$/1/c/

下面是一個完整的例子。我們會為ctags增加VBScript的支援。3 我們的目的是在看到某個函式時可以方便地跟到定義該函式的地方。為此我們需要抓函式的定義作為錨點,以函式名為標籤。明確了目標後剩下的就是寫正規表示式了!

在這一節寫作過程中,我想到可能已經有人寫過了這方面的內容,然後找到了這個:ctags增加VB支援。總的來說它VBS與VB的語法相似,正則也相近,除了VBS要簡單得多。考慮了許久為了文章的完整性還是留下這一部分的內容,而不是隻留下連結。

如果你不熟悉VBScript的話,先看一下VBS中定義函式的兩種方法:

' 無返回值的以Sub關鍵字定義函式,沒引數的話可以不加括弧
Sub mysub(argument1,argument2)
 ' 語句放在這裡
End Sub 
	
' 有返回值的以Function關鍵字定義函式
Function myfunction(argument1,argument2)
 ' 語句放在這裡
 ' 返回值是字串foobar
 myfunction="foobar"
End Function

對於這兩種函式,我們在抓tag時候將它們的kind分別設為s和f,分別表示subroutine和function。使用這個式樣就可以抓大部分的sub錨點了/sub +(w+)/1/s/i,但我們需要考慮到一些特殊的情況,而且5.6之前的ctags不支援w字元。這是完整的命令:

:: 在命令列中使用時如果正則中含有空格需要用引號括起來(Linux用單引號,Windows雙引號)
ctags --langdef=VBS --langmap=VBS:.vbs --regex-VBS="/^[ t]*sub[ t]+([a-z][a-z0-9_]*)/1/s/i" --regex-VBS="/^[ t]*function[ t]+([a-z][a-z0-9_]*)/1/f/i" *

但我們不希望每次都使用這麼長的命令,而且實際使用時我們可能需要抓更多錨點。我們將選項放到單獨的檔案中,像這樣:

--langdef=VBS
--langmap=VBS:.vbs
--regex-VBS=/^[ t]*sub[ t]+([a-z][a-z0-9_]*)/1/s/i
--regex-VBS=/^[ t]*function[ t]+([a-z][a-z0-9_]*)/1/f/i

然後,使用這條命令(將options.txt改為相應的路徑與檔名):

ctags --options=options.txt *

現在,在編輯VBScript的時候你也可以使用tags的功能了。不過你可能還希望讓taglist也支援VBScript(或者其他你新定義的語言)——這是下一節的內容。





4.3 增加taglist支援

Taglist確實是很好用的Vim外掛。我們將對它進行適當改造使之支援我們新定義的語言。在ctags中定義完語言後。你需要:1. 下載安裝taglist。2. 修改taglist,一些情況下還要修改Vim的filetype設定。3. 使用。

仍以VBScript為例,這是修改的步驟:

首先,在taglist的安裝目錄中搜尋“s:tlist_def_{vim_ftype}_settings”。這裡是taglist定義不同檔案型別,對應的型別的地方——因為kind項的那個字母,在不同檔案型別中有不同的含義。我們定義的VBS的kind(型別)有兩種s和f表示subroutine和function。往下翻可以找到這一行:let s:tlist_def_awk_settings = 'awk;f:function' 這是awk的定義,意思是如果Vim設定的filetype為awk的話,那就將f解讀為function。我們依葫蘆畫瓢:

let s:tlist_def_VBS_settings = 'VBS;s:subroutine;f:function'

這裡是最容易出錯的地方,這邊的{vim_ftype}既要與ctags裡定義的語言名稱一致(也就是VBS),同時也要與Vim中的filetype一致。Vim中*.vbs的filetype是vb而不是單獨的VBS或VBScript。所以,你要麼需要改變*.vbs的filetype為單獨的VBS,使用Vim能識別VBS的檔案型別。要麼更改變前面ctags中定義的語言名,也就是將VBS全部改為vb——這樣就不需要修改Vim的filetype定義。這裡我選擇前者,因為VBS與vb還是差別挺大的。

所以,在$VIMRUNTIME/filetype.vim中查詢:

au BufNewFile,BufRead *.vbs,*.dsm,*.ctl		setf vb

並改為(注意大小寫),

au BufNewFile,BufRead *.vbs,*.dsm,*.ctl		setf VBS

其次,在taglist中搜尋:

let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks '

並增加–options=options.txt,記得將options.txt改為實際的路徑名和檔名。改完後像這個樣子(注意字串前後都要留有空格):

let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks --options=options.txt '

大功告成。現在你可以在VBScript中使用taglist了。試一下,……語法高亮沒掉了。沒事,將$VIMRUNTIME/syntax/vb.vim複製為vbs.vim就可以了。





4.4 生成導航視窗

在摺疊篇我們用了一個唐詩的例子。在上一次我們使用摺疊讓顯示更緊湊一點——就像是目錄,我們只要點選一首詩就可以檢視內容。但我們現在還是遇到了問題,我們收集的詩越來越多,為了管理方便我們把它們放在不同的檔案中。只是這樣一來我們沒辦法在同一個檢視中檢視所有的詩。

這次我們不僅要利用tags方便地在不同檔案不同詩之間跳轉,我們還要利用tags做一個導航視窗出來——這樣我們只要雙擊某首詩的標題就可以在另一個視窗顯示該詩。

《感遇其一》
作者:張九齡
蘭葉春葳蕤,桂華秋皎潔。
欣欣此生意,自爾為佳節。
誰知林棲者,聞風坐相悅。
草木有本心,何求美人折?
	
《感遇其二》
作者:張九齡
江南有丹桔,經冬猶綠林。
豈伊地氣暖,自有歲寒心。
可以薦佳客,奈何阻重深。
運命唯所遇,迴圈不可尋。
徒言樹桃李,此木豈無陰。

我們選擇標題作為錨點。因為所有的標題都含有《》很容易從這些錨點抓出標籤。

" 一條簡單的命令就可以從單個檔案中抓取這種形式的tag
" 因為不需要編輯可以直接使用行號表示位置
g/《/ echo getline('.') ."t". expand('%') ."t". line('.')

生成的tags:

《感遇其一》	唐詩1.txt	1
《感遇其二》	唐詩1.txt	8

但我們希望在tag中增加作者的資訊——這正是用ctags做不到的,同時要能處理多個檔案:

" vim7 指令碼
" 抓取當前目錄下所有.txt的檔名,並逐一傳給變數f
for f in split(glob('*.txt'),'n')
  " 以只讀方式開啟一個檔案
  exe 'view '. f
  " 儲存以下操作的輸出到tags檔案
  redir >> tags
    " 抓取如下格式的tag:{標籤}	{檔案.txt}	{行號};"	author:{作者}
    g/《/ let nl = getline(line('.')+1) |
       let author = (nl=~'作者:' ? substitute(nl,'作者:','author:','') : '') |
       echo getline('.') ."t". expand('%') ."t". line('.') .';"'."t". author
  redir END
endfor
" 任務完成
qa!

在shell/命令列使用這條命令,

" 將xxx.vim換成指令碼的名稱
vim -S xxx.vim

這將會在當前目錄生成如下內容的tags:

《感遇其一》	唐詩1.txt	1;"	author:張九齡
《感遇其二》	唐詩1.txt	8;"	author:張九齡
  ...

事實上這個例子中用gawk或perl會更自然也更方便(雖然Vim指令碼也不長,但操作起來步驟比較煩瑣),而且快得多。記住,Vim的使用者總是選擇合適的工具完成工作——這同樣也是我們選擇Vim的理由。

現在我們有所有詩的tags了。現在用Vim開啟tags檔案。在任一首詩的標題上按CTRL-]就可以轉到相應的位置。再按CTRL-T回到tags檔案——似乎這樣就可以收工了。

不過我們有一些附加的要求,我們希望能控制導航視窗的行為和內容。首先,這個導航視窗應該是持續開啟的。其次可以使用雙擊在其他的視窗開啟一首詩(而不是在導航視窗中)。最後,要能按我們的格式顯示導航的內容。這需要20行左右的Vim程式碼:

" 用來更新目標視窗內容及更新目標檔名的函式。
" 當雙擊或者輸入CTRL-]時呼叫這個函式。
function! SToc(tag)
  " 高亮標題
  exe 'match Todo /%' . line(".") . 'l/'
  " 獲取目標視窗當前的編號
	let nr=bufwinnr(bufname(g:xbn))
  " 跳到目標視窗
	exe nr."wincmd w"
  " 在目標視窗中開啟tag
	silent! exe "tag " . a:tag
  " 更新目標視窗中的檔名(全域性變數)
	let g:xbn=bufname('%')
endfunction
	
" 負責初始化的函式
function! IToc()
  " 如果當前編輯區無檔案,則開啟一個臨時視窗
  if bufname('%')=="" | view _blah_  | endif
  " 初始化全域性變數,這個變數用來跟蹤當前編輯區的檔名
	let g:xbn=bufname('%')
  " 開啟一個視窗並做導航
  vsp __目錄__
  " 不需要實體檔案
  setlocal buftype=nofile
  " 簡單的語法高亮
  syn match Comment "[^-]"
  " 從tags讀取資訊並轉換成“使用者友好”的格式顯示
  call append(line('$'),
    map(taglist("^"),
    'substitute(printf("%-30s%s",v:val["name"],' .
    '(has_key(v:val,"author")?v:val["author"]:""))," ","-","g")'
    ))
  " 定義導航鍵
  map <2-LeftMouse> :call SToc('/'.expand(""))zt
  nmap  <2-LeftMouse>
endfunction
	
" 定義開啟導航視窗的命令
command! -nargs=0 Toc call IToc()

這20行指令碼中有幾個寫Vim程式常用到的技巧。首是多個視窗的管理控制。其次是建立臨時檔案。還有taglist()函式的使用。最後是用command命令建立宏(command 的好處是可以使用引數,不過這裡沒有用到。)

將指令碼儲存起來,用下面的命令執行

" 用下面的命令載入指令碼,將xxx.vim改為實際的檔名
:so xxx.vim
" 使用這條命令開啟導航視窗
:Toc

也可將指令碼放到plugin目錄下,這樣只要隨時輸入:Toc就可以開始閱讀了——當然,必須確保tags檔案在'rtp'或當前的目錄中。現在我們可以使用導航視窗中使用雙擊開啟任意一首詩了……

你可能會好奇為什麼我們要大費周章寫這樣的一個建立導航視窗的指令碼呢?在我們最初的版本中,我們只用了:g命令就生成了第一個tags檔案。在第二個版本中我們使用指令碼在tags檔案中增加了額外的資訊(作者/詩人)。我們只需要在Vim中開啟tags檔案就可以實現導航。但我們想要控制顯示的內容,而tags檔案只需要在後臺控制跳轉。為此我們寫了上面的指令碼。在使用tags做導航時,我們需要控制顯示在導航區的內容——而這一是實現更復雜應用的基礎。附圖是一個檢視郵件的應用,是基於同的的技巧實現的。

5 小結

tags的作用無非是幫助Vim查詢定位跳轉,但同樣是跳轉在不同的應用下起的作用也不一樣:

  • 在文件或文件之間的不同部分建立連繫。例如我們可以在一個檔案的底部放上其他檔案的標籤,讓使用者方便地移動,就像是網頁的“上一頁”“下一頁”。
  • 提供交叉引用。方便使用者使用參考。如同Vim的文件,每一個詞條對應著該詞條的解釋。最更要的也許是:無論是使用ctags還是其他工具,只要能找到自動生成tags的規則,我們就不需要人為的維護不同檔案之間的關係了。這在Vim文件的例子中尤為明顯——寫Vim文件時只要遵循約定,Vim就能自動維護文件之間的引用關係。手工維護這些交叉引用是不可想像的。
  • 為文件建立結構圖或導航圖。就像前面唐詩的例子所展現的一樣。
  • 特殊應用。作為補全的匹配源;資訊彙總,等等……比如,抓一個網頁的所有連結,再集中顯示在一個新視窗。 4

在文件間建立聯絡或提供交叉引用都是隻要有tags就可以,而顯示結構圖或導航圖則需要一點額外的努力——因為我們需要多開一個視窗。這種情況下應首先考慮taglist是否能做為現成的方案。

tags能起什麼作用取決與tags檔案都有什麼內容。因為生成什麼樣的tags才是決定tag功能的關鍵。如果出於程式設計的需要而用tags的話,那可能已經有某種ctags程式支援你所用的語言了。否則你可以用ctags的定義語言功能為某種語言生成tags檔案。在一些應用中我們可能需要Vim或awk,perl這類工具生成一些特殊的tags。但總的來說無論使用哪種工具都是關於正規表示式的運用。


Footnotes

[1] exuberant ctags != etags

[2] 較早的版本會直接顯示支援的語言在幫助中,只要輸入:ctags –help。就可以在最後的部分看到–{language}-types=…

[3] 為什麼是VBScript?我們需要在ctags不支援的語言中找一種語法簡單方便講解,而又相對為人所知的語言做例子說明——其實選擇不多。

[4] 在HTML文件中使用taglist時,會顯示所有錨點的name

http://blah.blogsome.com/2007/08/04/vim_tut_tags/
[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24790158/viewspace-1040223/,如需轉載,請註明出處,否則將追究法律責任。

相關文章