feat(buffer): preserve category fold state across re-renders
Problem: pressing :w, toggling priority, or any other operation that calls buffer.render() reset foldlevel = 99, causing all manually collapsed category sections to snap back open. Solution: snapshot which categories are folded (per window) before nvim_buf_set_lines destroys the fold tree, then restore them after fold options are re-applied by calling normal! zc on each previously closed header line. State persists across all render call sites within a session.
This commit is contained in:
parent
fc4a47a1ec
commit
7f0bd43b34
1 changed files with 48 additions and 0 deletions
|
|
@ -12,6 +12,8 @@ local task_ns = vim.api.nvim_create_namespace('pending')
|
|||
local current_view = nil
|
||||
---@type pending.LineMeta[]
|
||||
local _meta = {}
|
||||
---@type table<integer, table<string, boolean>>
|
||||
local _fold_state = {}
|
||||
|
||||
---@return pending.LineMeta[]
|
||||
function M.meta()
|
||||
|
|
@ -148,6 +150,50 @@ local function setup_highlights()
|
|||
vim.api.nvim_set_hl(0, 'PendingPriority', { link = 'DiagnosticWarn', default = true })
|
||||
end
|
||||
|
||||
local function snapshot_folds(bufnr)
|
||||
if current_view ~= 'category' then
|
||||
return
|
||||
end
|
||||
for _, winid in ipairs(vim.fn.win_findbuf(bufnr)) do
|
||||
local state = {}
|
||||
vim.api.nvim_win_call(winid, function()
|
||||
for lnum, m in ipairs(_meta) do
|
||||
if m.type == 'header' and m.category then
|
||||
if vim.fn.foldclosed(lnum) ~= -1 then
|
||||
state[m.category] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
_fold_state[winid] = state
|
||||
end
|
||||
end
|
||||
|
||||
local function restore_folds(bufnr)
|
||||
if current_view ~= 'category' then
|
||||
return
|
||||
end
|
||||
for _, winid in ipairs(vim.fn.win_findbuf(bufnr)) do
|
||||
local state = _fold_state[winid]
|
||||
if not state or next(state) == nil then
|
||||
goto continue
|
||||
end
|
||||
vim.api.nvim_win_call(winid, function()
|
||||
vim.cmd('normal! zx')
|
||||
local saved = vim.api.nvim_win_get_cursor(0)
|
||||
for lnum, m in ipairs(_meta) do
|
||||
if m.type == 'header' and m.category and state[m.category] then
|
||||
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
|
||||
vim.cmd('normal! zc')
|
||||
end
|
||||
end
|
||||
vim.api.nvim_win_set_cursor(0, saved)
|
||||
end)
|
||||
_fold_state[winid] = nil
|
||||
::continue::
|
||||
end
|
||||
end
|
||||
|
||||
---@param bufnr? integer
|
||||
function M.render(bufnr)
|
||||
bufnr = bufnr or task_bufnr
|
||||
|
|
@ -167,6 +213,7 @@ function M.render(bufnr)
|
|||
|
||||
_meta = line_meta
|
||||
|
||||
snapshot_folds(bufnr)
|
||||
vim.bo[bufnr].modifiable = true
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
vim.bo[bufnr].modified = false
|
||||
|
|
@ -185,6 +232,7 @@ function M.render(bufnr)
|
|||
vim.wo[winid].foldenable = false
|
||||
end
|
||||
end
|
||||
restore_folds(bufnr)
|
||||
end
|
||||
|
||||
function M.toggle_view()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue