5

I want to toggle foldmethod between expr and manual because if we always set foldmethod=expr, then the cursor tends to move slowly in vim.

I think that foldexpr is evaluated just after switching foldmethod=expr, thus I try to toggle at every 5000ms in the following way. However, foldexpr can't be evaluated, which implies foldexpr is not evaluated just after switching foldmethod=expr.

Then, I have a question: how often or when is foldexpr evaluated? To my knowledge, there does not exist any document about timing of evaluation of foldexpr.

function! s:enable_expr(timer_id) abort
  setlocal foldmethod=expr
  setlocal foldmethod=manual
endfunction
autocmd CursorMoved * call s:cursor_moved()

let s:timer_id = timer_start(5000, function('s:enable_expr'))

function! s:cursor_moved() abort
  setlocal foldmethod=manual

  call timer_stop(s:timer_id)
  let s:timer_id = timer_start(5000, function('s:enable_expr'))
endfunction

REMARK: I know a way to toggle them by using InsertEnter and InsertLeave like here. But, if we employ the toggle in this way, then switching between insert mode and normal mode can become slow. Moreover, I use the command <C-o> a lot in insert mode, thus we want to avoid this implementation.

Thus, I want to make vim evaluate foldexpr once in all lines when the cursor holds.

Additional REMARK: I toggle them with the following implementation for now. A drawback of this implementation is when we move the cursor after 5000ms under the cursor-hold, the move of the cursor becomes slowly at the beginning due to the switching foldmethod.

function! s:enable_expr(timer_id) abort
  if &l:foldmethod ==# 'manual'
    setlocal foldmethod=expr
  endif
endfunction
autocmd CursorMoved * call s:cursor_moved()

let s:timer_id = timer_start(5000, function('s:enable_expr'))

function! s:cursor_moved() abort
  if &l:foldmethod ==# 'expr'
    setlocal foldmethod=manual
  endif
  call timer_stop(s:timer_id)
  let s:timer_id = timer_start(5000, function('s:enable_expr'))
endfunction

A temporary solution

augroup foldmethod-syntax
  autocmd InsertEnter,CursorMoved,CursorMovedI * if &l:foldmethod ==# 'expr'
  \                   |   setlocal foldmethod=manual
  \                   | endif
  autocmd BufWrite * if &l:foldmethod ==# 'manual'
  \                   |   setlocal foldmethod=expr
  \                   | endif
augroup END
  • 2
    Welcome to Vi and Vim! Another option would be to toggle foldenable on and off – D. Ben Knoble Aug 30 at 13:59
  • 1
    Thank you! I know a way to toggle them by using InsertEnter and InsertLeave. However, if we toggle them in this way, then the command <C-o> in insert mode tends to be slowly due to the toggle. I want to avoid this situation. – kumegon Aug 31 at 7:22
  • 2
    Try to profile your folding expression. See :h profile, and this answer. Rewriting the expression inside a :def function might increase the performance; once fixed, this todo item might help too. – user938271 Aug 31 at 21:15
2

Let's look into vim source code:

There is a function which is called when a change was made:

https://github.com/vim/vim/blob/85629985b71035608a37ba3bde86968481490d46/src/change.c#L429

This function triggers foldUpdate:

https://github.com/vim/vim/blob/85629985b71035608a37ba3bde86968481490d46/src/change.c#L537

Which does folding (including foldexpr):

https://github.com/vim/vim/blob/81fcb67fb32a12414512b72e691a1bbbff9f8511/src/fold.c#L842

This also happens when you start editing a file:

https://github.com/vim/vim/blob/451c2e3536a3cb77d07faf3cb2b834512e174351/src/ex_cmds.c#L1270

And when you set foldexpr options:

https://github.com/vim/vim/blob/d43906d2e5969288f239df851f5ad7b1dc2c7251/src/optionstr.c#L1994

And so on.

PS

There is a plugin https://github.com/Konfekt/FastFold that probably does what you want.

| improve this answer | |
  • Thank you for your answer.Your proposal plugin is just what I want!! – kumegon Sep 5 at 9:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.