Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 661
David Avatar asked Feb 22 '12 21:02

David


People also ask

How do I go to previous in Vim?

Ctrl + O takes me to the previous location. Don't know about location before the search. Edit: Also, ` . will take you to the last change you made. It also appears that pressing CTRL+O enough times will also start taking you back through previously opened files.

How does folding work in Vim?

Vim uses the same movement commands to define folds. Folding also works in visual mode. If you enter visual mode using v or V , then select a few lines of text using the movement keys, and type zf , Vim will create a fold comprising those lines. Another option is to specify a range in command mode.

How do I fold in Vim?

With the following in your vimrc, you can toggle folds open/closed by pressing F9. In addition, if you have :set foldmethod=manual , you can visually select some lines, then press F9 to create a fold. Here is an alternative procedure: In normal mode, press Space to toggle the current fold open/closed.

How do I expand all lines in Vim?

To expand the lines, put the cursor over the fold and hit spacebar (in vim terminology, this deletes the fold). (Side note: you may want to change the look of collapsed folds.


2 Answers

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>  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 

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:

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

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> 
like image 183
ib. Avatar answered Oct 09 '22 00:10

ib.


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.

like image 22
Rook Avatar answered Oct 09 '22 02:10

Rook