我使用 vim C++ 标记文件使用 Ctrl-] 进行导航。问题是每当修改某些文件时,链接不再有效,我必须重新运行 ctags 并更新标记文件。我们的代码库很大,生成标签文件需要很长时间。
是否有任何工具可以在后台定期更新标签文件?我可以配置 VIM 来做同样的事情吗?
我在 Windows 下使用 gvim。
除了 Blixtor 的回答之外,您还需要仔细考虑脚本的设计。我建议分离设计,以便自动命令使用 Windows“启动”命令或类似命令在后台运行外部脚本:从而防止 Vim 在生成标记文件时无响应。
然后,该脚本可以使用不同的文件名(即不是“tags”:)生成标记文件ctags -R -o newtags .
,并且当 ctags 完成时,删除tags
并重命名newtags
为tags
. 这将防止标签文件在生成完成时在 Vim 中不可用。
我编写了vim-easytags插件就是为了做到这一点。我通过扫描整个项目(:UpdateTags **/*.[hc]
例如使用命令)初始化我的标签文件一次,然后插件将在我编辑时自动更新标签文件和:update
我在 Vim 中的源代码文件。虽然它会更新标签文件,但它会阻止 Vim,但因为它只扫描当前文件,所以不会花很长时间。
更新 (2014-07-30):仍在使用 vim-easytags 插件:-)。现在它支持异步模式以避免阻塞 Vim。在我写这篇文章的时候,异步模式还不是默认模式,但经过更多反馈后,我可能会切换默认模式。
我已经编写了一个插件来使用 ctags 完成所有艰巨的工作:Indexer。
它为整个项目提供了无痛的自动标签生成,并使标签保持最新。标签是在后台生成的,因此您不必等待 ctags 生成标签。您可以独立使用它,也可以作为另一个插件project.tar.gz的附加组件。
在第一种方式中,您可以~/.indexer_files
像这样声明您的项目:
[CoolProject]
/home/user/cool_project
[AnotherProject]
option:ctags_params = "--languages=c++"
/home/user/another_project/src
/home/user/another_project/lib
然后,当您从 中打开任何文件时/home/user/cool_project
,所有该项目都将被 ctags 索引。当您从另一个项目打开标签时,也会为其生成标签。来自不同项目的标签永远不会混合。当您从项目中保存文件时,标签会静默更新。你不必关心它,它只是工作。
有关详细信息,请参阅文章:Vim:为您的项目提供方便的代码导航,其中详细解释了 Indexer + Vimprj 的用法。
它在 Vim 7.3 上成功测试,在以下系统上:
Archlinux
Ubuntu 10.4
视窗
Mac OS X 狮子
一个想法:
每次使用 BufWritePost 事件保存缓冲区时,使用 Vim 自动命令 (:help autocommand) 触发脚本运行。
该脚本启动 ctags 生成并包含一些额外的小逻辑,在它已经运行时不运行(或最多每 10 分钟运行一次,等等)。
编辑:
事先在这里问过类似的问题,请参阅Vim auto-generate ctags
来自它的存储库:vim-gutentags
是一个插件,负责管理 Vim 中非常需要的标签文件。它会在您工作时(重新)生成标签文件,同时完全不妨碍您。它甚至会尽最大努力让这些标签文件远离你。它没有依赖关系并且可以正常工作。
这个逻辑适用于大多数情况:当在 vim 中打开一个新文件时,切换到该文件的目录并在那里生成一个标签文件,如果它不存在的话。保存更改的缓冲区时,在正在保存的文件的目录中生成标签文件:
function! GenerateTagsFile()
if (!filereadable("tags"))
exec ":!start /min ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --sort=foldcase ."
endif
endfunction
" Always change to directory of the buffer currently in focus.
autocmd! bufenter *.* :cd %:p:h
autocmd! bufread *.* :cd %:p:h
" Generate tags on opening an existing file.
autocmd! bufreadpost *.cpp :call GenerateTagsFile()
autocmd! bufreadpost *.c :call GenerateTagsFile()
autocmd! bufreadpost *.h :call GenerateTagsFile()
" Generate tags on save. Note that this regenerates tags for all files in current folder.
autocmd! bufwritepost *.cpp :call GenerateTagsFile()
autocmd! bufwritepost *.c :call GenerateTagsFile()
autocmd! bufwritepost *.h :call GenerateTagsFile()
http://vim.wikia.com/wiki/Autocmd_to_update_ctags_file
function! DelTagOfFile(file)
let fullpath = a:file
let cwd = getcwd()
let tagfilename = cwd . "/tags"
let f = substitute(fullpath, cwd . "/", "", "")
let f = escape(f, './')
let cmd = 'sed -i "/' . f . '/d" "' . tagfilename . '"'
let resp = system(cmd)
endfunction
function! UpdateTags()
let f = expand("%:p")
let cwd = getcwd()
let tagfilename = cwd . "/tags"
let cmd = 'ctags -a -f ' . tagfilename . ' --c++-kinds=+p --fields=+iaS --extra=+q ' . '"' . f . '"'
call DelTagOfFile(f)
let resp = system(cmd)
endfunction
autocmd BufWritePost *.cpp,*.h,*.c call UpdateTags()