nvim-neo-tree / neo-tree.nvim

Neovim plugin to manage the file system and other tree like structures.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

BUG: Toggling neotree and then closing a buffer expands neotree

beastr45 opened this issue · comments

commented

Did you check docs and existing issues?

  • I have read all the docs.
  • I have searched the existing issues.
  • I have searched the existing discussions.

Neovim Version (nvim -v)

0.10.0 (latest)

Operating System / Version

Linux 6.6.34-1-lts x86_64 GNU/Linux

Describe the Bug

When dealing with multiple buffers neotree will no longer become split view after closing a buffer. This is really annoying because in large co-debases I cant read code and navigate at the same time when this happens. I often just reopen neovim to fix it.

Screenshots, Traceback

expected behaviour
image
behaviour after closing one buffer out of multiple open (toggling neotree takes up entire screen)
image

Steps to Reproduce

  1. open more than one buffer
  2. toggle neotree
  3. focus the buffer while neotree is open and type :bw
  4. neotree now takes up entire screen, toggling neotree is no longer in split view
  5. in order to refresh split screen neotree has to open a file in its buffer.

Expected Behavior

Neotree should always stay in split windows unless directed to do otherwise by the user in the config.

(the minimal config already provided reproduces my issue)

Your Configuration

-- 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",
  -- add any other plugins here
}

local neotree_config = {
  "nvim-neo-tree/neo-tree.nvim",
  dependencies = { "MunifTanjim/nui.nvim", "nvim-tree/nvim-web-devicons", "nvim-lua/plenary.nvim" },
  cmd = { "Neotree" },
  keys = {
    { "<Leader>e", "<Cmd>Neotree<CR>" }, -- change or remove this line if relevant.
  },
  opts = {
    -- Your config here
    -- ...
  },
}

table.insert(plugins, neotree_config)
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

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

I'm having the same problem.

I've checked if LazyVim, which uses neo-tree by default. Guess what, it doesn't happen.

I don't really know why. https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/editor.lua#L4-L127

Hi @vricop,

the reason why neo-tree does not expand to full screen size after deleting a buffer in LazyVim is not the neo-tree configuration, but rather the way LazyVim deletes a buffer.
I copied the whole utility function from LazyVim over to my config and passed the bufremove function to my keymap:

util/ui.lua:

local M = {}

--- This function is taken directly from [LazyVim's UI utils](https://github.com/LazyVim/LazyVim/blob/a1c3ec4cd43fe61e3b614237a46ac92771191c81/lua/lazyvim/util/ui.lua#L228).
--- Besides some other nice features, this primarily prevents neo-tree from
--- taking up the whole screen after deleting a buffer.
--- (Thank you folke)
---@param buf number?
function M.bufremove(buf)
  buf = buf or 0
  buf = buf == 0 and vim.api.nvim_get_current_buf() or buf

  if vim.bo.modified then
    local choice = vim.fn.confirm(("Save changes to %q?"):format(vim.fn.bufname()), "&Yes\n&No\n&Cancel")
    if choice == 0 or choice == 3 then -- 0 for <Esc>/<C-c> and 3 for Cancel
      return
    end
    if choice == 1 then -- Yes
      vim.cmd.write()
    end
  end

  for _, win in ipairs(vim.fn.win_findbuf(buf)) do
    vim.api.nvim_win_call(win, function()
      if not vim.api.nvim_win_is_valid(win) or vim.api.nvim_win_get_buf(win) ~= buf then
        return
      end
      -- Try using alternate buffer
      local alt = vim.fn.bufnr("#")
      if alt ~= buf and vim.fn.buflisted(alt) == 1 then
        vim.api.nvim_win_set_buf(win, alt)
        return
      end

      -- Try using previous buffer
      local has_previous = pcall(vim.cmd, "bprevious")
      if has_previous and buf ~= vim.api.nvim_win_get_buf(win) then
        return
      end

      -- Create new listed buffer
      local new_buf = vim.api.nvim_create_buf(true, false)
      vim.api.nvim_win_set_buf(win, new_buf)
    end)
  end
  if vim.api.nvim_buf_is_valid(buf) then
    pcall(vim.cmd, "bdelete! " .. buf)
  end
end

return M

config/keymaps.lua:

local ui = require("util.ui")

// ...

map("n", "<leader>bd", ui.bufremove, { desc = "Delete buffer" })

Works great for me. Plus, i get the fancy "Save changes" dialog for free :)

