【问题标题】:Vim and Ctags tips and tricks [closed]Vim 和 Ctags 提示和技巧 [关闭]
【发布时间】:2010-10-08 11:54:09
【问题描述】:

我刚刚在我的 Vim(或者更确切地说是 gVim)上安装了Ctags(以帮助 C++ 开发),并且想找出您最喜欢的命令、宏、快捷方式和提示...

分享您最好的武器库。对于 Vim 开发中的 C++,您会推荐哪些其他 Vim 附加组件?

编辑您会与 Ctags 一起使用哪些其他插件?

EDIT2 您使用哪个版本的 gVim 来处理标签?这有什么不同吗?

EDIT3您如何增强大型和小型项目的编程体验?

【问题讨论】:

  • 确保使用 exuberant ctags(现代实现)以获得最佳效果:ctags.sourceforge.net
  • 也许 kev 没有建设性?
  • 虽然closed as not constructive 差不多两年前,它对我来说很有建设性
  • 我认为结束这个问题的真正原因应该是:“这个问题尽管很有帮助,但不符合 StackOverflow 的问答政策。让这个问题和答案转移到 Quora 并增长该网站,而我们固执地不断关闭有用的问题和答案”。
  • 鉴于 SO 的规则,我理解为什么这个问题被关闭了。但是,将一个 >400 个赞成的问题标记为 deletion 的回答是 >300 个赞成,这有点不爽,不是吗?

标签: vim ctags vim-macros


【解决方案1】:

Ctrl+] - 转到定义
Ctrl+T - 从定义跳回.
Ctrl+W Ctrl+] - 水平拆分打开定义

在 vimrc 中添加这些行
map <C-\> :tab split<CR>:exec("tag ".expand("<cword>"))<CR>
map <A-]> :vsp <CR>:exec("tag ".expand("<cword>"))<CR>

Ctrl+\ - 在新选项卡中打开定义
Alt+] - 打开垂直分割中的定义

标签生成后。您可以使用以下键标记进入和标记出函数:

Ctrl+Left MouseClick - 转到定义
Ctrl+Right MouseClick - 从定义跳回

【讨论】:

  • C - ] => (控制键)和 ] 键 C - T => (控制键)和 T 键 仅供 ctags 新手使用。感谢新标签技巧
  • 类似地,在使用Ctrl-w C-] 分割窗口后,您可以使用C-w T(又名 Shift-t)将分割更改为新选项卡。
  • @Will 如果您从终端使用 vim,那么您必须更改终端首选项以使选项键的行为类似于 alt 键。如果您使用的是 MacVim,则将此行添加到 vimrc 'set macmeta'。有 macmeta 的文档,:h macmeta。
  • g C-] 非常有用。它会打开一个快速对话框以在多个定义中选择一个。
  • g] 也很有用。您可以将光标放在标签名称上,然后按g] 以获取匹配标签的列表。
【解决方案2】:

我的 .vimrc 中总有一行:

set tags=./tags;/

这将在当前目录中查找“标签”,然后将树向上移动到根目录,直到找到一个。 IOW,您可以位于源代码树中的任何位置,而不仅仅是它的根目录。

【讨论】:

  • 升到根目录是多余的。我建议只回家:tags+=tags;$HOME
  • 我处理的源代码树并不总是在我的主目录中......而且 $HOME 往往与根目录相距两个目录......好吧,我可以再进行两次目录查找. :)
  • 我同意 uzi。如果我的 cwd 是 /home/me/programming/foo/bar/baz/bang/bam 那只有 8 个目录查找。我想这取决于您对速度的容忍度,但查找 1 目录的时间与我机器上的 8 目录没有明显不同。
  • 这取决于您的情况,我需要在我的一台机器上使用 gotgenes 建议,因为 /home 中大约有 8,000 个目录,这往往有点慢。
  • cscope 有类似的东西吗?
【解决方案3】:

另一个对 C 开发有用的插件是 cscope 就像 Ctags 让您跳转到定义一样,Cscope 跳转到 调用 函数。

如果您的 ~/bin/ 目录中有 cscope,请将以下内容添加到您的 .vimrc 并使用 g^​​] 转到调用函数(请参阅 :help cscope)。

