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.
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.
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.
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.
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.
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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With