Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to expand a Vim fold automatically when your put your cursor on it?

Tags:

vim

Can you have Vim expand a fold automatically when the cursor touches it?

like image 842
dan Avatar asked Aug 11 '11 23:08

dan


3 Answers

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.

like image 176
12 revs Avatar answered Sep 30 '22 12:09

12 revs


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()
like image 32
Eelvex Avatar answered Sep 30 '22 12:09

Eelvex


: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
like image 34
romainl Avatar answered Sep 30 '22 14:09

romainl