mrjones2014 / smart-splits.nvim

🧠 Smart, seamless, directional navigation and resizing of Neovim + terminal multiplexer splits. Supports tmux, Wezterm, and Kitty. Think about splits in terms of "up/down/left/right".
MIT License
814 stars 32 forks source link

[Bug]: `set laststatus=3` + lualine.nvim + smart-splits.nvim == flickering when switching windows #179

Open ColinKennedy opened 3 months ago

ColinKennedy commented 3 months ago

Similar Issues

Neovim Version

NVIM v0.10.0-dev-2791+g99b3a068d
Build type: RelWithDebInfo
LuaJIT 2.1.1710088188
Run "nvim -V1 -v" for more info

Multiplexer Integration

tmux

Multiplexer Version

tmux 3.a

Steps to Reproduce

  1. Create a split and / up and down

Expected Behavior

No strobing on lualine. Note: No strobing / flickering happens when switching with simply j / k. Only smart-splits.nvim has this problem, it seems.

Actual Behavior

It flickers as you switch windows.

Minimal Configuration to Reproduce

-- 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 = {
  {
      "nvim-lualine/lualine.nvim",
      opts = true,
  },
  {
      "mrjones2014/smart-splits.nvim",
      config = function()
        require("smart-splits").setup(
            {
                resize_mode = {
                    hooks = {
                        on_leave = require('bufresize').register,
                    },
                },
            }
        )

        vim.keymap.set(
            "n",
            "<C-j>",
            require("smart-splits").move_cursor_down,
            {desc="Jump to the window (or tmux pane) below."}
        )
        vim.keymap.set(
            "n",
            "<C-k>",
            require("smart-splits").move_cursor_up,
            {desc="Jump to the window (or tmux pane) above."}
        )
      end,
      dependencies = { "kwkarlwang/bufresize.nvim" },
  }
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd[[set laststatus=3]]

Additional Details and/or Screenshots

Flickering

https://github.com/mrjones2014/smart-splits.nvim/assets/10103049/3f910dd8-99ef-427d-acde-bd86a15cf979

(uses and from the reproduction)

Working

https://github.com/mrjones2014/smart-splits.nvim/assets/10103049/34e49499-a5b0-4f88-82d2-fa8b61f424e1

The same environment as before but with nmap <C-{J,K}> <C-W>{j,k} to switch between the splits, instead. No flickering

ColinKennedy commented 3 months ago

Quick update - I switched to Wezterm and it happens less often but still does happen. The previous recordings are from Windows Terminal (Windows 10)

mrjones2014 commented 3 months ago

Does it only happen with laststatus=3?

ColinKennedy commented 3 months ago

I think so, yes. I made another recording with statusline=3 and statusline=1. The "flicker" from statusline=3 is visually identical to the "inactive window" of statusline=1 if you freeze-frame the recording while the statusline=3 view switches windows.

Probably for a split moment when switching between windows, the bottom statusline thinks that it switched away from the current window and is now "viewing" the inactive window. So it shows the inactive window as the only to later realize "actually the inactive window is still the current window, I'll show it as an active statusline instead". And that temporary confusion causes the flicker.

I guess it depends on how smart-splits.nvim is implemented but possibly this code be a (Neo)vim bug. However just worth reiterating <C-w>{j,k} have no flickering issues so I'm currently inclined to think it's a plugin issue.

https://github.com/mrjones2014/smart-splits.nvim/assets/10103049/94d01eea-2670-44b5-b534-45f3244f4340

mrjones2014 commented 3 months ago

Yeah, the plugin will potentially visit multiple windows to decide if it should wrap and verify it went the right direction. I'm not sure how to resolve this.

ColinKennedy commented 3 months ago

Well the good news is that on a fast enough terminal emulator this comes up less often. For example Windows Terminal flickers on every window change. But Wezterm hardly ever flickers. If it's possible to "look before you leap" then I could see that as a way of solving the issue completely but you'd know much better if that's a good idea with this codebase. If not, "get a faster terminal" IMO is a viable outcome and we can close this issue. Either way I have a personal fix so I'm happy. Up to you!

mrjones2014 commented 3 months ago

Well, the implementation of window movement is quite overcomplicated now, since improved Neovim APIs as well as me just having more knowledge of how it works. I've been meaning to refactor it for quite a while, and that might alleviate this issue somewhat.