跳转到函数定义

Posted

技术标签:

【中文标题】跳转到函数定义【英文标题】:Jump to function definition 【发布时间】:2010-10-12 18:07:15 【问题描述】:

如何使用 Vim ?例如,使用 Visual Assist,我可以在函数下键入 Alt+g,然后它会打开一个上下文菜单,其中列出了包含定义的文件。

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

【问题讨论】:

gnu global 比 ctags 好。 @Jichao,你能告诉我们你的经历吗? gnu global 使用哪些语言更适合您?在我很重要的情况下,您喜欢它的上下文还有什么其他的吗?或者,也许您已经在许多不同的场景中使用过它,并且您似乎大多/总是更喜欢它?你更喜欢它的哪一点?谢谢。 @Jichao 我将您的评论变成了社区 wiki 答案。我欢迎您对此答案的更改和输入。 【参考方案1】:

使用 ctags。生成一个标签文件,并使用 :tags 命令告诉 vim 它在哪里。然后你可以使用 Ctrl-]

跳转到函数定义

this question中有更多的标签技巧和技巧。

【讨论】:

php 非常类似于 C,“Exuberant ctags”应该可以使用它。不知道有没有python模式。 没有使用 Cscope 的经验。是什么? 与C的相似之处与CTags支持PHP无关。它支持 PHP 和 Python。看看ctags.sourceforge.net/languages.html 以获得全面支持。 如果能参考一下学习如何操作这些 ctag 的最佳位置,那就太好了。 这已经过时了。当前的解决方案是使用可用于vimnvim 的LSP 客户端之一作为插件与实时分析代码的专用独立语言服务器结合使用。有许多 LSP 服务器,例如Eclipse.JDT.ls 用于 Java,felixfbecker/php-language-server 用于 PHP 等等。【参考方案2】:

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

【讨论】:

如果我没有光标下的单词(我宁愿键入它)怎么办? / 几乎总是不精确,因为它会匹配所有出现的情况。我发现你实际上可以通过 ctags 执行 :tag <function_name> 跳转到定义。 @Faud 跳转到定义功能依赖于用光标指向标识符(在每个 IDE 中)。打字/搜索是另一个功能,你让他们感到困惑。 美丽。它甚至可以遍历 IdeaVIM(IntelliJ 工具的免费插件,例如 CLion)中的文件。 完成gd后如何回到原来的位置?【参考方案3】:

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

也就是说,键入 g,* (或只是 * - 见下文)搜索光标下的单词(在此大小写,函数名)。然后按 n 转到下一个(或 Shift-n 表示上一个)。

它不会直接跳转到定义,因为这个命令只是搜索光标下的单词,但是如果你现在不想处理设置ctags,你至少可以从必须重新输入函数名称来搜索其定义。

--编辑-- 虽然我用 g* 已经很久了,但是我最近发现了这两个快捷键的两个快捷键!

(a) * 将跳转到光标下单词的下一个匹配项。 (无需输入g,vi 中的'goto' 命令)。

(b) # 以类似的方式转到上一个事件。

N 和 n 仍然有效,但 '#' 通常在开始反向搜索时非常有用,例如,在查找光标下的变量声明时。

【讨论】:

*g* 之间的区别在于搜索的单词边界。 * 执行 \<keyword\> 搜索(与常规正则表达式中的 \bkeyword\b 相同),而 g* 搜索 keyword 没有单词边界。 如果您在一个文件中有一百次出现的函数,* 会在您找到定义之前平均为您带来 50 次点击。 @naught101,但如果您有两次出现该函数,* 平均只需点击一次即可找到定义。除非你对定义做了* on,否则你应该休息一下……【参考方案4】:

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

    gd 会带你去当地的声明处。 gD 将带您进入全球声明。

更多导航选项可以在here找到。

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

【讨论】:

问题是关于跳转到“定义”而不是“声明”。如果函数在头文件中声明,例如test.h g+d 将带你进入“声明”。一旦没有办法跳转到“test.c”中的“定义”......有没有办法使用COC进行这个跳转? @cpm 回答了一些事情,但没有解释这个跳转。 我不知道在终端 (项目文件夹内) 中使用 ctags -R * 的任何其他方式,然后在 vim 发出命令 :tag <searched tag> 中使用。经过这么多年,这仍然没有实施......我很失望...... @71GA 你没有在我的回答下问:) nmap <silent> gD <Plug>(coc-implementation) 应该将你想要的东西绑定到gD【参考方案5】:

TL;DR:

可以使用内部 VIM 功能执行此操作,但一种现代(且更简单)的方法是使用 COC 进行类似智能感知的完成,并使用一个或多个 language servers (LS) 进行跳转-to-definition(以及更多)。要获得更多功能(但跳转到定义不需要),您可以安装一个或多个 debuggers 并获得完整的 IDE 体验。

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

快速入门:

    安装vim-plug来管理你的VIM插件 在~/.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'
    
    调用:source $MYVIMRC | PlugInstall重新加载VIM配置和下载插件 重启vim并拨打:CocInstall coc-marketplace即可轻松访问COC扩展 致电:CocList marketplace并搜索语言服务器,例如:
输入python 查找coc-jedi, 键入php 以查找coc-phpls 等。
    (可选)查看:h VimspectorInstall 以安装额外的调试器,例如:
:VimspectorInstall debugpy, :VimspectorInstall vscode-php-debug

全文:

Language server (LS) 是一个单独的独立应用程序(每种编程语言一个),它在后台运行并实时分析您的整个项目,为您的编辑器提供额外的功能(任何编辑器,不仅仅是vim) .你会得到类似的东西:

