romgrk / barbar.nvim

The neovim tabline plugin.
2.26k stars 85 forks source link

Closing buffers very quicky causes consistent UI glitch for barbar.nvim #550

Closed thunder-coding closed 5 months ago

thunder-coding commented 8 months ago

Description

Closing tabs too quickly causes race conditions in barbar.lua

To Reproduce

init.lua:

local lazypath = vim.fn.stdpath("data") .. "/lazy/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",
    "--branch=stable", -- latest stable release
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

require("lazy").setup({
  {
  "romgrk/barbar.nvim",
    dependencies = {
      "lewis6991/gitsigns.nvim",
      "nvim-tree/nvim-web-devicons",
    },
  },
})

vim.keymap.set({ "n", "i", "t" }, "<A-w>", "<Cmd>BufferClose<CR>", { silent = true })

Steps to reproduce the behavior:

  1. Use the above NeoVim configuration
  2. Change your respective DE's keyboard configuration and reduce repeat delay and increase repeat rate. I could reproduce the behaviour with 100ms delay and 20 repeat/s. This seems to be some sort of race condition which is being triggerred.
  3. Disabling animations by using the following config reduces the probability of triggering the race condition but doesn't entirely fixes it:
    require("lazy").setup({
    {
    "romgrk/barbar.nvim",
    dependencies = {
      "lewis6991/gitsigns.nvim",
      "nvim-tree/nvim-web-devicons",
    },
    init = function()
      vim.g.barbar_auto_setup = false
    end,
    opts = {                                                                
      animation = false,
    },
    },
    })
  4. open a bunch of files and hold Alt+w (note: you might have to follow step 2 if not reproducible on your end)
  5. after the bug if you open another file, it opens in a new buffer, and there is only 1 tab

Screenshots

Demo 1 Demo 2 Demo 3

Informations

nvim --version:

NVIM v0.9.5
Build type: Release
LuaJIT 2.1.1702233742

:checkhealth output:

──────────────────────────────────────────────────────────────────────────────
lazy: require("lazy.health").check()

lazy.nvim
- OK Git installed
- OK no existing packages found by other package managers
- OK packer_compiled.lua not found

──────────────────────────────────────────────────────────────────────────────
nvim: require("nvim.health").check()

Configuration
- OK no issues found

Runtime
- OK $VIMRUNTIME: /usr/share/nvim/runtime

Performance
- OK Build type: Release

Remote Plugins
- OK Up to date

terminal
- key_backspace (kbs) terminfo entry: key_backspace=\177
- key_dc (kdch1) terminfo entry: key_dc=\E[3~
- $COLORTERM="truecolor"

──────────────────────────────────────────────────────────────────────────────
provider: health#provider#check

Clipboard (optional)
- OK Clipboard tool found: xclip

Python 3 provider (optional)
- g:python3_host_prog is not set.  Searching for python3 in the environment.
- Multiple python3 executables found.  Set g:python3_host_prog to avoid surprises.
- Executable: /sbin/python3
- Other python executable: /bin/python3
- Other python executable: /usr/bin/python3
- Other python executable: /usr/sbin/python3
- Python version: 3.11.6
- pynvim version: 0.5.0
- OK Latest pynvim is installed.

Python virtualenv
- OK no $VIRTUAL_ENV

Ruby provider (optional)
- Ruby: ruby 3.0.6p216 (2023-03-30 revision 23a532679b) [x86_64-linux]
- WARNING neovim-ruby-host not found.
  - ADVICE:
    - Run gem install neovim to ensure the neovim RubyGem is installed.
    - Run gem environment to ensure the gem bin directory is in $PATH.
    - If you are using rvm/rbenv/chruby, try "rehashing".
    - See :help g:ruby_host_prog for non-standard gem installations.
    - You may disable this provider (and warning) by adding let g:loaded_ruby_provider = 0 to your init.vim

Node.js provider (optional)
- Node.js: v21.6.1
- WARNING Missing "neovim" npm (or yarn, pnpm) package.
  - ADVICE:
    - Run in shell: npm install -g neovim
    - Run in shell (if you use yarn): yarn global add neovim
    - Run in shell (if you use pnpm): pnpm install -g neovim
    - You may disable this provider (and warning) by adding let g:loaded_node_provider = 0 to your init.vim

Perl provider (optional)
- WARNING "Neovim::Ext" cpan module is not installed
  - ADVICE:
    - See :help provider-perl for more information.
    - You may disable this provider (and warning) by adding let g:loaded_perl_provider = 0 to your init.vim

──────────────────────────────────────────────────────────────────────────────
vim.lsp: require("vim.lsp.health").check()

- LSP log level : WARN
- Log path: /home/testuser/.local/state/nvim/lsp.log
- Log size: 0 KB

vim.lsp: Active Clients
- No active clients

──────────────────────────────────────────────────────────────────────────────
vim.treesitter: require("vim.treesitter.health").check()

- Nvim runtime ABI version: 14

OS: Arch Linux (all packages up to date)

Iron-E commented 7 months ago

I haven't looked into this yet, but perhaps I can suggest alternative workflows in the meantime:

These commands should not exhibit this behavior.

Iron-E commented 7 months ago

Minimal repro: nvim -u minimal.lua a b c d -S script.lua

minimal.lua

vim.opt.rtp:append '~/.local/share/nvim/lazy/barbar.nvim'
require'barbar'.setup { icons = { filetype = { enabled = false } } }

script.lua

for i = 1, 100 do vim.cmd.BufferClose() end
romgrk commented 5 months ago

I reverted the fix, the approach was adding too much complexity. I'll fix in a follow-up PR.

romgrk commented 5 months ago

I've opened #573 to fix the underlying issue, I'll run with it in my config for a day before merging.

Iron-E commented 5 months ago

I reverted the fix, the approach was adding too much complexity. I'll fix in a follow-up PR.

Can you speak more as to what the previous approach was preventing? If the vim.loop strategy was unreliable it'll be good for me to know for the future 😅

romgrk commented 5 months ago

Too much complexity :( I know I said ok initially, but it was hard to reason about what was going on with the semaphore and the asynchronous mutation, and there were many edge-cases such as the ones you found in your follow-up PR, but I've also seen other weird behavior with buffer closing this last week. Notable one case where buffers would glitch and jitter very fast non-stop after closing a buffer. Had to restart my editor 2-3 times. Didn't investigate as I've been busy, but it felt better to revert and rework the approach.

I've added a .will_close flag that we set at bdelete and then consider those buffers as gone. This is trivial to understand and debug, compared to the semaphore + loop thing to close buffers asynchronously.