perf(treesitter): incremental foldupdate

Problem:
While the fold level computation is incremental, the evaluation of the
foldexpr is done on the full buffer. Despite that the foldexpr reads
from the cache, it can take tens of milliseconds for moderately big (10K
lines) buffers.

Solution:
Track the range of lines on which the foldexpr should be evaluated.
This commit is contained in:
Jaehwang Jung
2024-04-20 02:33:44 +09:00
committed by Christian Clason
parent f42ab1dc48
commit 2b6c9bbe7f
2 changed files with 89 additions and 56 deletions

View File

@@ -543,14 +543,25 @@ static int nlua_iconv(lua_State *lstate)
return 1;
}
// Update foldlevels (e.g., by evaluating 'foldexpr') for all lines in the current window without
// invoking other side effects. Unlike `zx`, it does not close manually opened folds and does not
// open folds under the cursor.
// Update foldlevels (e.g., by evaluating 'foldexpr') for the given line range in the given window,
// without invoking other side effects. Unlike `zx`, it does not close manually opened folds and
// does not open folds under the cursor.
static int nlua_foldupdate(lua_State *lstate)
{
curwin->w_foldinvalid = true; // recompute folds
foldUpdate(curwin, 1, (linenr_T)MAXLNUM);
curwin->w_foldinvalid = false;
handle_T window = (handle_T)luaL_checkinteger(lstate, 1);
Error err = ERROR_INIT;
win_T *win = find_window_by_handle(window, &err);
if (ERROR_SET(&err)) {
nlua_push_errstr(lstate, err.msg);
api_clear_error(&err);
lua_error(lstate);
return 0;
}
linenr_T start = (linenr_T)luaL_checkinteger(lstate, 2);
linenr_T end = (linenr_T)luaL_checkinteger(lstate, 3);
foldUpdate(win, start + 1, end);
return 0;
}