David
David

Reputation: 20085

Is it possible to jump to the next closed fold in Vim?

In Vim, I often find myself wanting to do a quick zk or zj to jump to the previous or next fold in a file. The problem is, I frequently want to skip all the open folds, and just jump to the nearest closed fold.

Is there a way to do this? I see no built-in keymap in the help.

Upvotes: 40

Views: 6615

Answers (2)

ib.
ib.

Reputation: 28934

Let me propose the following implementation of the described behavior.

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

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

If it is desirable for the mappings to accept a count for the number of repetitions of the corresponding movement, one can implement a simple function for repeating any given command:

func! RepeatCmd(cmd) range abort
    let n = v:count < 1 ? 1 : v:count
    while n > 0
        exec a:cmd
        let n -= 1
    endwhile
endfunc

and then redefine the above mappings as follows:

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

Upvotes: 44

Rook
Rook

Reputation: 62528

No, there isn't, as far as I know, a build-in method to do that. Interesting idea, though.

If I had some time at the moment, I might try to figure out a way to do it — unfortunately, being busy nowadays, all I can suggest you is to look at the Detecting a folded line or an incremental search question (particularly the foldclosed function) and try to make a function yourself. Checking every line, if fold is open, skip… something along those lines.

Upvotes: 1

Related Questions