Vim 之代碼跟蹤 gtags.files使用【轉】


轉自:https://juejin.cn/post/6971437759701450765

這一篇聊聊我們如何通過 vim 瀏覽代碼

代碼瀏覽最重要的就是跟蹤代碼, 跟蹤定義, 跟蹤聲明, 跟蹤調用, 跟蹤引用...

himg

vim 的跟蹤通常可以通過兩種方式實現:

  • tags: 通過 ctags 工具生成 tags 文件
  • cscope 數據庫: 通過 cscopegtags-cscope 生成 cscope 數據庫

兩種方法各有優缺點, 而且可以搭配使用, 並不沖突. 下面逐個介紹.

ctags

ctags 定義: 產生標記文件以幫助在源文件中定位對象. 包含以下對象:

  • class names(類名)
  • macro definitions(宏定義)
  • enumeration names(枚舉名)
  • enumerators(枚舉變量)
  • function definitions(函數定義)
  • function prototypes/declarations(函數定義 / 聲明)
  • class, interface, struct, and union data members(類, 接口, 結構體, 聯合體)
  • structure names(結構體名)
  • typedefs(別名)
  • union names(聯合體名)
  • variables (definitions and external declarations) 變量

安裝 ctags

我們一般所說的 ctags 分為兩種

  • Exuberant Ctags: 這個是正統的 Ctags, 但是年久失修, 上一次更新還是 2009 年
  • Universal Ctags: 是老 Exuberant Ctags 的一個 fork 版本, 繼承了其所有優點, 並且直到現在還在活躍更新

綜上所述, 建議安裝 Universal Ctags, 使用如下方式安裝即可

brew install --HEAD universal-ctags/universal-ctags/universal-ctags
復制代碼

生成 tags

使用 ctags -R –c++-kinds=+px –fields=+iaS –extra=+q . 可以將當前目錄下的所有文件內容進行處理生成 ./tags 文件, 這些選項的作用如下:

  • -R: ctags 循環生成子目錄的 tags
  • --c++-kinds=+pxl: ctags 記錄 c++ 文件中的函數聲明和各種外部和前向聲明 (l 表示記錄局部變量, 可以認為是 local 的縮寫)
  • --fields=+iaS: ctags 要求描述的信息, 其中 i 表示如果有繼承, 則標識出父類; a 表示如果元素是類成員的話, 要標明其調用權限 (即是 public 還是 private); S 表示如果是函數, 則標識函數的 signature.
  • extra=+q: 強制要求 ctags 做如下操作: 如果某個語法元素是類的一個成員, ctags 默認會給其記錄一行, 可以要求 ctags 對同一個語法元素再記一行, 這樣可以保證在 VIM 中多個同名函數可以通過路徑不同來區分.

配置 tags 路徑

生成了 tags 文件后, 我們要讓 vim 找的到當前瀏覽的文件所對應的是哪個 tags 文件, 我們在 ~/.vimrc 中應該加上這樣的配置

set tags=./tags;,tags 復制代碼

前半部分 ./.tags; 代表在文件的所在目錄下查找名字為 .tags 的符號文件, 后面一個分號代表查找不到的話向上遞歸到父目錄, 直到找到 tags 文件或者遞歸到了根目錄還沒找到; 逗號分隔的后半部分 tags 是指同時在 vim 的當前目錄 (:pwd 命令返回的目錄, 可以用 :cd .. 命令改變) 下面查找 tags 文件.

使用 tags

tags 的使用非常簡單, 把光標移動到某個元素上, CTRL+] 就會跳轉到對應的定義, CTRL+o 可以回退到原來的地方.

另外也有一些其他的 tags 相關命令可以使用:

  • :tag func: 跳轉到 func 函數實現的地方
  • :tnext: 下一個標簽匹配處
  • :tprev: 上一個標簽匹配處
  • :tfirst: 第一個標簽匹配處
  • :tlast: 最后一個標簽匹配處
  • :tags: 所有匹配的標簽
  • :tselect: 顯示所有匹配的標簽並讓你選擇指定的