All credits go to @folke – Thank you!

Best regards
Stefan

I have the same problem. I also find that doing a simple :bd command with the neo-tree plugin open and other files open closes nvim completely if I have the close_if_last_window setting to true.

I have the same problem. I also find that doing a simple :bd command with the neo-tree plugin open and other files open closes nvim completely if I have the close_if_last_window setting to true.

Hi @JohnWilliston,
I would assume that's exactly how neo-tree should behave if close_if_last_window is true.
Besides that, maybe you want to checkout my comment above, which describes how to prevent neo-tree from taking up whole screen space when closing a buffer.
Hope this helps.

Best regards
Stefan

I have the same problem. I also find that doing a simple :bd command with the neo-tree plugin open and other files open closes nvim completely if I have the close_if_last_window setting to true.

Hi @JohnWilliston, I would assume that's exactly how neo-tree should behave if close_if_last_window is true. Besides that, maybe you want to checkout my comment above, which describes how to prevent neo-tree from taking up whole screen space when closing a buffer. Hope this helps.

Best regards Stefan

Well perhaps I misunderstand. I tend to toggle neo-tree open with a keyboard shortcut (F3 from my old CUA days is a hard habit to break). Here's the procedure I follow to evince what seems to me like a bug:

  1. Open nvim with a single file specified on the command line.
  2. Hit F3 to toggle neo-tree (it appears in a new left pane). Open a second file using neo-tree.
  3. Issue the :bd command.

With two files open like that, I would think deleting the buffer that's open in the right pane would leave neo-tree open on the left and the original file from the command line open on the right. What actually happens with close_if_last_window set to true is that nvim exits completely. And I believe it's neo-tree doing that for two reasons: (1) changing close_if_last_window to false stops it from happening, as does (2) if I toggle the neo-tree pane closed before the :bd command. Serious question: am I wrong in that initial expectation?

I'd happy just change that close_if_last_window setting, but it was giving me fits when neo-tree was the last thing open. For what it's worth, I managed to get your workaround installed, configured, and functioning for me. I just doubt after decades of using :bd to close a buffer that I'm ever going to be able to retrain myself to hit <space>bd instead.

[...]
With two files open like that, I would think deleting the buffer that's open in the right pane would leave neo-tree open on the left and the original file from the command line open on the right. What actually happens with close_if_last_window set to true is that nvim exits completely. And I believe it's neo-tree doing that for two reasons: (1) changing close_if_last_window to false stops it from happening, as does (2) if I toggle the neo-tree pane closed before the :bd command. Serious question: am I wrong in that initial expectation?

This actually sound like a bug. I assumed, you mean that neovim would exit completely after closing the last buffer (and also with neo-tree still open).
However, this sounds like a completely different issue. I'd recommend creating a separate issue for that.

Also, I think this issue here can be closed now. A pane taking up the whole screen space after closing another one possibly is default neovim behaviour and not a bug. It can be worked around with the bufremove utility function from folke's LazyVim.

commented

[...]
With two files open like that, I would think deleting the buffer that's open in the right pane would leave neo-tree open on the left and the original file from the command line open on the right. What actually happens with close_if_last_window set to true is that nvim exits completely. And I believe it's neo-tree doing that for two reasons: (1) changing close_if_last_window to false stops it from happening, as does (2) if I toggle the neo-tree pane closed before the :bd command. Serious question: am I wrong in that initial expectation?

This actually sound like a bug. I assumed, you mean that neovim would exit completely after closing the last buffer (and also with neo-tree still open). However, this sounds like a completely different issue. I'd recommend creating a separate issue for that.

Also, I think this issue here can be closed now. A pane taking up the whole screen space after closing another one possibly is default neovim behaviour and not a bug. It can be worked around with the bufremove utility function from folke's LazyVim.

