fix(init): prevent infinite filetype retry loop on did_filetype

Problem: the deferred filetype retry in ensure_cache created an infinite
invalidation loop. did_filetype() stays 1 for the lifetime of a buffer
opened via FileType autocmd — it never resets in vim.schedule callbacks.
Each retry reparsed, found has_nil_ft=true again, and scheduled another
retry. Each iteration cleared all extmarks via pending_clear, causing the
deferred syntax pass to bail on its tick check. Result: language syntax
highlighting never settled on buffers containing files with
function-handled extensions (.sh, .bash, .conf, etc).

Solution: add ft_retry_pending guard table. Set before scheduling the
retry, check before scheduling again. The flag is set while the callback
is pending and during the synchronous redraw inside it, preventing the
reparse from scheduling another iteration. Cleared after the callback
completes. Cleaned up on BufWipeout.
This commit is contained in:
Barrett Ruth 2026-03-04 13:44:57 -05:00
parent 907387b64f
commit 0a10f3882d
Signed by: barrett
GPG key ID: A6C96C9349D2FC81

View file

@ -169,6 +169,9 @@ local fast_hl_opts = {} ---@type diffs.HunkOpts
---@type table<integer, boolean>
local attached_buffers = {}
---@type table<integer, boolean>
local ft_retry_pending = {}
---@type table<integer, boolean>
local diff_windows = {}
@ -334,13 +337,15 @@ local function ensure_cache(bufnr)
has_nil_ft = true
end
end
if has_nil_ft and vim.fn.did_filetype() ~= 0 then
if has_nil_ft and vim.fn.did_filetype() ~= 0 and not ft_retry_pending[bufnr] then
ft_retry_pending[bufnr] = true
vim.schedule(function()
if vim.api.nvim_buf_is_valid(bufnr) and hunk_cache[bufnr] then
dbg('retrying filetype detection for buffer %d (was blocked by did_filetype)', bufnr)
invalidate_cache(bufnr)
vim.cmd('redraw')
vim.cmd.redraw()
end
ft_retry_pending[bufnr] = nil
end)
end
end
@ -864,6 +869,7 @@ function M.attach(bufnr)
callback = function()
attached_buffers[bufnr] = nil
hunk_cache[bufnr] = nil
ft_retry_pending[bufnr] = nil
if neogit_augroup then
pcall(vim.api.nvim_del_augroup_by_id, neogit_augroup)
end