aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim
diff options
context:
space:
mode:
authorJaehwang Jung <tomtomjhj@gmail.com>2023-07-07 19:12:46 +0900
committerGitHub <noreply@github.com>2023-07-07 11:12:46 +0100
commitc44d819ae1f29cd34ee3b2350b5c702caed949c3 (patch)
tree4cccd21d5ddf9c7196224dd72850ea81d40eb3f1 /runtime/lua/vim
parent811140e276a6312775bfcf9b368de25386f7a356 (diff)
downloadrneovim-c44d819ae1f29cd34ee3b2350b5c702caed949c3.tar.gz
rneovim-c44d819ae1f29cd34ee3b2350b5c702caed949c3.tar.bz2
rneovim-c44d819ae1f29cd34ee3b2350b5c702caed949c3.zip
fix(treesitter): update folds in all relevant windows (#24230)
Problem: When using treesitter foldexpr, * :diffput/get open diff folds, and * folds are not updated in other windows that contain the updated buffer. Solution: Update folds in all windows that contain the updated buffer and use expr foldmethod.
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r--runtime/lua/vim/treesitter/_fold.lua34
1 files changed, 26 insertions, 8 deletions
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
index d308657237..a02d0a584d 100644
--- a/runtime/lua/vim/treesitter/_fold.lua
+++ b/runtime/lua/vim/treesitter/_fold.lua
@@ -232,20 +232,40 @@ local M = {}
---@type table<integer,TS.FoldInfo>
local foldinfos = {}
-local function recompute_folds()
+--- Update the folds in the windows that contain the buffer and use expr foldmethod (assuming that
+--- the user doesn't use different foldexpr for the same buffer).
+---
+--- Nvim usually automatically updates folds when text changes, but it doesn't work here because
+--- FoldInfo update is scheduled. So we do it manually.
+local function foldupdate(bufnr)
+ local function do_update()
+ for _, win in ipairs(vim.fn.win_findbuf(bufnr)) do
+ api.nvim_win_call(win, function()
+ if vim.wo.foldmethod == 'expr' then
+ vim._foldupdate()
+ end
+ end)
+ end
+ end
+
if api.nvim_get_mode().mode == 'i' then
-- foldUpdate() is guarded in insert mode. So update folds on InsertLeave
api.nvim_create_autocmd('InsertLeave', {
once = true,
- callback = vim._foldupdate,
+ callback = do_update,
})
return
end
- vim._foldupdate()
+ do_update()
end
---- Schedule a function only if bufnr is loaded
+--- Schedule a function only if bufnr is loaded.
+--- We schedule fold level computation for the following reasons:
+--- * queries seem to use the old buffer state in on_bytes for some unknown reason;
+--- * to avoid textlock;
+--- * to avoid infinite recursion:
+--- get_folds_levels → parse → _do_callback → on_changedtree → get_folds_levels.
---@param bufnr integer
---@param fn function
local function schedule_if_loaded(bufnr, fn)
@@ -261,14 +281,12 @@ end
---@param foldinfo TS.FoldInfo
---@param tree_changes Range4[]
local function on_changedtree(bufnr, foldinfo, tree_changes)
- -- For some reason, queries seem to use the old buffer state in on_bytes.
- -- Get around this by scheduling and manually updating folds.
schedule_if_loaded(bufnr, function()
for _, change in ipairs(tree_changes) do
local srow, _, erow = Range.unpack4(change)
get_folds_levels(bufnr, foldinfo, srow, erow)
end
- recompute_folds()
+ foldupdate(bufnr)
end)
end
@@ -289,7 +307,7 @@ local function on_bytes(bufnr, foldinfo, start_row, old_row, new_row)
end
schedule_if_loaded(bufnr, function()
get_folds_levels(bufnr, foldinfo, start_row, end_row_new)
- recompute_folds()
+ foldupdate(bufnr)
end)
end
end