@@ -13,6 +13,10 @@ M._prev_line_count_by_win = {}
1313local _update_depth = 0
1414local _update_buf = nil
1515
16+ local function is_win_showing_buf (win , buf )
17+ return win and vim .api .nvim_win_is_valid (win ) and vim .api .nvim_win_get_buf (win ) == buf
18+ end
19+
1620--- Begin a batch of buffer writes — toggle modifiable once for the whole batch.
1721--- Returns true if the batch was opened (buffer is valid). Must be paired with end_update().
1822--- @return boolean
@@ -320,29 +324,60 @@ end
320324_G .opencode_fold_expr = M .fold_expr
321325_G .opencode_fold_text = M .fold_text
322326
327+ function M .snapshot_open_folds (win , prev_folds )
328+ local ok , result = pcall (vim .api .nvim_win_call , win , function ()
329+ local open = {}
330+ for _ , range in ipairs (prev_folds ) do
331+ if vim .fn .foldclosed (range .from ) == - 1 then
332+ open [# open + 1 ] = range .from
333+ end
334+ end
335+ return open
336+ end )
337+ return ok and result or {}
338+ end
339+
340+ function M .restore_open_folds (win , open_fold_starts )
341+ pcall (vim .api .nvim_win_call , win , function ()
342+ local view = vim .fn .winsaveview ()
343+ vim .cmd (' silent! normal! zX' )
344+ for _ , lnum in ipairs (open_fold_starts ) do
345+ if vim .fn .foldclosed (lnum ) ~= - 1 then
346+ vim .fn .cursor (lnum , 1 )
347+ vim .cmd (' silent! normal! zo' )
348+ end
349+ end
350+ vim .fn .winrestview (view )
351+ end )
352+ end
353+
323354--- Set the folds for the output buffer
324355--- @param fold_ranges table< {from : number , to : number } >
325356function M .set_folds (fold_ranges )
326357 local windows = state .windows
327- if not windows or not windows .output_buf or not vim .api .nvim_buf_is_valid (windows .output_buf ) then
358+ local buf = windows .output_buf
359+ if not M .mounted () then
328360 return
329361 end
330362
331363 local folds = fold_ranges or {}
332- local buf = windows .output_buf
333- local win = windows .output_win
334-
335364 local ok , prev_folds = pcall (vim .api .nvim_buf_get_var , buf , ' opencode_folds' )
336- if ok and vim .deep_equal (prev_folds , folds ) then
365+ if ok and # folds == # prev_folds and vim .deep_equal (prev_folds , folds ) then
337366 return
338367 end
339368
369+ local win = windows .output_win
370+ local win_owns_buf = is_win_showing_buf (win , buf )
371+
372+ local open_fold_starts = {}
373+ if ok and win_owns_buf then
374+ open_fold_starts = M .snapshot_open_folds (win , prev_folds )
375+ end
376+
340377 vim .api .nvim_buf_set_var (buf , ' opencode_folds' , folds )
341378
342- if win and vim .api .nvim_win_is_valid (win ) and vim .api .nvim_win_get_buf (win ) == buf then
343- pcall (vim .api .nvim_win_call , win , function ()
344- vim .cmd (' silent! normal! zX' )
345- end )
379+ if win_owns_buf then
380+ M .restore_open_folds (win , open_fold_starts )
346381 end
347382end
348383
0 commit comments