跳转到函数定义

如何使用Vim跳转到函数定义?例如,使用Visual Assist,我可以在函数下键入Alt+g,它会打开一个上下文菜单,列出带有定义的文件。

如何在vim中做这样的事情?

290656 次浏览

使用ctags。生成一个标记文件,并使用:tags命令告诉vim它的位置。然后你可以使用Ctrl-跳转到函数定义

这个问题中有更多的标签技巧和提示。

正如Paul Tomblin提到的,你必须使用ctags。 你也可以考虑使用插件来选择合适的函数,或者在光标下预览函数的定义。 如果没有插件,你将会头疼地试图从数百个重载的“doAction”方法中选择一个,因为内置的ctags支持不考虑上下文-只是一个名称。< / p >

你也可以使用cscope和它的'find global symbol'函数。但是你的vim必须用+cscope支持编译,这不是默认的一个构建选项。

如果您知道该函数在当前文件中定义,则可以在正常模式下使用'gD'键击跳转到光标下的符号定义。

这是下载最多的导航插件 http://www.vim.org/scripts/script.php?script_id=273 < / p > 这是我写的一个选择上下文,同时跳转到标签
http://www.vim.org/scripts/script.php?script_id=2507 < / p >

第二个Paul的回答是:是的,ctags(尤其是exuberant-ctags (http://ctags.sourceforge.net/))很棒。我还添加了这个到我的vimrc,所以我可以为整个项目使用一个标签文件:

set tags=tags;/

如果所有内容都包含在一个文件中,则有gd命令(如在'goto definition'中),它将带您到光标下的文件中单词的第一个出现处,这通常是定义。

另一种常用的技术是将函数名放在第一列中。这样就可以通过简单的搜索找到定义。

int
main(int argc, char *argv[])
{
...
}

上面的函数可以在文件中的/^main中找到,或者在目录中的:grep -r '^main' *.c中找到。只要代码被正确缩进,标识符只会出现在一行的开头是在函数定义处。

当然,如果你从现在开始不使用ctags,你应该为自己感到羞愧!然而,我发现这个编码标准也是一个有用的补充。

g *在没有设置ctags的情况下做得不错。

也就是说,输入g(或者只是 -见下文)来搜索光标下的单词(在本例中,是函数名)。然后按n转到下一个(或转变-n前一个)事件。

它不会直接跳转到定义,因为这个命令只是在光标下搜索单词,但是如果您现在不想处理设置ctags的问题,那么至少可以避免重新键入函数名来搜索它的定义。

< p >——编辑 虽然我已经使用g*很长时间了,但我最近发现了这些快捷键的两个快捷键!< / p >

(a) 将跳转到光标下一个单词出现的位置。(不需要键入g,即vi中的'goto'命令)。

(b) 以类似的方式指向前一个事件。

N和N仍然可以工作,但是'#'通常非常有用,可以从相反的方向开始搜索,例如,在游标下查找变量的声明。

安装cscope。它的工作原理很像ctags,但更强大。要转到定义,执行Ctrl + + g而不是Ctrl + 。当然,您可以同时使用两者。但是对于一个大项目(比如Linux内核),cscope遥遥领先。

1- install exuberant ctags。如果你正在使用osx,这篇文章展示了一个小技巧: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html < / p >

2-如果你只想在你的目录中包含文件的ctags,在你的目录中运行这个命令:

ctags -R

这将为您创建一个“标签”文件。

3-如果你正在使用Ruby,并且希望为你的宝石包含ctags(这对我使用RubyMotion和我开发的本地宝石非常有帮助),请执行以下操作:

ctags --exclude=.git --exclude='*.log' -R * `bundle show --paths`

来源:https://coderwall.com/p/lv1qww (注意,我省略了-e选项,它为emacs而不是vim生成标记)

4-在~/.vimrc中添加以下行

set autochdir
set tags+=./tags;

(为什么用分号:http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree)

5-找到你想要关注的单词并点击ctrl + ];如果你想返回,使用ctrl+o(来源:https://stackoverflow.com/a/53929/226255)

使用gdgD将光标放在程序中的任何变量上。

  1. gd将带你到本地声明。
  2. gD将带你到全局声明。

更多的导航选项可以在在这里中找到。

使用cscope来交叉引用大型项目,例如linux内核。

TL;博士:

可以使用内部的VIM功能来完成这一点,但是一个现代的(更简单的)方法是使用COC来完成类似智能的补全,使用一个或多个语言的服务器 (LS)来跳转到定义(以及更多)。对于更多的功能(但对于跳转到定义不需要),你可以安装一个或多个调试器,并获得完整的IDE体验。

最好的第二种方法是使用本地VIM的名为define-search的功能,但它是为C预处理器的#define指令而发明的,对于大多数其他语言来说需要额外的配置,对于一些根本不可能(你也错过了其他IDE功能)。最后,一个回退方法是ctags

快速启动:

  1. 安装vim-plug来管理你的VIM插件
  2. ~/.vimrc的顶部添加COC和(可选)Vimspector:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
    
    " key mappings example
    nmap <silent> gd <Plug>(coc-definition)
    nmap <silent> gD <Plug>(coc-implementation)
    nmap <silent> gr <Plug>(coc-references)
    " there's way more, see `:help coc-key-mappings@en'
    
  3. 调用:source $MYVIMRC | PlugInstall重新加载VIM配置并下载插件
  4. 重新启动vim并调用:CocInstall coc-marketplace以轻松访问COC扩展
  5. 调用:CocList marketplace并搜索语言服务器,例如:
  • 输入python找到coc-jedi
  • 输入php来查找coc-phpls,等等。
  1. (可选)参见:h VimspectorInstall安装其他调试器,例如:
  • :VimspectorInstall debugpy,
  • :VimspectorInstall vscode-php-debug等等。

完整的故事:

语言的服务器 (LS)是一个单独的独立应用程序(每一种编程语言都有一个),它在后台运行,实时分析你的整个项目,将额外的功能暴露给你的编辑器(任何编辑器,不仅仅是vim)。你会得到这样的东西:

  • 名称空间感知标记补全
  • 跳转到定义
  • 跳转到下一个/上一个错误
  • 查找对一个对象的所有引用
  • 查找所有接口实现
  • 在整个项目中重命名
  • 悬停文档
  • 代码片段,代码动作,格式化,检测和更多…

与语言服务器的通信通过语言服务器协议 (LSP)进行。nvimvim8(或更高)都通过插件支持LSP,最流行的是完成的征服 (COC)。

正在开发的语言服务器及其功能的列表可在朗服务器网站上找到。并非所有这些都是由COC扩展提供的。如果你想使用其中之一,你可以自己编写一个COC扩展,或者手动安装LS,并使用以下VIM插件的组合作为COC的替代方案:

与调试器的通信通过调试适配器协议 (DAP)进行。VIM最流行的DAP插件是Vimspector

语言服务器协议 (LSP)是由微软为Visual Studio Code创建的,并作为具有许可MIT许可的开源项目发布(由与Red Hat和Codenvy合作标准化)。后来微软也发布了调试适配器协议 (DAP)。vcode支持的任何语言在VIM中都是受支持的。

我个人建议使用COC扩展提供的COC +语言服务器+ 啤酒进行额外检测(但为了避免与COC冲突,LSP支持被禁用)+ Vimspector提供的Vimspector +调试器(称为“小工具”)+以下VIM插件:

call plug#begin()
Plug 'neoclide/coc.nvim'
Plug 'dense-analysis/ale'
Plug 'puremourning/vimspector'
Plug 'scrooloose/nerdtree'
Plug 'scrooloose/nerdcommenter'
Plug 'sheerun/vim-polyglot'
Plug 'yggdroot/indentline'
Plug 'tpope/vim-surround'
Plug 'kana/vim-textobj-user'
\| Plug 'glts/vim-textobj-comment'
Plug 'janko/vim-test'
Plug 'vim-scripts/vcscommand.vim'
Plug 'mhinz/vim-signify'
call plug#end()

你可以谷歌每个,看看他们做什么。

本地VIM跳转到定义:

如果你真的不想使用Language Server,并且仍然想要在某种程度上体面地跳转到原生VIM的定义,你应该熟悉:ij:dj,它们代表include-jumpdefinition-jump。这些VIM命令允许您跳转到项目包含的任何文件,或跳转到包含的任何文件中定义的任何符号。但是,要实现这一点,VIM必须知道包含文件或定义符号的行在任何给定语言中的样子。你可以在~/.vim/ftplugin/$file_type.vim中为每种语言设置set include=$regexset define=$regex模式,如:h include-search中所述,尽管,提出这些模式有点像艺术,有时根本不可能,例如对于符号定义或文件导入可以跨越多行(例如Golang)的语言。如果这是你的情况,通常的备用方案是ctags,如其他答案所述。

在生成ctags之后,你还可以在vim中使用以下命令:

:tag <f_name>

以上将带您了解函数定义。