From 2b6c9bbe7f7ac950683e81129b76e35e35839ede Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 20 Apr 2024 02:33:44 +0900 Subject: 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. --- src/nvim/lua/stdlib.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index 788185f2b4..032cb246bf 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -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; } -- cgit