cscope

cscope 是類似於 ctags 一樣的工具, 但可以認為是 ctags 的增強版, 因為她比 ctags 能夠做更多的事:

  • 符號在哪里使用的?
  • 符號在哪里定義的?
  • 變量從哪里得到它的值的?
  • 全局變量的定義?
  • 這個函數在源代碼中的什么文件中?
  • 什么函數調用了這個函數?
  • 這個函數調用了什么函數?
  • 消息 out of space 來自哪里?
  • 這個源文件在目錄中的結構?
  • 哪些文件包含了這個頭文件?

cscope 如何使用

在終端中的項目路徑中使用 cscope -Rbkq:

  • R: 表示把所有子目錄里的文件也建立索引
  • b: 表示 cscope 不啟動自帶的用戶界面, 而僅僅建立符號數據庫
  • q: 生成 cscope.in.outcscope.po.out 文件, 加快 cscope 的索引速度
  • k: 在生成索引文件時, 不搜索 /usr/include 目錄

通常我們使用 cscope -Rb 可以在當前路徑下得到 cscope.out

cs 是 cscope 的簡寫命令, 后面也是如此.

然后在 vim 中使用 :cs add cscope.out: 添加一個新的 cscope 數據庫鏈接. 之后便可以在 vim 中使用 :cs ... 的一系列命令了

  • :cs show: 查看當前已經鏈接的 cscope 數據庫鏈接
  • :cs a ...: Find assignments to this symbol
  • :cs c ...: Find functions calling this function
  • :cs d ...: Find functions called by this function
  • :cs e ...: Find this egrep pattern
  • :cs f ...: Find this file
  • :cs g ...: Find this definition
  • :cs i ...: Find files #including this file
  • :cs s ...: Find this C symbol
  • :cs t ...: Find this text string

gtags

gtags, 全名為 gnu global, 是一個類似 cscope 的工具(不是 ctags 的替代品!), 也能提供源文件之間的交叉索引. 其獨到之處在於, 當生成索引文件以后, 再修改整個項目里的一個文件, 然后增量索引的過程非常快.

安裝

brew install global
復制代碼

安裝好以后, 有 global, gtags, gtags-cscope 三個命令. global 是查詢, gtags 是生成索引文件, gtags-cscope 是與 cscope 一樣的界面.

gtags 環境配置

gtags 是支持使用 ctags/universal-ctags 或者 pygments 來作為分析前端支持 50+ 種語言. 使用 ctags/universal-ctags 作為前端只能生成定義索引不能生成引用索引, 因此我們要安裝 pygments , 保證你的 $PATH 里面有 python, 接着:

pip install pygments
復制代碼

保證在環境里里要設置過如下兩個環境變量:

export $GTAGSLABEL = 'native-pygments' export $GTAGSCONF = '/path/to/share/gtags/gtags.conf' 復制代碼

第一個 GTAGSLABEL 告訴 gtags 默認 C/C++/Java 等六種原生支持的代碼直接使用 gtags 本地分析器, 而其他語言使用 pygments 模塊. 第二個環境變量必須設置, 否則會找不到 native-pygmentslanguage map 的定義, Mac 下的路徑為 /usr/local/share/gtags, 可以把它拷貝成 ~/.globalrc

實際使用 pygments 時, gtags 會啟動 python 運行名為 pygments_parser.py 的腳本, 通過管道和它通信, 完成源代碼分析, 故需保證 gtags 能在 $PATH 里調用 python, 且這個 python 安裝了 pygments 模塊.

gtags 使用

$ cd project/ $ gtags 復制代碼

