fix(buffer): fix stale extmarks, duplicate window, and fold state loss

Problem: Deleting lines (`dd`, `dat`, `d3j`) left extmarks stranded on
adjacent rows since `render()` only clears and reapplies marks on `:w`.
Quickfix `<CR>` opened the pending buffer in a second window because
`BufEnter` did not redirect to `task_winid`. Category fold state was
lost across `<Tab>/<Tab>` view toggles because `render()` overwrote the
saved state with an empty snapshot taken while folds were disabled.

Solution: Add a `TextChanged`/`TextChangedI` autocmd that clears the
extmark namespace immediately on any edit. Fix `BufEnter` to close
duplicate windows and redirect focus to `task_winid`, updating it when
stale. Fix `snapshot_folds` to skip if a state is already saved, and
`restore_folds` to always clear the saved state; snapshot in
`toggle_view` before the view flips so the state survives the round-trip.
This commit is contained in:
Barrett Ruth 2026-03-06 21:30:58 -05:00
parent c392874311
commit b41fab79a3
2 changed files with 43 additions and 1 deletions

View file

@ -77,6 +77,18 @@ function M.clear_winid()
task_winid = nil
end
---@param winid integer
---@return nil
function M.update_winid(winid)
task_winid = winid
end
---@param b? integer
---@return nil
function M.clear_marks(b)
vim.api.nvim_buf_clear_namespace(b or task_bufnr, task_ns, 0, -1)
end
---@return nil
function M.close()
if not task_winid or not vim.api.nvim_win_is_valid(task_winid) then
@ -263,6 +275,9 @@ local function snapshot_folds(bufnr)
return
end
for _, winid in ipairs(vim.fn.win_findbuf(bufnr)) do
if _fold_state[winid] ~= nil then
goto continue
end
local state = {}
vim.api.nvim_win_call(winid, function()
for lnum, m in ipairs(_meta) do
@ -274,6 +289,7 @@ local function snapshot_folds(bufnr)
end
end)
_fold_state[winid] = state
::continue::
end
end
@ -283,6 +299,7 @@ local function restore_folds(bufnr)
end
for _, winid in ipairs(vim.fn.win_findbuf(bufnr)) do
local state = _fold_state[winid]
_fold_state[winid] = nil
if state and next(state) ~= nil then
vim.api.nvim_win_call(winid, function()
vim.cmd('normal! zx')
@ -295,7 +312,6 @@ local function restore_folds(bufnr)
end
vim.api.nvim_win_set_cursor(0, saved)
end)
_fold_state[winid] = nil
end
end
end
@ -372,6 +388,7 @@ end
---@return nil
function M.toggle_view()
snapshot_folds(task_bufnr)
if current_view == 'category' then
current_view = 'priority'
else