fix(compiler): use BufDelete instead of BufUnload for cleanup

Problem: `:e` (edit/reload) fires `BufUnload`, which tears down the
entire preview — process, watchers, and viewer — even though the user
is just reloading the current buffer.

Solution: Switch the cleanup autocmd from `BufUnload` to `BufDelete`,
which only fires on `:bdelete` and `:bwipeout`. Guard `nvim_del_autocmd`
calls with `pcall` in cleanup paths since buffer-local autocmds may
already be gone when the buffer is wiped before `stop_watching` runs.

Closes #57
This commit is contained in:
Barrett Ruth 2026-03-12 16:47:36 -04:00
parent 535d4cfd5e
commit a2edb9a499
Signed by: barrett
GPG key ID: A6C96C9349D2FC81

View file

@ -16,7 +16,7 @@ local log = require('preview.log')
---@field has_errors? boolean
---@field debounce? uv.uv_timer_t
---@field bwp_autocmd? integer
---@field unload_autocmd? integer
---@field cleanup_autocmd? integer
---@type table<integer, preview.BufState>
local state = {}
@ -189,7 +189,7 @@ local function stop_watching(bufnr, s)
close_viewer(bufnr)
s.viewer_open = nil
if s.bwp_autocmd then
vim.api.nvim_del_autocmd(s.bwp_autocmd)
pcall(vim.api.nvim_del_autocmd, s.bwp_autocmd)
s.bwp_autocmd = nil
end
if s.debounce then
@ -508,8 +508,8 @@ end
function M.stop_all()
for bufnr, s in pairs(state) do
stop_watching(bufnr, s)
if s.unload_autocmd then
vim.api.nvim_del_autocmd(s.unload_autocmd)
if s.cleanup_autocmd then
pcall(vim.api.nvim_del_autocmd, s.cleanup_autocmd)
end
state[bufnr] = nil
end
@ -541,10 +541,10 @@ function M.toggle(bufnr, name, provider, ctx_builder)
log.dbg('toggle on for buffer %d', bufnr)
s.watching = true
if s.unload_autocmd then
vim.api.nvim_del_autocmd(s.unload_autocmd)
if s.cleanup_autocmd then
vim.api.nvim_del_autocmd(s.cleanup_autocmd)
end
s.unload_autocmd = vim.api.nvim_create_autocmd('BufUnload', {
s.cleanup_autocmd = vim.api.nvim_create_autocmd('BufDelete', {
buffer = bufnr,
once = true,
callback = function()