因為學習使用vim,遇到ctags這樣乙個東東,花了一天時間大致搞清楚了一點,記下來,和大家分享。我寫的匆忙,大家也就隨便看看好了。希望有用。
一. ctags 是幹什麼的
二. ctags 可以識別哪些語言,是如何識別的
ctags 識別很多語言,可以用如下命令來檢視:
ctags --list-languages
還可以識別自定義語言,具體沒研究過。
ctags 是可以根據檔案的副檔名以及檔名的形式來確定該檔案中是何種語言,從而使用正確的分析器。可以使用如下命令來檢視預設哪些副檔名對應哪些語言:
ctags --list-maps
還可以指定 ctags 用特定語言的分析器來分析某種副檔名的檔案或者名字符合特定模式的檔案。例如如下命令告知 ctags ,以 inl 為副檔名的檔案是 c++ 檔案。
ctags --langmap=c++:+.inl –r
並不十分清楚 ctags 使用何種技術來解析內容,估計包括正規表示式、詞法分析、語法分析等等。但 ctags 不是編譯器也不是預處理器,它的解析能力是有限的。例如它雖然可以識別巨集定義,但對於使用了巨集的語句的識別還是有缺陷的,在一些稍微正規點的**(例如 ace 的庫或 vc 的標頭檔案等)中的某些常規的巨集使用方式會導致 ctags 無法識別,或者識別錯誤,從而使得 ctags 沒有記錄 user 想記錄的內容,或者記錄下的資訊不準確。另一方面 ctags 也有聰明的一面,例如在 cpp 檔案中掃瞄到 static 的全域性變數時, ctags 會記錄這個變數,而且還會標明說這個變數是侷限於本檔案的,同樣的定義,如果放在 h 檔案中, ctags 則不會標明說這個變數是侷限於本檔案的,因為 ctags 認為 h 檔案是標頭檔案的一種,會被其他檔案 include ,所以在其他檔案中可能會用到該 h 檔案裡定義的這個全域性變數。
三. ctags 可以識別和記錄哪些語法元素
可以用如下命令檢視 ctags 可以識別的語法元素:
ctags --list-kinds
或者單獨檢視可以識別的 c++ 的語法元素
ctags --list-kinds=c++
ctags 識別很多元素,但未必全都記錄,例如「函式宣告」這一語法元素預設是不記錄的,可以控制 ctags記錄的語法元素的種類。如下命令要求 ctags 記錄 c++ 檔案中的函式宣告和各種外部和前向宣告:
ctags -r --c++-kinds=+px
四. ctags 是怎麼記錄的
不管一次掃瞄多少檔案,一條 ctags 命令把記錄的內容都記到乙個檔案裡去,預設是當前目錄的 tags檔案,當然這是可以更改的。
每個語法元素對應檔案裡的一行,學名叫 tag entry 。
1) 開頭是 tag 的名字,其實也就是語法元素的名字,例如記錄的是函式的話則 tag 名就是函式名,記錄的是類的話, tag 名就是類名。
2) 接下來是乙個 tab 。
3) 接下來是語法元素所在的檔名。
4) 又是乙個 tab 。
5) 一條「命令」。這個要解釋一下意義: ctags 所記錄的內容的乙個功能就是要幫助像 vi 這樣的編輯器快速定位到語法元素所在的檔案中去。前面已經記錄了語法元素所在的檔案,這條命令的功能就是一旦在 vi 中開啟語法元素所在的檔案,並且執行了該「命令」後, vi 的游標就能定位到語法元素在檔案中的具體位置。所以該「命令」的內容一般分兩種,一種是乙個正規表示式的搜尋命令,一種是第幾行的指向命令。預設讓 ctags 在記錄時自行選擇命令的種類,選擇的依據不詳,可以通過命令列引數來強制 ctags 使用某種命令,這裡就不多談了。
6) 對於本 tag entry (簡稱 tag )所對應的語法元素的描述,例如語法元素的型別等。具體內容和語法元素的種類密切相關。顯示哪些描述,顯示的格式等都是可以在命令列指定的。例如如下命令要求描述資訊中要包含: a 表示如果語法元素的類的成員的話,要標明其 access (即是public 的還是 private 的); i 表示如果有繼承,標明父類; k 表示顯示語法元素的型別的全稱; s 表示如果是函式,標明函式的 signature ; z 表示在顯示語法元素的型別是使用 kind:type的格式。
ctags -r --fields=+aiksz
ctags 除了記錄上述的各種內容之外,還可以在 tags 檔案中記錄本次掃瞄的各個檔案,乙個檔名對應乙個 tag entry 。預設是不記錄的,要強制記錄要是使用如下命令:
ctags –r --extra=+f
還可以強制要求 ctags 做這樣一件事情——如果某個語法元素是類的乙個成員,當然 ctags 缺省會給其記錄乙個 tag entry (說白了就是在 tags 檔案裡寫一行),可以要求 ctags 對同乙個語法元素再記一行。舉乙個例子來說明:假設語法元素是乙個成員函式, ctags 預設記錄的 tag entry 中的 tag 的名字就是該函式的名字(不包括類名作為字首),而我們強制要求 ctags 多記的那個 tag entry 的 tag 的名字是包含了類明作為字首的函式的全路徑名。這樣做有什麼好處見下文分析。強制 ctags 給類的成員函式多記一行的命令為:
ctags -r --extra=+q
五. vi 大概是怎樣使用 ctags 生成的 tags 檔案的
估計 vi 是這樣使用 tags 檔案的:我們使用 vi 來定位某個 tag 時, vi 根據我們輸入的 tag 的名字在 tags檔案中一行行查詢,判斷每一行 tag entry 的 tag 名字(即每行的開頭)是否和使用者給出的相同,如果相同就認為找到一條記錄,最後 vi 顯示所有找到的記錄,或者根據這些記錄直接跳轉到對應檔案的特定位置。
考慮到 ctags 記錄的內容和方式,出現同名的 tag entry 是很常見的現象,例如函式宣告和函式定義的 tag 名字是一樣的,過載函式的 tag 名字是一樣的等等。 vi 只是使用 tag 名字來搜尋,還沒智慧型到可以根據函式的 signature 來選擇相應的 tag entry 。 vi 只能簡單的顯示 tag entry 的內容給 user ,讓 user 自行選擇。
ctags 在記錄成員函式時預設是把函式的名字(僅僅是函式的名字,不帶任何類名和 namespace 作為字首)作為 tag 的名字的,這樣就導致很多不同類但同名的函式所對應的 tag entry 的名字都是一樣的,這樣 user 在 vi 中使用函式名來定位時就會出現暴多選擇,挑選起來十分麻煩。 user 可能會想在 vi 中用函式的全路徑名來進行定位,但這樣做會失敗,因為 tags 檔案中沒有對應名字的 tag entry 。要滿足使用者的這種心思,就要求 ctags 在記錄時針對類的成員多記錄一條 tag entry ,該 tag entry 和已有的 tag entry 的內容都相同,除了 tag 的名字不同,該 tag entry 的名字是類的成員的全路徑名(包括了命名空間和類名)。這就解釋了ctags 的 --extra=+q 這樣一條命令列選項(見四)。
六. 我的一條 ctags 命令
ctags -r --languages=c++ --langmap=c++:+.inl -h +.inl --c++-kinds=+px --fields=+aiksz --extra=+q --exclude=lex.yy.cc --exclude=copy_lex.yy.cc
命令太長了,折成兩行了,可以考慮把命令的各個引數寫到檔案裡去了(具體做法就不談了)。
1.-r
表示掃瞄當前目錄及所有子目錄(遞迴向下)中的原始檔。並不是所有檔案 ctags 都會掃瞄,如果使用者沒有特別指明,則 ctags 根據檔案的副檔名來決定是否要掃瞄該檔案——如果 ctags 可以根據檔案的副檔名可以判斷出該檔案所使用的語言,則 ctags 會掃瞄該檔案。
2.--languages=c++
只掃瞄檔案內容判定為 c++ 的檔案——即 ctags 觀察副檔名,如果副檔名對應 c++ ,則掃瞄該檔案。反之如果某個檔案叫 aaa.py ( python 檔案),則該檔案不會被掃瞄。
3.--langmap=c++:+.inl
告知 ctags ,以 inl 為副檔名的檔案是 c++ 語言寫的,在加之上述 2 中的選項,即要求 ctags 以 c++ 語法掃瞄以 inl 為副檔名的檔案。
4.-h +.inl
告知 ctags ,把以 inl 為副檔名的檔案看作是標頭檔案的一種( inl 檔案中放的是 inline 函式的定義,本來就是為了被 include 的)。這樣 ctags 在掃瞄 inl 檔案時,就算裡面有 static 的全域性變數, ctags 在記錄時也不會標明說該變數是侷限於本檔案的(見第一節描述)。
5.--c++-kinds=+px
記錄型別為函式宣告和前向宣告的語法元素(見第三節)。
6.--fields=+aiksz
控制記錄的內容(見第四節)。
7.--extra=+q
讓 ctags 額外記錄一些東西(見第
四、五節)。
8.--exclude=lex.yy.cc --exclude=copy_lex.yy.cc
告知 ctags 不要掃瞄名字是這樣的檔案。還可以控制 ctags 不要掃瞄指定目錄,這裡就不細說了。
exuberant ctags 附帶的幫助文件( ctags.html )。
ctags的使用及相關引數介紹
因為學習使用vim,遇到ctags這樣乙個東東,花了一天時間大致搞清楚了一點,記下來,和大家分享。我寫的匆忙,大家也就隨便看看好了。希望有用。一 ctags是幹什麼的 二 ctags可以識別哪些語言,是如何識別的 ctags識別很多語言,可以用如下命令來檢視 ctags list languages...
vim及ctags的使用
0.vim的配置檔案 在使用者目錄下 新建檔案.vimrc,儲存即可生效。如果想所有使用者生效,請修改 etc vimrc 建議先cp乙份 1.vim hello.c 在當前目錄下建立hello.c檔案,並進入vim的一般模式,一般模式下不能插入,可以複製 貼上 刪除。按下i a或o按鍵,進入插入模...
ctags安裝及使用
使用及問題 sudo apt get install ctags 沒搞明白ctags和ctags exuberant的區別,之前12.04和14.04版本的ubuntu使用的是ctags,現在20.04ctags就有問題了,只能使用ctags exuberant,不過效果還是一樣的。ctags檢視版...