dhruvasagar / vim-table-mode

VIM Table Mode for instant table creation.
2.11k stars 96 forks source link

Disable/restore foldmethod during realignment #134

Closed jeetsukumaran closed 6 years ago

jeetsukumaran commented 6 years ago

During realignment, folds are recalculated multiple times --- once for each line set via "setline()". When foldmethod==expr and the expression is difficult to calculate (e.g., pandoc/restructuredtext), the performance hit is incredible, especially on tables with many lines.

A simple fix is to suspend fold calculation while the table is being composed. This patch simply saves the foldmethod before realignment, switches it to "manual", carries out the realignment, and then restores the foldmethod again.

With this even very large tables combined with very expensive fold expression calculations are still performant.

Update (Clarification)

The foldmethod expression is actually called for the whole document once for each line set during realignment. So, if the table is 100 lines long and the entire document is a 1000 lines long, the foldmethod expression will be called not just 100 times, but 100,000 times! To see the performance hit, just set:

function! F()
  return "="
endfunction
set foldmethod=F()

and try realigning a large table. Vim totally freezes.

With this PR, the problem is largely solved.

dhruvasagar commented 6 years ago

That's interesting, thanks for this PR. This may also be applicable to other similar expr stuff like indentexpr i suppose ?

jeetsukumaran commented 6 years ago

I think so, but not sure. Problem it is not clearly documented what stuff gets triggered when setline() is used. In addition to background Vim tasks such as folding/indents, I wonder about various autocmds, especially, e.g. InsertEnter/Leave events? This might have been what was causing the issues when the auto-aligning was triggered by an InsertLeave autocommand that caused you to go back to CursorHold --- recursion tailspin until all lines in the table were (finally) updated?

dhruvasagar commented 6 years ago

I doubt if autocmd could be an issue, though we can get past that simply by using :noautocmd