folke / lazy.nvim

💤 A modern plugin manager for Neovim
https://lazy.folke.io/
Apache License 2.0
14.6k stars 353 forks source link

bug: The buffer is wiped out and thus invalid when the autocommand for nvim-tree is registered first. #1192

Closed Fau818 closed 9 months ago

Fau818 commented 11 months ago

Did you check docs and existing issues?

Neovim version (nvim -v)

NVIM v0.9.4

Operating system/version

MacOS14.1.1 (23B81)

Describe the bug

I received an error message when attempting to open a directory using neovim.

After troubleshooting, I narrowed down the issue to an autocmd of nvim-tree.

Steps To Reproduce

  1. Ensure using the following minimal init.lua file.
  2. Use the nvim command on a directory, an error message will arise.

Expected Behavior

No error message.

Repro

-- -----------------------------------
-- -------- Autocmd
-- -----------------------------------
local function open_nvim_tree(data)
  local directory = vim.fn.isdirectory(data.file) == 1
  if not directory then return end

  vim.cmd.enew()
  vim.cmd.bw(data.buf)
  vim.cmd.cd(data.file)
  require("nvim-tree.api").tree.open()
end

vim.api.nvim_create_autocmd("VimEnter", {
  desc = "Open nvim-tree when open a directory.",
  pattern = "*",
  callback = open_nvim_tree
})

-- -----------------------------------
-- -------- Lazy
-- -----------------------------------
-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "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", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
  "folke/tokyonight.nvim",

  {
    "goolord/alpha-nvim",
    config = function() require'alpha'.setup(require'alpha.themes.startify'.config) end,
    event = "VimEnter",
  },
  -- add any other plugins here
  {
    "nvim-tree/nvim-tree.lua",
    config = true,
    event = "VeryLazy",
    lazy = true,
  }
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")

-- add anything else here
Fau818 commented 11 months ago

error message

...repro/plugins/lazy.nvim/lua/lazy/core/handler/event.lua:157: Invalid buffer id: 1
dpetka2001 commented 11 months ago

Taken from the Lazyvim website for neo-tree, could you try adding the following in the nvim-tree spec

init = function()
    if vim.fn.argc(-1) == 1 then
      local stat = vim.loop.fs_stat(vim.fn.argv(0))
      if stat and stat.type == "directory" then
        require("nvim-tree")
      end
    end
  end,

and see if that works for you?

Fau818 commented 11 months ago

Taken from the Lazyvim website for neo-tree, could you try adding the following in the nvim-tree spec

init = function()
    if vim.fn.argc(-1) == 1 then
      local stat = vim.loop.fs_stat(vim.fn.argv(0))
      if stat and stat.type == "directory" then
        require("nvim-tree")
      end
    end
  end,

and see if that works for you?

Thanks for your help, but it doesn't work well for me.

Although this function is guaranteed to open nvim-tree, it does not realize the window layout in autocmd; it opened the file tree in full screen.

abeldekat commented 11 months ago

Although this function is guaranteed to open nvim-tree, it does not realize the window layout in autocmd; it opened the file tree in full screen.

How to open in that window layout is an nvim-tree specific question in my opinion.

Using your code, nvim-tree also opens full screen without lazy.nvim:

-- -----------------------------------
-- -------- Autocmd
-- -----------------------------------
local function open_nvim_tree(data)
  local directory = vim.fn.isdirectory(data.file) == 1
  if not directory then
    return
  end

  vim.cmd.enew()
  vim.cmd.bw(data.buf)
  vim.cmd.cd(data.file)
  require("nvim-tree.api").tree.open()
end

vim.api.nvim_create_autocmd("VimEnter", {
  desc = "Open nvim-tree when open a directory.",
  pattern = "*",
  callback = open_nvim_tree,
})

-- clean after testing: rm -rf pack .repro
local root = vim.fn.fnamemodify("./.repro", ":p")

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

local plugins = {
  { "nvim-web-devicons", "https://github.com/nvim-tree/nvim-web-devicons.git" },
  { "nvimtree.lua", "https://github.com/nvim-tree/nvim-tree.lua.git" },
}

local packpath = root .. "/../pack/plugins/opt"
if not vim.loop.fs_stat(packpath) then
  vim.fn.system({ "mkdir", packpath })
end

for _, plugin in pairs(plugins) do
  local pluginpath = packpath .. "/" .. plugin[1]
  if not vim.loop.fs_stat(pluginpath) then
    vim.fn.system({ "git", "clone", "--filter=blob:none", plugin[2], pluginpath })
  end
end

for _, plugin in pairs(plugins) do
  vim.cmd("packadd " .. plugin[1])
end

vim.cmd.colorscheme("habamax")
require("nvim-tree").setup()
Fau818 commented 11 months ago

@abeldekat Sorry for the late reply.

I would like to describe the reproduction conditions of this error: The presence of the alpha-nvim plugin is required. At this time, when I open a directory using nvim, it seems like lazy.nvim accessed a invalid buffer.

image

I cannot be completely sure whether the issue should be solved by lazy.nvim. And the autocmd come from this nvim-tree wiki page.

So could you please consider including the alpha-nvim plugin and then take a look at this issue?

dpetka2001 commented 11 months ago

Can you try removing vim.cmd.bw(data.buf) from the function? Does this achieve what you want?

abeldekat commented 11 months ago

So could you please consider including the alpha-nvim plugin and then take a look at this issue?

Thanks @Fau818! You're right. It works as intended without using lazy.nvim. Could you check the repro below?