if has("cscope")
    set csprg=~/bin/cscope
    set csto=0
    set cst
    set nocsverb
    " add any database in current directory
    if filereadable("cscope.out")
        cs add cscope.out
        " else add database pointed to by environment
    elseif $CSCOPE_DB != ""
        cs add $CSCOPE_DB
    endif
endif

差点忘了...就像 ctags - 您必须生成(并定期更新)数据库。我使用以下脚本

select_files > cscope.files
ctags -L cscope.files
ctags -e -L cscope.files
cscope -ub -i cscope.files

其中 'select_files' 是另一个从 Makefile 中提取 C 和头文件列表的脚本。这样我只索引项目实际使用的文件。

【讨论】:

  • cscope 比 ctags 有什么优势?他们互相赞美吗?
  • 它们相辅相成。 Ctags 查找符号或函数的定义。 Cscope 可以找到所有调用函数的地方。同时使用它们可以很容易地在大型源代码树中导航。
  • 然而,AFAIK cscope 对 C++ 的理解有限。
  • 它是有限的,不是很好。但是对于它的作用(跳转到 USAGES),没有更好的选择。它的主要问题是当你想跳转到函数调用 (f) 时,你通常需要跳转到使用符号 (s) 的任何地方,并在心理上过滤结果......
  • @Whaledawg 是的,当我按下 CTRL+] 我的声卡在输出中发送“clap.wav”:)
【解决方案4】:

您可以将目录添加到您的 ctags 查找中。例如,我有一个为 Qt4 构建的 ctags 索引,并且在我的 .vimrc 中有这个:

set tags+=/usr/local/share/ctags/qt4

