diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 5581733fbc..d82b7a2f88 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -462,15 +462,16 @@ reads back as the function (from Lua) or a `""` hint (Vimscript/RPC). Setting the filetype :setf[iletype] [FALLBACK] {filetype} *:setf* *:setfiletype* - Set the 'filetype' option to {filetype}, but only if - not done yet in a sequence of (nested) autocommands. + Set the 'filetype' option to {filetype}, unless it was + already set (non-empty) in a sequence of (nested) + autocommands. This is short for: > :if !did_filetype() : setlocal filetype={filetype} :endif -< This command is used in a filetype.vim file to avoid - setting the 'filetype' option twice, causing different - settings and syntax files to be loaded. +< Used in a filetype.vim file to avoid setting the + 'filetype' option twice, causing different settings + and syntax files to be loaded. When the optional FALLBACK argument is present, a later :setfiletype command will override the diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt index f8e33e6d36..2ad24365fb 100644 --- a/runtime/doc/vimfn.txt +++ b/runtime/doc/vimfn.txt @@ -1743,10 +1743,11 @@ dictwatcherdel({dict}, {pattern}, {callback}) *dictwatcherdel()* did_filetype() *did_filetype()* Returns |TRUE| when autocommands are being executed and the - FileType event has been triggered at least once. Can be used - to avoid triggering the FileType event again in the scripts - that detect the file type. |FileType| + FileType event triggered at least once for a buffer with + a non-empty 'filetype'. Can be used to avoid triggering + the FileType event again in the |ftdetect| scripts. |FileType| Returns |FALSE| when `:setf FALLBACK` was used. + When editing another file, the counter is reset, thus this really checks if the FileType event has been triggered for the current buffer. This allows an autocommand that starts diff --git a/runtime/lua/vim/_meta/vimfn.gen.lua b/runtime/lua/vim/_meta/vimfn.gen.lua index 6c439e5c8c..79577042b8 100644 --- a/runtime/lua/vim/_meta/vimfn.gen.lua +++ b/runtime/lua/vim/_meta/vimfn.gen.lua @@ -1528,10 +1528,11 @@ function vim.fn.dictwatcheradd(dict, pattern, callback) end function vim.fn.dictwatcherdel(dict, pattern, callback) end --- Returns |TRUE| when autocommands are being executed and the ---- FileType event has been triggered at least once. Can be used ---- to avoid triggering the FileType event again in the scripts ---- that detect the file type. |FileType| +--- FileType event triggered at least once for a buffer with +--- a non-empty 'filetype'. Can be used to avoid triggering +--- the FileType event again in the |ftdetect| scripts. |FileType| --- Returns |FALSE| when `:setf FALLBACK` was used. +--- --- When editing another file, the counter is reset, thus this --- really checks if the FileType event has been triggered for the --- current buffer. This allows an autocommand that starts diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 0b529f0757..909c8263bc 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1710,8 +1710,8 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL); nesting++; // see matching decrement below - // Remember that FileType was triggered. Used for did_filetype(). - if (event == EVENT_FILETYPE) { + // Remember that FileType was triggered, if 'filetype' was actually set. For :setf. + if (event == EVENT_FILETYPE && *curbuf->b_p_ft != NUL) { curbuf->b_did_filetype = true; } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 2e37a8bc76..3e4e535970 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -1952,10 +1952,11 @@ M.funcs = { did_filetype = { desc = [=[ Returns |TRUE| when autocommands are being executed and the - FileType event has been triggered at least once. Can be used - to avoid triggering the FileType event again in the scripts - that detect the file type. |FileType| + FileType event triggered at least once for a buffer with + a non-empty 'filetype'. Can be used to avoid triggering + the FileType event again in the |ftdetect| scripts. |FileType| Returns |FALSE| when `:setf FALLBACK` was used. + When editing another file, the counter is reset, thus this really checks if the FileType event has been triggered for the current buffer. This allows an autocommand that starts diff --git a/test/functional/autocmd/filetype_spec.lua b/test/functional/autocmd/filetype_spec.lua index 4841377946..1914477329 100644 --- a/test/functional/autocmd/filetype_spec.lua +++ b/test/functional/autocmd/filetype_spec.lua @@ -16,4 +16,17 @@ describe('autocmd FileType', function() command('help help') t.eq(1, eval('g:foo')) end) + + it("empty 'filetype' does not prevent FileType event #41711", function() + local file = t.tmpname(false) .. '.md' + t.write_file(file, '# hi\n') + command('filetype on') + -- Like vim.lsp.enable() lazy-loaded while the buffer is being read. + command('autocmd FileType * :') + command('autocmd BufReadPre * ++once doautoall FileType') + -- Run :edit in a nested event (mimics :restart session-restore). + command(('autocmd User X ++nested edit %s'):format(vim.fn.fnameescape(file))) + command('doautocmd User X') + t.eq('markdown', eval('&filetype')) + end) end)