Can you have Vim expand a fold automatically when the cursor touches it?
See the foldopen
option. It controls which groups of commands will lead to
opening a fold if the cursor is moved into a closed fold.
Note that vertical movements do not open a closed fold, though. Moreover,
there is no setting in foldopen
to enable this behavior. When hor
item is
set in foldopen
option, to open a fold one can use h
, l
or other
horizontal movement commands. In case if it is crucial to automatically open
a fold on any cursor movement that touches it, one can approach this problem
by remapping some subset of vertical movement commands like it is shown below.
nnoremap <silent> j :<c-u>call MoveUpDown('j', +1, 1)<cr>
nnoremap <silent> k :<c-u>call MoveUpDown('k', -1, 1)<cr>
nnoremap <silent> gj :<c-u>call MoveUpDown('gj', +1, 1)<cr>
nnoremap <silent> gk :<c-u>call MoveUpDown('gk', -1, 1)<cr>
nnoremap <silent> <c-d> :<c-u>call MoveUpDown("\<lt>c-d>", +1, '&l:scroll')<cr>
nnoremap <silent> <c-u> :<c-u>call MoveUpDown("\<lt>c-u>", -1, '&l:scroll')<cr>
nnoremap <silent> <c-f> :<c-u>call MoveUpDown("\<lt>c-f>", +1, 'winheight("%")')<cr>
nnoremap <silent> <c-b> :<c-u>call MoveUpDown("\<lt>c-b>", -1, 'winheight("%")')<cr>
function! MoveUpDown(cmd, dir, ndef)
let n = v:count == 0 ? eval(a:ndef) : v:count
let l = line('.') + a:dir * n
silent! execute l . 'foldopen!'
execute 'norm! ' . n . a:cmd
endfunction
An inferior, but a bit thriftier solution would be to open a fold on every cursor movement.
autocmd CursorMoved,CursorMovedI * silent! foldopen
Unfortunately, this solution is not general one. After the fold under the cursor is opened, the cursor is positioned on the first line of that fold. If this behavior is undesirable, one can follow the vertical direction of a movement, and place the cursor on the last line of the fold when the cursor is moving bottom-up.
autocmd CursorMoved,CursorMovedI * call OnCursorMove()
function! OnCursorMove()
let l = line('.')
silent! foldopen
if exists('b:last_line') && l < b:last_line
norm! ]z
endif
let b:last_line = l
endfunction
However, a fold will not be opened if the movement jumps over the fold. For
example, 2j
on the line just above a fold will put the cursor on the line
just after that fold, not the second line in it.
set foldopen=all
seems to do what you want. You may also make an autocommand for cursor movement:
au CursorMoved * call AutoOpen()
calling a function like:
function! AutoOpen()
if foldclosed(".") == line(".")
call feedkeys("zo")
endif
endfunction
If you want this to also work in insert mode, use:
au CursorMoved,CursorMovedI * call AutoOpen()
:help fdo
and possibly :help fcl
may help you. I have this line in my .vimrc:
set foldopen=block,hor,insert,jump,mark,percent,quickfix,search,tag,undo
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