背景 在 vim 中使用 fzf.vim 插件可以進行方便的搜索文件, 源碼TAG, GIT 記錄等, 最近抽空看了下 BTags 命令在 c, c++ 文件中, 無法顯示頭文件中的函數聲明 標簽問題. 比如在頭文件中有如下一個函數聲明, 使用 BTags 命令是無法顯示出這個函數原型的. /* 函 ...
背景
在 vim 中使用 fzf.vim
插件可以進行方便的搜索文件, 源碼TAG, GIT 記錄等, 最近抽空看了下 BTags
命令在 c, c++ 文件中, 無法顯示頭文件中的函數聲明
標簽問題.
比如在頭文件中有如下一個函數聲明, 使用 BTags 命令是無法顯示出這個函數原型的.
/*=========================================================================
函 數 名: IMGVideoAlgOpen
功 能: 演算法初始化
演算法實現: 無
參 數: pvHandle 演算法句柄[in]
emIMGAlgType 演算法類型[in]
pvOpen 初始化結構體指針[in]
返 回 值: 返回函數調用信息
===========================================================================*/
int IMGVideoAlgOpen(void** pvHandle,
EMIMGAlgType emIMGAlgType,
void* pvOpen);
分析
通過代碼定位, 在 ~/.vim/bundle/fzf.vim/autoload/fzf/vim.vim
文件中, 可以看到 BTags 是通過 ctags
生成的標簽.
" query, [tag commands], [spec (dict)], [fullscreen (bool)]
function! fzf#vim#buffer_tags(query, ...)
...
let sort = has('unix') && !has('win32unix') && executable('sort') ? '| sort -s -k 5' : ''
let tag_cmds = (len(args) > 1 && type(args[0]) != type({})) ? remove(args, 0) : [
\ printf('ctags -f - --sort=yes --excmd=number --language-force=%s %s 2> %s %s', get({ 'cpp': 'c++' }, &filetype, &filetype), escaped, null, sort),
\ printf('ctags -f - --sort=yes --excmd=number %s 2> %s %s', escaped, null, sort)]
...
endfunction
通過在命令行執行 ctags 命令, 確實是沒有生成函數聲明
的標簽.
$ ctags -f - --sort=yes --excmd=number --language-force=c include/VideoAlg.h | grep IMGVideoAlgInit
# output nothing
通過查詢 ctags
文檔瞭解到, 每個語言生成標簽時, 都有預設的標簽類型列表.
可以通過 --kinds-(<LANG>|all)=[+|-](<kinds>|*)
參數去控制, 比如我需要控制 c 語言的生成標簽類型, 可以寫成這樣: --kinds-C=+類型
.
具體的標簽類型可以通過 ctags --list-kinds-full
進行查看, 如下.
$ ctags --list-kinds-full
# output
#LANGUAGE LETTER NAME ENABLED REFONLY NROLES MASTER DESCRIPTION
...
C D macroparam no no 0 C parameters inside macro definitions
C L label no no 0 C goto labels
C d macro yes no 1 C macro definitions
C e enumerator yes no 0 C enumerators (values inside an enumeration)
C f function yes no 0 C function definitions
C g enum yes no 0 C enumeration names
C h header yes yes 2 C included header files
C l local no no 0 C local variables
C m member yes no 0 C struct, and union members
C p prototype no no 0 C function prototypes
C s struct yes no 0 C structure names
C t typedef yes no 0 C typedefs
C u union yes no 0 C union names
C v variable yes no 0 C variable definitions
C x externvar no no 0 C external and forward variable declarations
C z parameter no no 0 C function parameters inside function definitions
...
由上 ENABLED
列可知, 預設 ctags
為 c 語言生成的 tags 是不包含 prototype
的, 如果需要支持生成 prototype, 需要使用參數加上.
解決
修改 ~/.vim/bundle/fzf.vim/autoload/fzf/vim.vim
文件, 增加 ctags --kinds-C=+p
參數來支持 prototype 方法簽名.
\ printf('ctags -f - --sort=yes --kinds-C=+p --excmd=number --language-force=%s %s 2> %s %s', get({ 'cpp': 'c++' }, &filetype, &filetype), escaped, null, sort),
\ printf('ctags -f - --sort=yes --kinds-C=+p --excmd=number %s 2> %s %s', escaped, null, sort)]
搞定收工, 同時也提交了 PR
到 github , 不知道是否會採納.
總結
如果需要其它語言額外的標簽類型, 可以基於類似的方法添加.回想了一下 ctag 之所以預設不提供 prototype 類型的標簽, 可能是因為一個文件中如果有聲明和定義, 可能會有兩個相同的標簽影響查看. 我這邊是做了標簽選擇預覽的, 所以不存在這個問題.