命名空间感知标记完成 跳转到定义 跳转到下一个/上一个错误 查找对象的所有引用 查找所有接口实现 在整个项目中重命名 悬停文档 sn-ps、代码操作、格式化、linting 等等...

通过Language Server Protocol (LSP) 与语言服务器进行通信。 nvimvim8(或更高版本)都通过插件支持 LSP,最流行的是 Conquer of Completion (COC)。

Lang Server 网站上提供了积极开发的语言服务器及其功能的列表。并非所有这些都是由 COC 扩展提供的。如果您想使用其中之一,您可以自己编写 COC 扩展或手动安装 LS,并使用以下 VIM 插件的组合来替代 COC:

LanguageClient - 处理 LSP deoplete - 在您输入时触发完成

与调试器的通信通过Debug Adapter Protocol (DAP) 进行。 VIM 最流行的 DAP 插件是Vimspector。

Language Server Protocol (LSP) 由 Microsoft 为 Visual Studio Code 创建,并作为具有许可 MIT 许可证的开源项目 发布(通过与 Red Hat 合作标准化和 Codenvy)。后来微软也发布了Debug Adapter Protocol(DAP)。 VIM 支持任何 VSCode 支持的语言。

我个人建议使用 COC + 由 COC 扩展提供的语言服务器 + ALE 进行额外的 linting(但禁用 LSP 支持以避免与 COC 冲突)+ Vimspector + Vimspector 提供的调试器(称为“gadgets”)+以下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 必须知道包含文件或定义符号的行在任何给定语言中的外观。您可以使用set include=$regexset define=$regex 中描述的:h include-search 中描述的~/.vim/ftplugin/$file_type.vim 中的每种语言设置它,但是,提出这些模式有点艺术,有时根本不可能,例如对于符号定义或文件导入可以跨越多行的语言(例如 Golang)。如果这是您的情况,通常的后备是 ctags,如其他答案中所述。

【讨论】:

coc 似乎没有提供一种通过搜索跳转到函数定义的方法,对吧?即如果我知道一个函数名,我可以使用 coc 从任何地方跳转到它吗? Coc 支持它自己的扩展类型并附带一些 - 其中有一个 symbols list 扩展。默认情况下它映射到&lt;space&gt;s(至少我认为它是 - 如果不是,只需输入:CocList symbols)。当列表触发时,您会获得输入以搜索变量、函数、类、接口等。 旁注:symbols list 不支持模糊搜索(或者不知道如何配置它)所以我经常发现自己使用files list 代替(至少对于类和接口)。最常见的列表插件位于::CocInstall coc-lists.【参考方案6】:

正如 Paul Tomblin 所说,您必须使用 ctags。 您也可以考虑使用 plugins 来选择合适的插件或预览光标下函数的定义。 如果没有插件,您将在尝试选择数百个重载的“doAction”方法之一时感到头疼,因为内置的 ctags 支持不考虑上下文 - 只是一个名称。

您也可以使用 cscope 及其“查找全局符号”功能。但是您的 vim 必须使用 +cscope 支持进行编译,这不是构建的默认选项之一。

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

这里是下载次数最多的导航插件http://www.vim.org/scripts/script.php?script_id=273

这是我为在跳转到标签时选择上下文而编写的一个http://www.vim.org/scripts/script.php?script_id=2507

【讨论】:

嗨@mykola-golubyev,您在#2507 脚本的Detailed description 部分提供的链接已损坏。请问可以再提供一个吗?【参考方案7】:

另一种常见的技术是将函数名称放在第一列。这允许通过简单的搜索找到定义。

int
main(int argc, char *argv[])

    ...

然后可以在文件中使用/^main 或在目录中使用:grep -r '^main' *.c 找到上述函数。只要代码正确缩进,标识符出现在行首的唯一时间就是函数定义处。

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

【讨论】:

我一直想知道为什么有些程序员会这样写他们的签名! 此外,当您编写函数签名时,包括第一列中的“”,您可以通过按 ]] 在文件中前进和 [[ 后退来快速移动到每个函数.【参考方案8】:

1- 安装丰富的 ctags。如果你使用的是 osx,这篇文章展示了一个小技巧: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- 如果您只想在您的目录中包含文件的 ctags,请在您的目录中运行此命令:

ctags -R

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

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

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

信用:https://coderwall.com/p/lv1qww (请注意,我省略了为 emacs 而不是 vim 生成标签的 -e 选项)

4- 将以下行添加到您的 ~/.vimrc

set autochdir 
set tags+=./tags;

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

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

【讨论】:

上述 Mac 文章的链接已损坏。这是更新后的链接:runtime-era.blogspot.com/2012/05/… 你最好的办法是使用 Homebrew 之类的工具安装 ctags【参考方案9】:

赞同 Paul 的回答:是的,ctags(尤其是 exuberant-ctags (http://ctags.sourceforge.net/))很棒。我也将它添加到我的 vimrc 中,所以我可以为整个项目使用一个标签文件:

set tags=tags;/

【讨论】:

【参考方案10】:

安装cscope。它的工作原理与ctags 非常相似,但功能更强大。要进行定义,请执行 Ctrl + \ + g 而不是 Ctrl + ] kbd>。当然,您可以同时使用两者。但是有了一个大项目(比如 Linux 内核),cscope 遥遥领先。

【讨论】:

【参考方案11】:

生成ctags后,还可以在vim中使用如下:

:tag <f_name>

上面将带你到函数定义。

【讨论】:

以上是关于跳转到函数定义的主要内容,如果未能解决你的问题,请参考以下文章

跳转到函数定义

webstorm怎么跳转到函数声明的地方

vscode怎么快速查看函数定义

apicloud 怎么跳转到另一个页面执行某个函数

vscode跳转到函数定义处

使用粘贴时如何跳转到emacs中的函数定义?