【讨论】:

    【解决方案5】:

    以上所有和...

    code_complete :函数参数完成,代码 sn-ps 等等。

    taglist.vim : 源码浏览器(支持C/C++、java、perl、python、tcl、sql、php等)

    【讨论】:

    • 我觉得最好加上taglist.vim是下载最多的vim插件。
    【解决方案6】:

    我使用 ALT-left 和 ALT-right 从标签堆栈弹出/推送。

    " Alt-right/left to navigate forward/backward in the tags stack
    map <M-Left> <C-T>
    map <M-Right> <C-]>
    

    如果您使用hjkl 进行移动,您可以映射&lt;M-h&gt;&lt;M-l&gt;

    【讨论】:

    • 与 ctrl -] 和 ctrl-t 不同——我想,你的建议更简洁一些。
    • @Sasha,对不起?不知道你在说什么。 =X 请注意,这也适用于 :help.
    • 我觉得这个比默认的更直观更简洁。
    • @Ayman 但也违反了不用将手从本垒上移开的原则,就像使用 hjkl 与箭头键一样。
    • @TankorSmash,什么原理?
    【解决方案7】:

    同名的多个定义

    &lt;C-w&gt;g&lt;C-]&gt; 在拆分中打开定义,但也执行:tjump ,它可以转到定义,或者如果有多个定义,则为您提供一个可供选择的定义列表。

    【讨论】:

    • 与第一个命令类似,vim 有一个:ptag 命令可以在预览窗口中打开定义。
    • 预览窗口很不错,因为您可以在任何其他窗口中使用 :pc 将其关闭,而无需先将光标移动到预览窗口。
    • :h CursorHold-example 处还有一个带有 ptag 的简洁 autocmd 技巧,它在可配置的超时后在预览窗口中显示光标下项目的标签。
    • +1 for :tjump 我现在绑定了 :tjump 效果更好 恕我直言很想将此行为与 :ptag
    • :help 有时很棒……见:help CTRL-W_g}:ptjump
    【解决方案8】:

    我用得最多的命令是C-],它跳转到光标下函数的定义处。您可以更频繁地使用它来跟踪更多电话。之后,C-o 会带你回到上一级,C-i 会更深。

    【讨论】:

    • C-t 在 C-] 堆栈中返回一级,而 C-o 在移动后返回上一个光标位置。所以如果你 C-] 到一个函数然后向下翻页,C-t 将立即返回,而 C-o 将返回到函数的开头,然后返回到调用。
    【解决方案9】:

    我发现taglist 插件是必备的。它在一个单独的窗口中列出了它知道的所有标签(您已经打开的文件),并且可以很容易地浏览更大的文件。

    我主要将它用于 Python 开发,但它只能更好地用于 C/C++。

    【讨论】:

      【解决方案10】:

      我已将标签操作封装在我的 experimental plugin 中。

      关于 vim 中的 C++ 开发,我已经回答了there:我使用自己的套件,以及一些其他插件。

      【讨论】:

        【解决方案11】:

        两年来我一直在调整我的 vim 插件以支持足够大的 c++ 项目。你可以看看他们。

        他们使用 ctags 和 cscsope。

        http://www.vim.org/scripts/script.php?script_id=1638
        http://www.vim.org/scripts/script.php?script_id=2507

        【讨论】:

          【解决方案12】:

          我将以下内容放在我的 .gvimrc 文件中,它会在 gvim 启动时从任意点向上搜索标签文件:

          function SetTags()
              let curdir = getcwd()
          
              while !filereadable("tags") && getcwd() != "/"
                  cd ..
              endwhile
          
              if filereadable("tags")
                  execute "set tags=" . getcwd() . "/tags"
              endif
          
              execute "cd " . curdir
          endfunction
          
          call SetTags()
          

          然后,我会定期在源代码树顶部使用如下脚本重新生成标签文件:

          #!/bin/bash
          
          find . -regex ".*\.\(c\|h\|hpp\|cc\|cpp\)" -print | ctags --totals --recurse --extra="+qf" --fields="+i" -L -
          

          【讨论】:

          【解决方案13】:

          我在macos中使用vim,原来的ctags不好用,所以我下载最新的并配置make make install。 我在 /usr/local/bin/ctags 中安装了 ctgas(保留原来的)

          "taglist
          let Tlist_Ctags_Cmd = "/usr/local/bin/ctags"
          let Tlist_WinWidth = 50
          map <leader>ta :TlistToggle<cr>
          map <leader>bta :!/usr/local/bin/ctags -R .<CR>
          set tags=tags;/
          map <M-j> <C-]>
          map <M-k> <C-T>
          

          【讨论】:

            【解决方案14】:

            我修改了上面的 SetTags() 搜索函数(应该被等效的 set tags+=./tags;/ 替换)来为 cscope 工作。似乎有效!

            "cscope file-searching alternative
            function SetCscope()
                let curdir = getcwd()
            
                while !filereadable("cscope.out") && getcwd() != "/"
                        cd ..
                            endwhile
            
                if filereadable("cscope.out")
                        execute "cs add " . getcwd() . "/cscope.out"
                            endif
            
                execute "cd " . curdir
                endfunction
            
            call SetCscope()
            

            【讨论】:

            • 正如 gotgenes 所说,您只是重新发明了向上搜索。请参阅 :h 文件搜索。相关示例请参见 this plugin
            【解决方案15】:

            上面的 SetCscope() 函数的另一个迭代。这将 cscope 预路径设置为在不位于“cscope.out”所在的目录上的情况下获取匹配项:

            function s:FindFile(file)
                let curdir = getcwd()
                let found = curdir
                while !filereadable(a:file) && found != "/"
                    cd ..
                    let found = getcwd()
                endwhile
                execute "cd " . curdir
                return found
            endfunction
            
            if has('cscope')    
                let $CSCOPE_DIR=s:FindFile("cscope.out")
                let $CSCOPE_DB=$CSCOPE_DIR."/cscope.out"
                if filereadable($CSCOPE_DB)
                    cscope add $CSCOPE_DB $CSCOPE_DIR
                endif
            
                command -nargs=0 Cscope !cscope -ub -R &
            endif
            

            【讨论】:

            • 正如 gotgenes 所说,您只是重新发明了向上搜索。请参阅 :h 文件搜索。相关示例请参见 this plugin
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-05-02
            • 2010-10-22
            • 2023-03-08
            • 1970-01-01
            • 2010-09-16
            • 1970-01-01
            相关资源
            最近更新 更多