【问题标题】:How to automatically update tag file in vim?如何在vim中自动更新标签文件?
【发布时间】:2010-11-12 13:06:39
【问题描述】:

我使用 vim C++ 标记文件使用 Ctrl-] 进行导航。问题是每当修改某些文件时,链接不再有效,我必须重新运行 ctags 并更新标记文件。我们的代码库很大,生成标签文件需要相当长的时间。

是否有任何工具可以在后台定期更新标签文件?我可以配置 VIM 来做同样的事情吗?

我在 Windows 下使用 gvim。

【问题讨论】:

    标签: vim ctags


    【解决方案1】:

    除了 Blixtor 的回答之外,您还需要仔细考虑脚本的设计。我建议分离设计,以便自动命令使用 Windows“启动”命令或类似命令在在后台运行外部脚本:从而防止 Vim 在生成标记文件时无响应。

    然后,该脚本可以使用不同的文件名(即不是“标签”:ctags -R -o newtags .)生成标签文件,并且当 ctags 完成时,删除 tags 并将 newtags 重命名为 tags。这将防止标签文件在生成完成时在 Vim 中不可用。

    【讨论】:

    • @AI,Linux有类似的解决方案吗?!
    • 对于 Linux,我想您可以使用 & 运行命令将其推送到后台,不是吗?
    • 实际上,taglist 插件已经具有在文件更改时自动更新其 taglist 的功能。我唯一找不到的是该插件如何与普通标签集成,以便 ^] 使用该列表。也许有这样的解决方案(我对此很感兴趣)。我的两分钱:)
    【解决方案2】:

    我写了vim-easytags 插件就是为了做到这一点。我通过扫描整个项目来初始化我的标签文件一次(例如使用命令:UpdateTags **/*.[hc]),然后插件将在我编辑时自动更新标签文件和:update我在Vim中的源代码文件。虽然它会更新标签文件,但它会阻止 Vim,但因为它只扫描当前文件,所以不会花费很长时间。

    更新 (2014-07-30): 仍在开发 vim-easytags 插件 :-)。现在它支持异步模式以避免阻塞 Vim。在我写这篇文章的时候,异步模式还不是默认模式,但是在更多的反馈之后我可能会切换默认模式。

    【讨论】:

    • 嗯,未来的编辑。 (虽然我在这里......)这与AutoTag相比如何。
    • @FDinoff:AutoTag 看起来要简单得多,因此一个区别因素是完整性/可配置性/复杂性。另一个区别是 vim-easytags 可以更新 并突出显示 标签,而 AutoTag 似乎只关注更新部分。此外,AutoTag 需要 Python,而 vim-easytags 不需要。
    • “这个插件会自动创建一个全局标签文件,并在你在 Vim 中编辑文件时保持它是最新的。”如何为不同的项目保留单独的标签而不是单个全局标签? @xolox
    • @xterm:支持项目特定的标签文件,请查看主页/自述文件。
    • @xolox 是否可以同步执行第一次项目扫描,然后执行异步更新?感谢插件!
    【解决方案3】:

    我已经编写了一个插件来使用 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: convenient code navigation for your projects,详细讲解Indexer + Vimprj的使用方法。

    已在 Vim 7.3 上成功测试,在以下系统上:

    • Archlinux

    • Ubuntu 10.4

    • Windows XP

    • Mac OS X Lion

    【讨论】:

      【解决方案4】:

      一个想法:

      每次使用 BufWritePost 事件保存缓冲区时,使用 Vim 自动命令 (:help autocommand) 触发脚本运行。

      此脚本启动 ctags 生成并包含一些额外的小逻辑,在它已经运行时不运行(或最多每 10 分钟运行一次等)。

      编辑:

      之前在这里询问过类似的问题,请参阅Vim auto-generate ctags

      【讨论】:

        【解决方案5】:

        来自它的存储库:vim-gutentags 是一个插件,负责管理 Vim 中非常需要的标签文件。它会在您工作时(重新)生成标记文件,同时完全不妨碍您。它甚至会尽最大努力让这些标签文件远离你。它没有依赖关系,可以正常工作。

        你可以试试https://github.com/ludovicchabant/vim-gutentags

        【讨论】:

          【解决方案6】:

          这个逻辑适用于大多数情况:当在 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()
          

          【讨论】:

          • 您可能想使用 :call system() 代替,这样它就可以移植了,您可以通过 'let l:lines=system("cmdline")' 和返回码获得任何输出在 v:shell_error 中返回。
          【解决方案7】:

          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()
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-17
            • 1970-01-01
            • 1970-01-01
            • 2011-01-02
            • 2017-10-08
            • 2016-07-24
            相关资源
            最近更新 更多