fix(dir): let 3P dir-browser plugin rename the dir buffer #40529

Problem:
`FileType directory` fires *before* the `BufEnter` path where `dir.lua`
populates the buffer, in order to allow a 3P dir-browser plugin to handle the
event and (optionally) rename the buffer to e.g. `example:///tmp/foo/`.

But currently, `open_buffer()` continues after `filetypedetect BufRead` as if
the original directory buffer is *still* current and valid, which may fall
through to the built-in `nvim.dir` path after a 3P plugin ALREADY handled the
directory.

Solution:
Keep a buf ref around the early `filetypedetect BufRead` call for directory
buffers.

If the `FileType directory` handler switches away from/deletes the original
directory buffer, stop the open path instead of continuing into the built-in
`nvim.dir` flow.
This commit is contained in:
Barrett Ruth
2026-07-13 14:10:19 -05:00
committed by GitHub
parent 4d736cd41f
commit 73bb6a8a5e
2 changed files with 35 additions and 0 deletions

View File

@@ -413,7 +413,12 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
&& after_pathsep(curbuf->b_ffname,
curbuf->b_ffname + strlen(curbuf->b_ffname))) {
if (augroup_exists("filetypedetect")) {
bufref_T bufref;
set_bufref(&bufref, curbuf);
do_doautocmd("filetypedetect BufRead", false, NULL);
if (!bufref_valid(&bufref) || curbuf != old_curbuf.br_buf || aborting()) {
return FAIL;
}
}
}

View File

@@ -105,6 +105,36 @@ describe('nvim.dir', function()
line_of('alpha.txt')
end)
it('3P dir-browser can handle `FileType directory` event and rename buf', function()
make_fixture()
n.clear({ args_rm = { '-u' } })
exec_lua(function()
_G.nvim_dir_loaded_in_filetype = nil
vim.api.nvim_create_autocmd('FileType', {
pattern = 'directory',
callback = function(ev)
_G.nvim_dir_loaded_in_filetype = package.loaded['nvim.dir'] ~= nil
local dir = vim.api.nvim_buf_get_name(ev.buf)
local browser = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(browser, 'example://' .. dir)
vim.api.nvim_buf_set_lines(browser, 0, -1, false, {
'plugin browser for: ' .. dir,
})
vim.api.nvim_set_current_buf(browser)
vim.api.nvim_buf_delete(ev.buf, { force = true })
end,
})
end)
edit(root)
eq(false, exec_lua('return _G.nvim_dir_loaded_in_filetype'))
eq('example://' .. root .. '/', api.nvim_buf_get_name(0))
eq({ 'plugin browser for: ' .. root .. '/' }, lines())
eq(false, exec_lua([[return package.loaded['nvim.dir'] ~= nil]]))
eq('', exec_capture('messages'))
end)
it('triggers nested autocmds when opening directory buffers', function()
make_fixture()