stevearc / resession.nvim

A replacement for mksession with a better API
MIT License
220 stars 15 forks source link

bug: saving a session in a "[No Name]" buffer loads a scratch buffer into window #18

Closed Subjective closed 1 year ago

Subjective commented 1 year ago

Did you check the docs and existing issues?

Neovim version (nvim -v)

NVIM v0.10.0-dev-713+gf2ce31d3d

Operating system/version

MacOS 13.4

Describe the bug

When saving a session while in a "[No Name]" buffer, loading it up opens a scratch buffer. This doesn't happen when "[No Name]" buffer is opened but not in the active window when saving. Additionally, saving a session with named buffers (e.g. :e testfile.txt) that have not yet been written to a file recreates empty buffers with those names when loading the session.

Screen Recording 2023-07-25 at 9 02 01 PM

Steps To Reproduce

  1. nvim -u repro.lua
  2. Open some buffers
  3. :enew
  4. <leader>s to save session while in the "[No Name]" buffer
  5. <leader>l to load the saved session
  6. Session opens with scratch buffer in the active window

Expected Behavior

I would expect the session to load without a scratch buffer when a session is saved on a "[No Name]" buffer. And to not load named but unwritten buffers, or at least have the option of ignoring them when saving the session. Thanks for your time!

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)

vim.g.mapleader = " "

-- install plugins
local plugins = {
    "folke/tokyonight.nvim",
    {
        "stevearc/resession.nvim",
        opts = {},
        keys = {
          { "<leader>s", function() require("resession").save() end },
          { "<leader>l", function() require("resession").load() end }
        }
    },
    -- add any other plugins here
}
require("lazy").setup(plugins, {
    root = root .. "/plugins",
})

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

Did you check the bug with a clean config?

stevearc commented 1 year ago

So there's two situations at work here

  1. unnamed buffers are restored if they are focused during the save
  2. named, unwritten buffers are saved and restored

For 1, this is actually intentional and, I believe, the least confusing way to behave. In a perfect world, if I save a session and open it again, I expect Neovim to look the exact same as when I left. This means that we need to restore all windows. If there's a scratch buffer in one of those windows, then we have to restore it with something there, and I think that a new scratch buffer is less confusing that just picking a random buffer to fill it. Think also about tabs. If you open up a new tab (empty, with a scratch buffer) then save and restore the session, what should happen to that tab? Again I think the least confusing behavior is to recreate that tab with a new scratch buffer.

For 2, this is an interesting case. I don't expect this to be a common scenario, so this is something that would make sense as an addition to your own config. You can set the buf_filter to ignore files that are not saved to disk. Probably something like this:

require("resession").setup({
  buf_filter = function(bufnr)
    local bufname = vim.api.nvim_buf_get_name(bufnr)
    if vim.bo[bufnr].buftype == "" and bufname ~= "" then
      if vim.fn.filereadable(bufname) == 0 then
        return false
      end
    end
    return require("resession").buf_filter(bufnr)
  end
})
Subjective commented 1 year ago

Thanks for the snippet in 2 :)

Regarding 1), I agree that it makes sense for everything to be restored to how it was previously (though it would be nice to have the option just restore the last active "real buffer"). My only qualm is that it doesn't work the same way it does with native :mksession:

What I expect to happen:

Restore a "[No Name]" buffer by creating a new "[No Name]" buffer instead of a scratch buffer ![Screen Recording 2023-07-31 at 5 35 39 PM](https://github.com/stevearc/resession.nvim/assets/56745535/a534a7a7-9855-45e3-841d-a1140fbada1d)

The current behavior:

1. A scratch buffer is created when restoring a "[No Name]" buffer instead of creating another "[No Name]" buffer ![Screen Recording 2023-07-31 at 5 05 09 PM](https://github.com/stevearc/resession.nvim/assets/56745535/9aa228b3-b701-4dfd-a77f-c013a55ae768)
2. A scratch buffer not created when restoring a scratch buffer (I think mksession just creates an empty buffer by default) ![Screen Recording 2023-07-31 at 5 03 43 PM](https://github.com/stevearc/resession.nvim/assets/56745535/1de4abf0-1f31-41a6-917a-703322ab1da2)
3. "[No Name]" buffer is not restored if it was not in the active window upon saving the last session ![Screen Recording 2023-07-31 at 5 26 47 PM](https://github.com/stevearc/resession.nvim/assets/56745535/b6be0280-92b9-434e-83a6-e3cdb075e555)

In any case, this a pretty minor nitpick - please don't feel obligated to make any changes, I just wanted to share my thoughts on this matter. Thanks for all the great plugins you've made!