Perhaps it may be a good idea to make a pr describing this to the readme documentation or add the utility function to the plugin itself allowing the option to toggle the workaround in the config.

Hi @vricop,

the reason why neo-tree does not expand to full screen size after deleting a buffer in LazyVim is not the neo-tree configuration, but rather the way LazyVim deletes a buffer. I copied the whole utility function from LazyVim over to my config and passed the bufremove function to my keymap:

util/ui.lua:

local M = {}

--- This function is taken directly from [LazyVim's UI utils](https://github.com/LazyVim/LazyVim/blob/a1c3ec4cd43fe61e3b614237a46ac92771191c81/lua/lazyvim/util/ui.lua#L228).
--- Besides some other nice features, this primarily prevents neo-tree from
--- taking up the whole screen after deleting a buffer.
--- (Thank you folke)
---@param buf number?
function M.bufremove(buf)
  buf = buf or 0
  buf = buf == 0 and vim.api.nvim_get_current_buf() or buf

  if vim.bo.modified then
    local choice = vim.fn.confirm(("Save changes to %q?"):format(vim.fn.bufname()), "&Yes\n&No\n&Cancel")
    if choice == 0 or choice == 3 then -- 0 for <Esc>/<C-c> and 3 for Cancel
      return
    end
    if choice == 1 then -- Yes
      vim.cmd.write()
    end
  end

  for _, win in ipairs(vim.fn.win_findbuf(buf)) do
    vim.api.nvim_win_call(win, function()
      if not vim.api.nvim_win_is_valid(win) or vim.api.nvim_win_get_buf(win) ~= buf then
        return
      end
      -- Try using alternate buffer
      local alt = vim.fn.bufnr("#")
      if alt ~= buf and vim.fn.buflisted(alt) == 1 then
        vim.api.nvim_win_set_buf(win, alt)
        return
      end

      -- Try using previous buffer
      local has_previous = pcall(vim.cmd, "bprevious")
      if has_previous and buf ~= vim.api.nvim_win_get_buf(win) then
        return
      end

      -- Create new listed buffer
      local new_buf = vim.api.nvim_create_buf(true, false)
      vim.api.nvim_win_set_buf(win, new_buf)
    end)
  end
  if vim.api.nvim_buf_is_valid(buf) then
    pcall(vim.cmd, "bdelete! " .. buf)
  end
end

return M

config/keymaps.lua:

local ui = require("util.ui")

// ...

map("n", "<leader>bd", ui.bufremove, { desc = "Delete buffer" })

Works great for me. Plus, i get the fancy "Save changes" dialog for free :)

All credits go to @folke – Thank you!

Best regards Stefan

I know, that’s exactly what I did after commenting it was working in LazyVim. I forgot to mention it here.

Here’s mine: https://github.com/vricop/.dotfiles/blob/main/nvim/lua/utils/ui.lua

You can find a lot of useful mappings and tricks in @folke repo. I’m always taking this kind of things from him.

Perhaps it may be a good idea to make a pr describing this to the readme documentation or add the utility function to the plugin itself allowing the option to toggle the workaround in the config.

Good point.

in my keymaps.lua I had to do this:

local ui = require("util.ui")
vim.keymap.set("n", "<leader>bd", ui.bufremove, { desc = "Delete Buffer (without breaking neotree)" })

using vim.keymap.set rather than map.

And since I changed the desc I could confirm that the change worked using which-key.

Also, @vricop creates ~/.config/nvim/lua/utils/ui.lua when @stefanpartheym creates ~/.config/nvim/lua/util.lua, using util rather than utils, which tripped me up.

I also have this issue when closing a window.

  1. open file
  2. open neotree (space-e)
  3. switch to window with file (ctrl-l)
  4. quit window with file (:q)
  5. neotree is now taking up the whole screen
  6. close neotree (space-e)
  7. my previously closed file is now back
  8. open neotree (space-e)
  9. neotree is now taking up the whole screen when it should only have taken a small portion

I can't pretend to understand that Lua code, is there some equivalent to this when closing a window?