stevearc / oil.nvim

Neovim file explorer: edit your filesystem like a buffer
MIT License
3.4k stars 92 forks source link

bug: `BufReadPost` autocommands swallow output #348

Closed nathanmsmith closed 2 months ago

nathanmsmith commented 3 months ago

Did you check the docs and existing issues?

Neovim version (nvim -v)

0.9.5

Operating system/version

macOS 14.4

Describe the bug

BufReadPost autocommands are not executed for files/buffers opened from oil.nvim. This may affect other autocommand events, I just haven't tested on them.

What is the severity of this bug?

breaking (some functionality is broken)

Steps To Reproduce

In a directory with some files, edit some using :e and others via oil.nvim. Note that oil.nvim does not trigger the BufReadPost autocommand.

https://github.com/stevearc/oil.nvim/assets/5677971/3fc85b3a-770e-4c97-961c-fde384910a32

Expected Behavior

Autocmd should print (or do whatever defined behavior there is)

Directory structure

repro-dir/file{1,2,3}.txt

Repro

-- save as repro.lua
-- run with nvim -u repro.lua
-- DO NOT change the paths
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "runtime", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "--single-branch",
    "https://github.com/folke/lazy.nvim.git",
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
  "folke/tokyonight.nvim",
  {
        "stevearc/oil.nvim",
        config = function()
            require("oil").setup({
              -- add any needed settings here
            })
        end,
  },
  -- add any other plugins here
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here

vim.api.nvim_create_autocmd({ "BufReadPost" }, {
  pattern = "*",
  group = vim.api.nvim_create_augroup("buf_read_test", {}),
  callback = function()
    print("bufreadpost on " .. vim.fn.expand("%"))
  end,
})

Did you check the bug with a clean config?

stevearc commented 2 months ago

This is actually a more subtle bug. The autocmd is fired, but the output is swallowed. You can see this for yourself if you use this:

vim.api.nvim_create_autocmd({ "BufReadPost" }, {
  pattern = "*",
  group = vim.api.nvim_create_augroup("buf_read_test", {}),
  callback = function()
    -- Assuming you have conform.nvim installed, I just needed some easy way
    -- to write to a file.
    require("conform.log").debug("bufreadpost on %s", vim.fn.expand("%"))
  end,
})

I have seen this before and I'm not sure why it happens. It's probably some conflict between the async nature of the oil operations and how neovim captures the output from lua.

nathanmsmith commented 2 months ago

Interesting! My motivation for wanting a BufReadPost autocommand is to call projectionist#append on certain files in a project. Currently it's spotty with oil.nvim so totally makes sense that there's a race condition somewhere.

stevearc commented 2 months ago

Nevermind, it was actually introduced in my fix for #188. I added emsg_silent to the edit commands to suppress the stacktrace from a swapfile error. That has some other negative effects like suppressing all output for the duration of the edit command (including any triggered autocmds). I'm targeting that more specifically now with a pcall and checking the error type.