-- load nvim-tree
vim.api.nvim_create_autocmd("VimEnter", {
  desc = "Open nvim-tree when open a directory.",
  pattern = "*",
  callback = function(data)
    vim.cmd("packadd nvimtree.lua")
    require("nvim-tree").setup()

    if vim.fn.isdirectory(data.file) == 1 then
      -- vim.cmd.enew() -- not needed
      vim.cmd.bw(data.buf) -- "really delete a buffer"
      vim.cmd.cd(data.file)
      require("nvim-tree.api").tree.open()
    end
  end,
})

-- load alpha
vim.api.nvim_create_autocmd("VimEnter", {
  desc = "Open nvim-tree when open a directory.",
  pattern = "*",
  callback = function()
    vim.cmd("packadd alpha-nvim")
    require("alpha").setup(require("alpha.themes.startify").config)
  end,
})

local root = vim.fn.fnamemodify("./.repro", ":p")
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

local packdir = root .. "/data/site/pack/plugins/opt"
if not vim.loop.fs_stat(packdir) then
  vim.fn.system({ "mkdir", packdir })
end
vim.opt.packpath:prepend(root .. "/data/site/")

local plugins = {
  { "nvim-web-devicons", "https://github.com/nvim-tree/nvim-web-devicons.git" },
  { "nvimtree.lua", "https://github.com/nvim-tree/nvim-tree.lua.git" },
  { "alpha-nvim", "https://github.com/goolord/alpha-nvim" },
}

for _, plugin in pairs(plugins) do
  local pluginpath = packdir .. "/" .. plugin[1]
  if not vim.loop.fs_stat(pluginpath) then
    vim.fn.system({ "git", "clone", "--filter=blob:none", plugin[2], pluginpath })
  end
end

vim.cmd("packadd " .. "nvim-web-devicons")
vim.cmd.colorscheme("habamax")
Fau818 commented 11 months ago

Can you try removing vim.cmd.bw(data.buf) from the function? Does this achieve what you want?

If I remove it, there will be a buffer that cannot be closed.

image
dpetka2001 commented 11 months ago

If you change it to vim.cmd.bd(data.buf)?

Fau818 commented 11 months ago

@abeldekat I tested your code, it works for me.

Fau818 commented 11 months ago

vim.cmd.bd(data.buf)

Thank you for your help, the error did not occur again, and the issue has been resolved.

abeldekat commented 11 months ago

Interesting. When the nvim-tree autocommand is last, it works.

local root = vim.fn.fnamemodify("./.repro", ":p")
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath })
end
vim.opt.runtimepath:prepend(lazypath)

local plugins = {
  "folke/tokyonight.nvim",
  {
    "goolord/alpha-nvim",
    event = "VimEnter",
    config = function()
      require("alpha").setup(require("alpha.themes.startify").config)
    end,
  },
  {
    "nvim-tree/nvim-tree.lua",
    config = true,
    event = "VeryLazy",
  },
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})
vim.cmd.colorscheme("tokyonight")

vim.api.nvim_create_autocmd("VimEnter", {
  desc = "Open nvim-tree when open a directory.",
  pattern = "*",
  callback = function(data)
    if vim.fn.isdirectory(data.file) == 1 then
      vim.cmd.enew()
      vim.cmd.bw(data.buf)
      vim.cmd.cd(data.file)
      require("nvim-tree.api").tree.open()
    end
  end,
})
Fau818 commented 11 months ago

@abeldekat Yes, you are right. When autocmd is later than require("lazy").setup(), the error no longer occurs.

dpetka2001 commented 11 months ago

I'm guessing that happens because alpha has already been loaded in VimEnter and then the autocmd wipes out the buffer. From seeing the code in handler.event.lua line 157 it seems that lazy.nvim expects a buffer = opts.buffer to execute the events. Since that was deleted by vim.cmd.bw it cannot find the buffer to execute the alpha spec on VimEnter event. That's just a guess, since I cannot completely understand the code. Just in a very simplified manner as my brain tries to process this.

Edit: bdelete doesn't wipe out all the necessary info related to a buffer. It just lists it as unlisted. bwipe wipes out all related info about a buffer. I'm guessing that's why bdelete works if the autocmd is before require.

abeldekat commented 11 months ago

Given the different behavior of bd versus bw, I think it's best to not close this issue. Folke can decide if changes to the event handling mechanism are appropriate.

abeldekat commented 11 months ago

Adding another observation into the mix: Replace alpha with dashboard, and the code also works as intended...

local root = vim.fn.fnamemodify("./.repro", ":p")
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath })
end
vim.opt.runtimepath:prepend(lazypath)

vim.api.nvim_create_autocmd("VimEnter", {
  desc = "Open nvim-tree when open a directory.",
  pattern = "*",
  callback = function(data)
    if vim.fn.isdirectory(data.file) == 1 then
      vim.cmd.enew()
      vim.cmd.bw(data.buf)
      vim.cmd.cd(data.file)
      require("nvim-tree.api").tree.open()
    end
  end,
})
local plugins = {
  "folke/tokyonight.nvim",
  { --> replacing alpha with dashboard also solves the problem
    "nvimdev/dashboard-nvim",
    event = "VimEnter",
    opts = {
      theme = "doom",
    },
  },
  {
    "nvim-tree/nvim-tree.lua",
    config = true,
    event = "VeryLazy",
  },
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})
vim.cmd.colorscheme("tokyonight")
abeldekat commented 11 months ago

I tried to understand the difference between alpha and dashboard.

The alpha plugin registers an autocommand on VimEnter. The dashboard plugin works because it does not.

As lazy.nvim is configured to load the alpha plugin on VimEnter, the VimEnter autocommand registered by the newly loaded alpha plugin needs to be triggered

The use case of this issue: The buffer is wiped out and thus invalid when the autocommand for nvim-tree is registered first.

Fau818 commented 11 months ago

Okay, I've revised the title of the issue. Thank you for your efforts! @abeldekat