stevearc / resession.nvim

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

bug: `BufReadPre` and `BufReadPost` autocommand events not triggering #44

Closed mehalter closed 2 months ago

mehalter commented 7 months ago

Did you check the docs and existing issues?

Neovim version (nvim -v)

0.9.4 release

Operating system/version

Arch Linux

Describe the bug

When running resession.load on "VimEnter" event like suggested in the docs it seems that events like BufReadPre and BufReadPost are not triggered as they should when files are being loaded into the editor. This breaks plugin lazy loading for file reading, auto commands that the user might have set up when files are read into the buffer, etc.

Steps To Reproduce

  1. run rm -rf .repro to make sure it's a fresh install
  2. run nvim -u repro.lua to instantiate the editor
  3. run :e repro.lua to load a file (see that messages about BufReadPre/BufReadPost happened)
  4. run :q to quite and save the session
  5. run nvim -u repro.lua
  6. run :messages to see that nothing is shown
  7. quit with :q
  8. run nvim -u repro.lua repro.lua to open the file directly
  9. see that messages about BufReadPre/BufReadPost happened

Expected Behavior

When files are read into the editor even when restoring from a session it should trigger the expected autocommand events so that it plays nicely with automations the user has set up such as to load plugins or do an action when files are loaded.

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"

local resession = require "resession"

vim.api.nvim_create_autocmd("BufReadPre", {
  callback = function() print "BUFREADPRE HAPPENED" end,
})

vim.api.nvim_create_autocmd("BufReadPost", {
  callback = function() print "BUFREADPOST HAPPENED" end,
})

vim.api.nvim_create_autocmd("VimLeavePre", {
  callback = function() resession.save "last" end,
})

vim.api.nvim_create_autocmd("VimEnter", {
  callback = function()
    if vim.fn.argc(-1) == 0 then resession.load("last", { silence_errors = true }) end
  end,
})

Did you check the bug with a clean config?

mehalter commented 7 months ago

I also get the same behavior if I remove the "VimEnter" autocmd and just load the session manually with :lua require("resession").load("last") which also doesn't trigger any sort of BufReadPre/BufReadPost autocmd events even though a file has been read

willothy commented 7 months ago

This might be because vim.o.eventignore is set to "all" during loading, I would assume for redraw reasons / because autocmds could trigger something that messes up the layout. Maybe re-enabling autocmds temporarily while loading buffers would solve this? I can make a PR if I find a solution :)

Edit: I can reproduce BufReadPre not triggering (only on the first file opened though), but BufReadPost always seems to work properly.

chaozwn commented 5 months ago

This might be because vim.o.eventignore is set to "all" during loading, I would assume for redraw reasons / because autocmds could trigger something that messes up the layout. Maybe re-enabling autocmds temporarily while loading buffers would solve this? I can make a PR if I find a solution :)

Edit: I can reproduce BufReadPre not triggering (only on the first file opened though), but BufReadPost always seems to work properly.

mark.

willothy commented 5 months ago

mark.

Hacked around for a few minutes, didn't find a solution and it wasn't particularly problematic so I never went back to it, sorry. I can maybe look into it again though.

mehalter commented 5 months ago

A decent workaround I've used is to just call

vim.cmd.doautoall "BufReadPost"

after a load call on VimEnter. The autocommand isn't triggered in the first place so it doesn't seem to have any performance problems and works well

willothy commented 5 months ago

A decent workaround I've used is to just call

vim.cmd.doautoall "BufReadPost"

Hah yeah that's what I ended up doing as well, added that to my post_load handler though since I do a lot of lazy loading.

gabyx commented 5 months ago

https://github.com/gabyx/astronvim/blob/main/autocmds.lua#L52

AThePeanut4 commented 3 months ago

I believe the issue is with the VimEnter autocommand, it needs to use nested = true (:help autocmd-nested):

vim.api.nvim_create_autocmd("VimEnter", {
  callback = function()
    -- Only load the session if nvim was started with no args
    if vim.fn.argc(-1) == 0 then
      resession.load(get_session_name(), { dir = "dirsession", silence_errors = true })
    end
  end,
  nested = true,
})

Unfortunately if you use your repro.lua to test, it will still appear to fail because resession runs :edit silently when restoring a session (emsg_silent is equivalent to :silent!), which completely suppresses all output: https://github.com/stevearc/resession.nvim/blob/742aba4998123fc11f490a3aeffe8f550b2cb789/lua/resession/init.lua#L625

With a bit of hackery, we can get the messages to show up:

-- 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",
})

local function force_print(s)
  -- equivalent to :unsilent echom
  vim.cmd.echom({ args = { vim.fn.string(s) }, mods = { unsilent = true } })
end

vim.cmd.colorscheme "tokyonight"

local resession = require "resession"

vim.api.nvim_create_autocmd("BufReadPre", {
  callback = function() force_print "BUFREADPRE HAPPENED" end,
})

vim.api.nvim_create_autocmd("BufReadPost", {
  callback = function() force_print "BUFREADPOST HAPPENED" end,
})

vim.api.nvim_create_autocmd("VimLeavePre", {
  callback = function() resession.save "last" end,
})

vim.api.nvim_create_autocmd("VimEnter", {
  callback = function()
    if vim.fn.argc(-1) == 0 then resession.load("last", { silence_errors = true }) end
  end,
  nested = true,
})

An easier way is just to compress a file with gzip and observe that it is correctly decompressed (i.e. the gzip plugin's BufReadPost autocmd worked).

Also, with my repro.lua, if I remove the VimEnter autocmd and run :lua require("resession").load("last") manually, I also get both BufReadPre and BufReadPost messages in console correctly.

mehalter commented 2 months ago

This worked great @AThePeanut4 ! Thanks for the recommendation and for updating the docs. I have thoroughly tested it and it seems to work perfectly.