Vim:跳转到下一个方法的开头/结尾

45
Vim 中是否有本地功能可以使光标移动到下一个/上一个方法的开头/结尾?我已经知道了[[,]],[],和][,但它们并不能满足需求,因为它们只能在列零处的大括号中起作用。因此,在浏览 C++ 代码时,它们没有什么用处。是否有这样的命令已经内置在 Vim 中?如果没有,您会推荐实现它的插件吗?
感谢您的帮助!
编辑:[{和}]并不能一直工作,因为您必须在带有{}的块内部(而不是在该块内的某个更深的范围内)才能最终到达正确的{}之后。
编辑2:这是一个代码清单,其中[m]等命令无法使用。
namespace foo {

#define define_foo         \
    template <class T>     \
    struct foo_traits<X>   \
    {                      \
        using foo = X;     \
    };

template <class T>
struct foo_traits;

define_bar(T*, T*, T*);

template <class T>
struct baz;

template <class T>
struct baz<T&>
{
    static T* apply(T& t) { return &t; }
};

template <class T>
inline T a(T t) { return t; }

}

@EitanT 我应该提到,这些也不总是有效的,因为你必须在括号内部。 - void-pointer
11
[m]、]m[、]m和]M[这些符号代表什么? - Eitan T
@void-pointer 我曾经只使用vim进行编辑,我并不认为使用IDE会有任何区别。八年前,我开始使用IDE,当你看到IDE提供的内置功能时,我只能得出结论:有些人更喜欢用困难的方式做事情(承认我曾经是其中之一)。 - Peter Lawrey
1
我对C++不是很熟悉,但我使用过eclipse。它有一个vim插件,可以提供大部分功能。我发现在IDE中,许多需要导航的操作都不再需要了。例如,在Java中,如果您使用了一个未被导入/定义的类、字段或方法,它会在您的代码中添加它,而无需滚动到它所在的位置,添加它并滚动回来。如果您想在包之间移动一个类,您可以拖放所有引用(甚至注释、XML和文本文件引用)都可以更改。<Ctrl>+<Click>跳转到某个声明。 - Peter Lawrey
@EitanT 这些快捷键具体是做什么的?我刚刚尝试了一下,它有时会停在方法内的空格行上,有时会跳转到不同的方法之间... - User
显示剩余4条评论
5个回答

89

Vim内置了用于Java或类似结构化语言的 "[m / ]m"。

我编写了定制版本,可以处理Vim函数VBScript批处理文件等。这些都由我的CountJump插件驱动,可以使用正则表达式编写自定义跳转函数。


2
我认为对于C++的支持需要更加强大的工具,而不是普通的正则表达式,因为即使使用[m]m[M]M等字符,在我的C++代码中也无法正常工作。 - void-pointer
1
如果你需要一个100%的解决方案,你需要一个完整的C++解析器;但通常,使用正则表达式可以实现“大部分正确”的解决方案;参见Vim的语法高亮。 - Ingo Karkat
哇!从来不知道这个动作存在。 它在neovim的typescript / javascript上运行得非常好。 我很高兴发现这个内置的vim动作。 太酷了。 - avimehenwal

13
我花了几个小时来制作这个模式:/^\s*\(\i\+\_[ \t\*]\+\)\+\i\+\_s*(\_[^)]*)\_s*{,对我很有效。

编辑:更好的模式(版本2):/\(\(if\|for\|while\|switch\|catch\)\_s*\)\@64<!(\_[^)]*)\_[^;{}()]*\zs{

查看效果: enter image description here enter image description here

你可以在你的 .vimrc 中映射一些方便的 绑定,例如:

" jump to the previous function
nnoremap <silent> [f :call search('^\s*\(\i\+\_[ \t\*]\+\)\+\i\+\_s*(\_[^)]*)\_s*{', "bw")<CR>
" jump to the next function
nnoremap <silent> ]f :call search('^\s*\(\i\+\_[ \t\*]\+\)\+\i\+\_s*(\_[^)]*)\_s*{', "w")<CR>

编辑: 更好的模式(版本2):

" jump to the previous function
nnoremap <silent> [f :call
\ search('\(\(if\\|for\\|while\\|switch\\|catch\)\_s*\)\@64<!(\_[^)]*)\_[^;{}()]*\zs{', "bw")<CR>
" jump to the next function
nnoremap <silent> ]f :call
\ search('\(\(if\\|for\\|while\\|switch\\|catch\)\_s*\)\@64<!(\_[^)]*)\_[^;{}()]*\zs{', "w")<CR>

感谢您包含了详细的信息,包括使用“search”命令的“noremap”命令。虽然我的问题与此不同,但是您提供的示例帮助我解决了这个问题。 - Jeff Learman

4

看起来是一个重复的问题:Vim [m motion with c#

你可以尝试这个不太好的方法:9]}。它只是从当前位置跳到第9个}(如果你没有嵌套得太深,应该能行...)


1

Vim并不完全理解您的代码,因此建议的解决方案可能无法完美运行。

较新的Helix编辑器(一种现代化的vim替代品)具有tree-sitter集成功能,使您可以跳转到函数/参数/方法/类。


0
如果您使用taglist,我添加了一个功能来实现这一点。您可以使用Ctrl-up和Ctrl-down从一个标签跳转到另一个标签,前提是该语言受taglist支持。
在这里:https://github.com/man9ourah/taglist 并将此添加到您的.vimrc文件中。
nmap <silent> <c-up> <plug>(TlistJumpTagUp)     " Map ctrl-up to move one tag up
nmap <silent> <c-down> <plug>(TlistJumpTagDown) " Map ctrl-down to move one tag down

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