stevearc / oil.nvim

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

bug: Sometimes opening files when using `mkview` and `loadview` get messed up #245

Closed mehalter closed 10 months ago

mehalter commented 10 months ago

Did you check the docs and existing issues?

Neovim version (nvim -v)

0.9.4 release

Operating system/version

Arch Linux

Describe the bug

When using the core view features in Neovim for saving folds, cursor position, etc. it seems get get messed up when using Oil. Using a simple example pulled directly from the Neovim docs with :h loadview to automatically save and load views when opening C files we can get some bad behavior.

When reaching a certain level of nested directories (4 nested directories) and then opening a file that automatically loads a view, the filetype gets messed up. It seems that when Oil is opening a file it's not simply loading it into a buffer like what would happen if you run :e <some_file> so I'm not sure how to further debug or diagnose this problem.

Basically when doing loadview on the recommended autocommand events it seems that the filetype is being set to oil rather than the normal filetype. If we disable the loadview part of the autocommands and just run it manually when the file is loaded with :loadview, it seems to work fine. So the view that is being created is not wrong, but the way files are loaded really interfere with this core functionality.

Funny enough this behavior is not always the case. It seems to happen 100% of the time if I open up Oil and then navigate into 4 children directories and open a file.

Steps To Reproduce

  1. rm -rf .repro, make sure a completely clean install
  2. mkdir -p nested/nested2/nested3/nested4/test.c, create directory structure
  3. nvim -u repro.lua, load neovim with our repro and let the plugins install
  4. :Oil, open oil and then navigate into our nested folders to get all the way to open test.c
  5. :set filetype, check the filetype and see filetype=c. This is because it's the first time so no view was loaded, but when we leave the current view will be saved
  6. :q, quit the editor
  7. nvim -u repro.lua, load neovim and navigate back all the way down to test.c
  8. :set filetype, check the filetype and see filetype=oil

For further testing you can also go into the repro.lua you can follow these steps after the first:

  1. Edit repro.lua and comment out the line au BufWinEnter *.c silent! loadview to disable the automatic loading of views but not remove the automatic saving of views
  2. nvim -u repro.lua, load neovim and navigate to the test.c file
  3. :loadview, load the view manually after the file is opened
  4. :set filetype, see that filetype=c correctly, so the view that is being saved is not being messed up at all, it seems to be something about how the file is being loaded. seemingly in a non-traditional vim way.

Expected Behavior

I would expect that the usage of core vim/neovim features such as mkview and loadview should play nicely with my file browser especially when it's extremely useful when it comes to saving folds, cursor position, local variables, etc.

Directory structure

nested/nested2/nested3/nested4/test.c

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 = {
  {
    "stevearc/oil.nvim",
    config = function()
      require("oil").setup({
        -- add any needed settings here
      })
    end,
  },
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

-- set `viewdir` to not conflict with system viewdir
vim.opt.viewdir = vim.env["XDG_STATE_HOME"] .. "/nvim/view/"

-- Automatically save and load views for *.c files
-- Used to save foldes, cursor position, etc.
-- snippet directly from Neovim docs: `:h loadview`
vim.cmd([[
  au BufWinLeave *.c mkview
  au BufWinEnter *.c silent! loadview
]])

Did you check the bug with a clean config?

mehalter commented 10 months ago

Oh man, I just spent a few hours and finally was able to find where this is messing up! It has to do with at the end of loading a view neovim calls: doautoall SessionLoadPost which triggers this block even in a non-oil buffer and it goes in and messes up stuff:

https://github.com/stevearc/oil.nvim/blob/master/lua/oil/init.lua#L1126-L1140

If I comment out this block it works perfectly.

Going to keep investigating to see if I can make a PR to fix this!

mehalter commented 10 months ago

Ok, I have continued testing of this and it looks like it is only running the load_oil_buffer on oil buffer numbers, but I believe it is a problem with the fact that none of the buffers are loaded to a window. I don't fully understand the codebase so I also am not sure why it only happens when I have opened a sufficient number of oil buffers (i.e. gone into a sufficient number of nested folders). I'm not sure if I'll be able to make a PR to resolve this just because of my naivety of how this codebase works, but I hope this investigation/deep dive into the problem can help guide someone to the solution!