在Vim中,是否有可能跳转到下一个已关闭的折叠?

39
在Vim中,我经常想要快速执行zkzj以跳转到文件中的前一个或后一个折叠。问题在于,我经常希望跳过所有打开的折叠,只跳到最近的闭合折叠。
有没有办法做到这一点?我在帮助中没有看到内置的按键映射。
2个回答

42

让我提出以下所描述行为的实现方式。

nnoremap <silent> <leader>zj :call NextClosedFold('j')<cr>
nnoremap <silent> <leader>zk :call NextClosedFold('k')<cr>

function! NextClosedFold(dir)
    let cmd = 'norm!z'..a:dir
    let view = winsaveview()
    let [l0, l, open] = [0, view.lnum, 1]
    while l != l0 && open
        exe cmd
        let [l0, l] = [l, line('.')]
        let open = foldclosed(l) < 0
    endwhile
    if open
        call winrestview(view)
    endif
endfunction

如果希望映射接受相应运动的重复次数,可以实现一个简单的函数重复任何给定的命令:

function! RepeatCmd(cmd) range abort
    let n = v:count < 1 ? 1 : v:count
    while n > 0
        exe a:cmd
        let n -= 1
    endwhile
endfunction

然后重新定义上述映射如下:

nnoremap <silent> <leader>zj :<c-u>call RepeatCmd('call NextClosedFold("j")')<cr>
nnoremap <silent> <leader>zk :<c-u>call RepeatCmd('call NextClosedFold("k")')<cr>

1
@David:谢谢!我对代码进行了重构,简化了跳转循环,并在所需方向上没有关闭的折叠时保持光标不动。 (当zj/zk命令在下面/上面找不到折叠时,后一行为其行为)。 - ib.
@ib,请您提供修改后的脚本,好吗? - Glenn Jorde
@Glenn:如果你指的是我在评论中提到的重构,那么答案中的代码已经更新包含了它。 - ib.
有没有办法修改这个函数,使其允许计数,例如 [count]<leader>zj - travisw
1
@travisw:有的。我已经更新了答案,展示了一种支持在所提出的映射中计数重复次数的方法。 - ib.

1

据我所知,没有内置的方法可以做到这一点。不过这是个有趣的想法。

如果我现在有时间,我可能会尝试找出一种方法来实现它——不幸的是,现在很忙,我能建议你的是看看 检测折叠行或增量搜索 问题(特别是 foldclosed 函数),然后尝试自己编写一个函数。检查每一行,如果折叠是打开的,则跳过……类似这样的操作。


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