如何在VIM中浏览Ruby方法?

44
我正在学习如何在Rails开发中使用VIM,并希望能够轻松地浏览文件中的方法。到目前为止,我看到了几个选项:
  • 使用 '/' 查找 'def'
  • 使用 ':tag method_name' 跳转到方法名称
  • 使用 ']' 跳转到下一个方法
  • 使用 '[[' 跳转到当前代码块的开始位置

这些选项中是否有更好的方法?

/def<space>
  • 使用 q 和 record 创建与键相对应的宏
  • 使用 VIM 标记?(甚至不确定它们是做什么的,但听起来很有前途)
  • 有没有更好的想法?


    我认为更好的方法是使用]m[m,同时您也可以使用]M跳转到方法定义的结尾。 - hguzman
    8个回答

    42

    :help ]m

    我认为这需要vim-ruby来支持 Ruby。


    我现在使用 ctags 和 git hooks,以及 fzf 跳转到当前缓冲区的标签。它的效果非常好,但是设置所有这些东西还是相当费事的。 - eremite

    36

    你需要一个名为ctags的功能,可参考exuberant ctags,可用于多种语言包括Ruby,使用非常简单。

    在VIM中使用:help ctags

    ctags会创建源代码树中所有标识符的索引。然后,您可以使用标签命令浏览源代码树。请参阅:help tag-commands。 最简单的方法是将光标放在关键字上,然后按CTRL-]。要返回原处,请按CTRL-T

    除此之外,您可能还想查看这个页面,它记录了如何将VIM用作更完整的Ruby IDE:Using Vim as a Complete Ruby On Rails IDE


    太好了!对于其他有兴趣的人,还有一个叫做SimpleFold的插件,它比使用常规的ruby折叠(\f或ruby_fold = 1)更实用。这是链接:http://www.vim.org/scripts/script.php?script_id=1868 - btelles
    ctags,再加上Tag List vim模块,效果非常好。 - the Tin Man
    2
    重要警告:Ctags 不能正确解析Ruby文件。例如,它不接受具有四个点的类定义(例如class Xyz :: Classname),以及其他一些事情。不幸的是,最新版本是从2009年开始的,即使是开发版本也不支持该功能。 - lzap
    @lzap 这也是我的问题。有更好的插件吗?ruby.vim 也不能做到这一点。 - New Alexandria
    3
    有一个令人惊叹的东西,只支持Ruby 1.9及以上版本,它就是https://github.com/tmm1/ripper-tags。现在有一个拉取请求可以稍微改进一下CLI。但是目前的主分支也很好用。 - lzap
    exuberant ctags 对我来说完美地工作。我也使用这个标签生成器处理C/C++代码。 - Alexey Polonsky

    14

    对于Vim最佳解决方案是使用ctags。阅读Vim文档以了解如何在TAGS文件中导航,也安装像CtrlP这样的插件,它允许您直观地浏览标签。

    警告:Exuberant ctags与Ruby不兼容,解析器的状态不佳,而且4年来都没有更改过。

    • ctags无法处理:module A :: B
    • ctags无法标记(至少某些)运算符方法,如==
    • ctags不支持限定标签,-type = +
    • ctags不输出常量或属性的标签。

    不幸的是,所有其他(我找到的2个)Ruby ctags生成器要么已过时(不支持Ruby 1.9+),要么非常缓慢。

    然而有一个解决方案。Ripper-ctags:https://github.com/tmm1/ripper-tags 它速度快并且正常工作。它基于Ruby 1.9+功能称为“Ripper”,使我们可以在(快速的)Ruby原始解析器上构建。它是今天最准确的ctags生成器

    Ripper CLI选项与ctags几乎相同,因此如果您已经了解ctags,则会发现ripper-tags很容易学习。就像这样简单:

    ripper-tags -R .
    

    这将创建TAGS文件,vim默认会自动读取该文件(必须是您打开vim实例的目录,或者如果您在不同的目录中启动vim,则手动更改vim中的路径设置 - 更多内容请参见Vim手册)。

    如果您喜欢这个功能,可以进一步安装我的项目,它会自动为您安装的所有gem包创建TAGS文件https://github.com/lzap/gem-ripper-tags

    使用非常简单(请注意,仅适用于Ruby 1.9+):

    gem install gem-ripper-tags
    

    然后为所有已安装的 gem 生成标签:

    gem ripper_tags
    
    任何时候您现在安装一个 gem,标签都会自动创建。
    gem instal some_gem ...
    

    我进一步采取了一个额外的步骤 - 我有一个git模板,可以在每次自动进行git拉取或合并后重新生成我的项目TAGS(使用ripper-tags):

    https://github.com/lzap/bin-public/blob/master/git-hooks-reinstall

    请注意,您还需要来自同一git存储库的directory files/git_template目录。

    我希望这是浏览Ruby代码库的良好起点 :-)


    Ctags最适合静态语言(因为它是基本的静态分析器)。 - user916367
    当然可以,而且速度非常快,因为您不需要在内存中加载所有类,并且它足够准确。我在许多Ruby项目上工作,包括相当大的代码库,我得到了约90%的正确结果。对我来说很有效。 - lzap

    5

    几个想法:

    首先,创建一个映射,使用C函数在~/.vim/after/ftplugin/ruby.vim中搜索键:

    :nmap [[ ?def <CR>
    :nmap ]] /def <CR>
    

    然后,您可以使用[[]]来前进和后退函数,就像在C/Perl/Java代码等中一样。

    另一种可能有帮助的方法:

    .vimrc中添加以下行:

    :let ruby_fold = 1
    

    然后使用zjzkz[z]来折叠导航。你也可以安装这个插件,这样你就可以使用daz轻松删除折叠。
    如果要查找特定函数(而不仅仅是在它们之间导航),则需要使用ctags(由chillitom提到)。taglist插件使得导航到特定函数更加容易,但是(正如chillitom所说的那样)Ctrl-]Ctrl-T对于跟随光标下的关键字非常有用。
    更多信息请参见:
    :help [[
    :help ft-ruby-syntax
    :help z[
    :help after-directory
    

    4

    我最近发现Ruby.vim(根据上面的一个答案)带有非常有用的按键绑定:

    nnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','b','n')<CR>
    nnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','','n')<CR>
    nnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','b','n')<CR>
    nnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','','n')<CR>
    xnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','b','v')<CR>
    xnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','','v')<CR>
    xnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','b','v')<CR>
    xnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','','v')<CR>
    
    nnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','b','n')<CR>
    nnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','','n')<CR>
    nnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','b','n')<CR>
    nnoremap <silent> <buffer> ][ :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','','n')<CR>
    xnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','b','v')<CR>
    xnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','','v')<CR>
    xnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','b','v')<CR>
    xnoremap <silent> <buffer> ][ :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','','v')<CR>
    

    1

    一个技巧是只需使用'/f methodName'进行搜索。

    您还应该查看通过将以下行添加到您的 .vimrc 中打开代码折叠:

    :let ruby_fold
    

    更多详情请参见:help ft-ruby-syntax


    0
    通常我只是在增量搜索中输入方法的名称。

    0

    我使用ag(The Silver Searcher)编写了一个小的shell脚本。在你的.vimrc中定义以下函数。

    这个方法将扩展光标下的单词。

    function! SearchForDeclarationCursor()
      let searchTerm = expand("<cword>")
      call SearchForDeclaration(searchTerm)
    endfunction
    

    然后声明SearchForDeclaration方法

    function! SearchForDeclaration(term)
      let definition = 'def ' . a:term
      cexpr system('ag -w ' . shellescape(definition))
    endfunction
    

    请注意,我们明确地搜索def 关键字。(您可以使用您的语言方法签名语法)
    然后,我们将上述函数映射到一个Leader命令。
    map <Leader>cd :call SearchForDeclarationCursor()<CR>
    

    现在,如果您将光标放在“项目中”定义的方法上,并按下<Leader>cd,它将导航到定义该方法的位置。

    请注意,一个方法可以在多个类中定义。您可以使用<Leader>n进行下一个或<Leader>p进行上一个循环。

    如果您想要更详细的解释,请查看我在这里写的博客文章:https://pradyumna.dev/articles/2017-12-17-search-ruby-method-declarations-in-vim

    希望这有所帮助!


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接