stevearc / resession.nvim

A replacement for mksession with a better API
MIT License
175 stars 13 forks source link

bug: a floating window might interfere with session loading #37

Closed zemzelett closed 9 months ago

zemzelett commented 9 months ago

Did you check the docs and existing issues?

Neovim version (nvim -v)

0.9.2

Operating system/version

MacOS 13.5.1

Describe the bug

tl/dr

When a floating window (in my case lazy.nvim) is open during the loading of a session, it might interfere with the creation of the windows in such a way that the first window of the loaded session takes the place of the floating window.

A suggested "fix"

Disclaimer: I'm reluctant to call this a bug on resession.nivm's part. See the next paragraph for the why.

The fix i am proposing in PR #36 tries to solve the aforementioned issue by, after destroying all buffers, creating a new window by splitting off the existing last window and closing the leftover window from the previous session. The newly opened window is "clean" and therefore suited to be populated with session to be loaded.

A bit more context and what i found out

I'm pretty knew to the inner workings of Neovim and it's API and Lua. This hinders me to investigate this issue as much as i'd like to before presenting it to you. So keep that in mind, i apologise in advance.

I observed this behavior with lazy.nvim occasionally. It took me a while to realise this is due to the fact that when having added a new plug-in and restarting Neovim after doing so, the lazy.nvim window would popup and install it. I have resession.nvim setup so it loads the last profile in the current projects directory. So, after installing, resession.nvim would kick in and load the session. This generally works fine unless lazy.nvim installed things prior to the load. Then the left-most window would strangely occupy a floating window.

I could reliably reproduce this issue.

I tried to re-enact the same with mason.nvim as it also has a floating window. To no avail, resession.nvim interacted perfectly fine with it.

This led me to digging in both lazy.nvim's and mason.nvim's codebases in order to figure out why that is the case. My lack of knowledge of Neovim internals and the two considerable sizes of codebases made me give this up at some point. I could not find a difference between the two plug-ins in how they setup their floating windows.

I then concentrated on finding a workaround for myself in order to not have lazy.nvim interfere with enjoying my resession.nvim experience. What i ended up doing felt like it might be worth including into the resession.nvim codebase.

While searching that workaround i also found out, that deleting lazy.nvim's buffer does not help entirely. While the floating window is not a problem anymore, it's settings are for some reason. As an example: My config shows line numbers, these won't be present this way.

Steps To Reproduce

  1. Open up Neovim with the minimal config below.
  2. Open two windows with two distinctive files
  3. Save the session
  4. Open lazy.nvim
  5. Load the previously saved session while lazy.nvim is still in the foreground!

This works with any floating window created as follows as well:

vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), true, { relative="editor", row=1, col=1, width=100, height=100 })

Expected Behavior

Loading a session will never result in a floating window being part of the session, basically breaking it.

Directory structure

No response

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

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

local resession = require("resession")
local set = vim.keymap.set
vim.g.mapleader = " "
set("n", "<leader>rs", resession.save, { desc = "Save session" })
set("n", "<leader>rl", resession.load, { desc = "Load session" })
set("n", "<leader>rd", resession.delete, { desc = "Delete session" })

Did you check the bug with a clean config?

stevearc commented 9 months ago

This was definitely a bug in resession. While it is caused by an interaction with another plugin, we should be able to handle the case of being focused in a floating window.

I went with a slightly different solution from your PR to make the operations a bit more explicit. The reason the vsplit works is kind of a side effect. Floating windows don't support vsplit, so that will cause your cursor to go to a normal window and then split it. In this case it's not the splitting that fixes the problem, it's the leaving the floating window. I just made that operation more explicit.

Thanks for the report!

zemzelett commented 9 months ago

Thank you for the insight!