gtags 遍歷子目錄, 從源碼文件中提取符號, 這樣就生成了整個目錄的索引文件, 包括 GTAGS, GRTAGS, GPATH 三個數據庫文件.

  • GTAGS: 定義數據庫
  • GRTAGS: 引用數據庫
  • GPATH: 路徑名數據庫

也可以先用 find 命令生成一個文件列表, 叫 gtags.files, 然后再執行 gtags, 就會只索引 gtags.files 里的文件.

$ cd project/ $ find . -name "*.[ch]" > gtags.files $ gtags 復制代碼

gtags-cscopevim 中的使用

查詢使用的命令是 globalgtags-cscope. 前者是命令行界面, 后者是與 cscope 兼容的 ncurses 界面. 這里就不多介紹了, 重點是如何在 vim 里查詢:

首先進入 vim, 然后:

:set cscopeprg=gtags-cscope :cs add GTAGS 復制代碼

然后就可以像 cscope 一樣, 用 cs find g 等命令進行查詢了.

gtags-cscope 還有一個優點就是我后台更新了 gtags 數據庫, 不需要像 cscope 一樣調用 cs reset 重啟 cscope 子進程, gtags-cscope 一旦連上永遠不用重啟, 不管你啥時候更新數據庫, gtags-cscope 進程都能隨時查找最新的符號.

當我們更改了某個文件以后, 比如 project/subdir1/subdir2/file1.c, 想更新索引文件 (索引文件是 project/GTAGS), 只需這樣:

$ cd project/subdir1/subdir2/ $ vim file1.c $ global -u 復制代碼

global -u 這個命令會自動向上找到 project/GTAGS, 並更新其內容. 而 gtags 相對於 cscope 的優勢就在這里: 增量更新單個文件的速度極快, 幾乎是瞬間完成. 有了這個優勢, 我們就可以增加一個 autocmd, 每次 :w 的時候自動更新索引文件.

gutentags - 一個將 ctags, cscope, gtags 串起來的一個自動化工具

gutentags 可以為我們生成數據庫並自動 cs add 添加 gtags 數據庫到 vim, 在你配置好它之后, 一切皆在后台線程默默完成, 什么都不需要再操心. 可以參考 我的 gutentags 配置

編輯一個項目還好, 如果同時編輯兩個以上的項目, gutentags 會把兩個數據庫都連接到 vim 里, 於是你搜索一個符號, 兩個項目的結果都會同時出現, 基本沒法用了.

這時, 我們可以搭配 skywind3000/gutentags_plus 一起使用, 這個腳本讓已經加載過的數據庫不會重復加載, 非本項目的數據庫會得到即時清理, 所以你根本感覺不到 gtags 的存在, 只管始用 GscopeFind g 命令查找定義, GscopeFind s 命令查找引用, 既不用 care gtags 數據庫加載問題更不用關心何時更新, 你只管寫你的代碼, 打開你要閱讀的項目, 隨時都能通過 GscopeFind 查詢最新結果, 並放入 quickfix 窗口中:

這個小腳本末尾還還定義了一系列快捷鍵:

  • <leader>cg: 查看光標下符號的定義
  • <leader>cs: 查看光標下符號的引用
  • <leader>cc: 查看有哪些函數調用了該函數
  • <leader>cf: 查找光標下的文件
  • <leader>ci: 查找哪些文件 include 了本文件
  • <leader>cd: Functions called by this function
  • <leader>ct: Find text string under cursor
  • <leader>ce: Find egrep pattern under cursor
  • <leader>ca: Find places where current symbol is assigned
  • <leader>cz: Find current word in ctags database

設置排除文件類型

ctags 排除與 gtags 排除不一致, 需要手動在 $GTAGSCONF 中設置 skip

himg

最后

我的 vim 配置倉庫: HanleyLee/dotvim

本文作者 Hanley Lee, 首發於 閃耀旅途, 如果對本文比較認可, 歡迎 Follow


作者:HanleyLee
鏈接:https://juejin.cn/post/6971437759701450765
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM