Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(setup): add option to restore tree on session restore if possible #1366

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

pysan3
Copy link
Collaborator

@pysan3 pysan3 commented Feb 28, 2024

Experimental flag.

I'll do it correct in the rewrite.

Ref: #1365

@pysan3 pysan3 marked this pull request as draft February 28, 2024 07:06
@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 28, 2024

return {
  "pysan3/neo-tree.nvim",
  branch = "restore-session-experimental",
  version = false,
  opts = {
    auto_restore_session_experimental = true,
    -- ...

Caution:

You need to have blank set to sessionoptions like it is said here.
https://github.com/rmagatti/auto-session?tab=readme-ov-file#recommended-sessionoptions-config

For the case of vimscript, set sessionoptions+=blank. Idk much about lua.

Caution2:

It will be wonky (or not work at all) when you set the default neo-tree position to float or current.

Caution3:

If you had more than one neo-tree sources opened, only one of them will be respected, with filesystem being most prioritized.

Caution4:

Neotree must be loaded before session restore is done.

lazy = false for lazy.nvim users.

Or :lua require("neo-tree") in PRE_restore_hook in your session plugin.

@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 28, 2024

@SparrowMike Sorry to ping you many times.

Did you have lazy = false?

I added Caution 4 above.

@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 28, 2024

record.mp4

This is what I'm seeing.

The one I used to switch to a different nvim process is tmux (yellow-ish selector) so don't care about that.

  1. set sessionoptions+=blank
  2. :SessionSave (1)
  3. :qa
  4. $ nvim
  5. --> Restored correctly.
  6. Switch to a different neovim.
  7. set sessionoptions+=blank and :SessionSave (2)
  8. Go back to the old neovim.
  9. <Leader>ls -> the UI
  10. Session (2) is loaded successfully and neo-tree is loaded.
  11. <Leader>ls again and select (1)
  12. Session (1) is loaded with neo-tree again

@cseickel
Copy link
Contributor

@pysan3 There's no reason to be hacky about this. We already store all details about the tree in buffer local variables every time a window is shown. If there is any extra information you may need, you can easily add it here:

if type(state.bufnr) == "number" then
vim.api.nvim_buf_set_var(state.bufnr, "neo_tree_source", state.name)
vim.api.nvim_buf_set_var(state.bufnr, "neo_tree_tabnr", tabid_to_tabnr(state.tabid))
vim.api.nvim_buf_set_var(state.bufnr, "neo_tree_tabid", state.tabid)
vim.api.nvim_buf_set_var(state.bufnr, "neo_tree_position", state.current_position)
vim.api.nvim_buf_set_var(state.bufnr, "neo_tree_winid", state.winid)
end

Those buffer variables should be saved as part of the session and you can use them to restore the tree exactly as it was. I would think that auto-sesion also saves and restores the cwd of the window/tab so you shouldn't have to specify a dir to the command. If not, you can add the current root dir as another variable.

@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 28, 2024

Those buffer variables should be saved as part of the session and you can use them to restore the tree exactly as it was.

Are you sure about that?

When I :mksession, I don't see those variables written to the session file. Am I missing something?

@cseickel
Copy link
Contributor

Are you sure about that?

When I :mksession, I don't see those variables written to the session file. Am I missing something?

You're right, I guess it only save global variables with an upper case and not buffer local variables, which is frustrating.

The ideal solution is to add an API to require("neo-tree").save_session() and require("neo-tree").restore_session(). The session can be created by iterating over all states and serialized to some string format which is saved to vim.g.NeotreeSesionState, which will be saved as part of the standard session mechanism. All session plugins have some utility for running specific commands before save and after restore so you can have a perfect solution using that technique.

@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 28, 2024

I was actually thinking of enhancing renderer.position.save to become not only a position saver, but it'll save some kind of data structure which contains cwd (i.e. session name?), topline, lnum, (colnum), expanded_nodes (list of node_ids that are explicitly expanded), and so on.

I haven't yet solidified the API yet or even started implementing it, but I think this'll be the solution to a lot of session restoring mechanisms.

@josephcrawfordSRH
Copy link

josephcrawfordSRH commented Feb 28, 2024

@pysan3 I have run through a test using your fork and branch and it seems there is progress, the tree no longer seems to open full screen. However there are still a few issues, one instance when I switched sessions the tree remained open with the cwd of the previous session. I am also seeing tabs get opened for the session directory and [No Name].

The error that you see flash on the screen is the following

[Neo-tree ERROR] Error in event handler for event vim_after_session_load[table: 0x01012e19e0]: ...hare/nvim/lazy/neo-tree.nvim/lua/neo-tree/setup/init.lua:696: attempt to call field 'list_contains' (a nil value)

I slowed down on my actions in this screen recording, please let me know if you are able to understand, if not I will go through and explain all actions through text as well.

This is my config for neo-tree, outside of using the default implementation from LazyVim

return {
  "pysan3/neo-tree.nvim",
  branch = "restore-session-experimental",
  version = false,
  opts = {
    auto_restore_session_experimental = true,
  },
}

This is my auto-session configuration

return {
  "rmagatti/auto-session",
  config = function()
    require("auto-session").setup({
      auto_session_last_session_dir = vim.fn.stdpath("data") .. "/sessions/",
      auto_session_root_dir = vim.fn.stdpath("data") .. "/sessions/",
      auto_session_enabled = true,
      log_level = vim.log.levels.ERROR,
      auto_session_suppress_dirs = { "~/", "~/Projects", "~/Downloads", "/" },
      auto_save_enabled = true,
      auto_session_create_enabled = true,
      session_lens = {
        buftypes_to_ignore = {},
        load_on_setup = true,
        theme_conf = { border = true },
        previewer = false,
      },
    })

    vim.keymap.set("n", "<leader>ls", require("auto-session.session-lens").search_session, {
      noremap = true,
    })
  end,
}
Screen.Recording.2024-02-28.at.10.08.55.AM.mp4

@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 28, 2024

@josephcrawfordSRH That helps a lot! Thank you.

OMG vim.list_contains is only included in nvim-nightly...

@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 28, 2024

Fixed it. Could you update and try again @josephcrawfordSRH ?

@josephcrawfordSRH
Copy link

@pysan3 I have updated and tested again, I feel it is getting much closer. I am still seeing the tab for the session appear and the tree goes to being full screen. I managed to figure out how to fix it by mixing up my keys :). Hitting t in normal mode will get the tree back to normal size. In the attached video when you see it jump from full-screen to normal size that is from hitting the t key.

Screen.Recording.2024-02-28.at.1.10.06.PM.mp4

@pysan3
Copy link
Collaborator Author

pysan3 commented Feb 29, 2024

@josephcrawfordSRH I believe netrw hijacking and session restore is colliding.

Could you disable netrw and test it out?

Put this in the top line of your init.vim.

let loaded_netrwPlugin = 1

@josephcrawfordSRH
Copy link

josephcrawfordSRH commented Feb 29, 2024

@josephcrawfordSRH I believe netrw hijacking and session restore is colliding.

Could you disable netrw and test it out?

Put this in the top line of your init.vim.

let loaded_netrwPlugin = 1

This did not help at all...


I stand corrected, after saving my sessions again I was actually able to flip back and forth between sessions having the tree work properly. For about 3 switches anyway after that the tree was again full screen. I am not sure why it would act like that initially it got my hopes up :D

I think it has something to do with the session directory being opened in a buffer tab in bufferline or something. It seems like if I close the buffer and save my session I can jump back and forth without issue. As soon as I try to jump with the buffer open it goes full screen.

Screen.Recording.2024-02-29.at.8.42.55.AM.1.mp4

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 4, 2024

@josephcrawfordSRH Could you repost your neo-tree config?

This is more of an issue on the auto-session side that your auto-session does not take care of unlisted buffers carefully, but I can fix it on our end (and it'll be easier for us to solve anyways).

However I cannot reproduce the issue on my end since I deal with those buffers myself in my config.

Could you fill in this repro.lua? Or if you don't understand what to do, please send me your config file and I'll figure it out.

-- 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 = {
  "folke/tokyonight.nvim",
  -- add any other plugins here
}

local neotree_config = {
  "nvim-neo-tree/neo-tree.nvim",
  dependencies = { "MunifTanjim/nui.nvim", "nvim-tree/nvim-web-devicons", "nvim-lua/plenary.nvim" },
  cmd = { "Neotree" },
  keys = {
    { "<Leader>e", "<Cmd>Neotree<CR>" }, -- change or remove this line if relevant.
  },
  opts = {
    -- Your config here
    -- ...
  },
}

table.insert(plugins, neotree_config)
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

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

@josephcrawfordSRH
Copy link

I would love to provide you with that, but neo-tree is bundled with lazyvim. I am not sure where the default opts are for neo-tree when it comes to the lazy vim internals. All I have for my own configuration which overrides the defaults is the following.

return {
  "pysan3/neo-tree.nvim",
  branch = "restore-session-experimental",
  version = false,
  lazy = false,
  opts = {
    auto_restore_session_experimental = true,
  },
}

I have only installed LazyVIm and added the auto-session plugin along with the neo-tree modifications that were requested last week to see about getting this working.

My auto session configuration is the following.

return {
  "rmagatti/auto-session",
  config = function()
    require("auto-session").setup({
      auto_session_last_session_dir = vim.fn.stdpath("data") .. "/sessions/",
      auto_session_root_dir = vim.fn.stdpath("data") .. "/sessions/",
      auto_session_enabled = true,
      log_level = vim.log.levels.ERROR,
      auto_session_suppress_dirs = { "~/", "~/Projects", "~/Downloads", "/" },
      auto_save_enabled = true,
      auto_session_create_enabled = true,
      session_lens = {
        buftypes_to_ignore = {},
        load_on_setup = true,
        theme_conf = { border = true },
        previewer = false,
      },
    })

    vim.keymap.set("n", "<leader>ls", require("auto-session.session-lens").search_session, {
      noremap = true,
    })

    vim.o.sessionoptions = "blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal,localoptions"
  end,
}

To make it easier to replicate I am attaching my nvim configs, you can launch nvim with these, I believe
they should include lazyvim but not sure if you will need to install lazyvim or not

nvim-config.zip

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 4, 2024

Could you use vimscript instead? I think this might fix the issue.

set sessionoptions+=winpos,terminal,folds
set sessionoptions+=blank

And add lazy = false to auto-session's spec.

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 4, 2024

And delete all old sessions and start from scratch.

@josephcrawfordSRH
Copy link

josephcrawfordSRH commented Mar 5, 2024

This did not help!

What finally did end up working was adding the following to my init.lua instead of in the auto sessions configuration.

vim.o.sessionoptions = "blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal,localoptions"

I am going to give this a good test but jumping between 2 projects seems to work just fine now.

@josephcrawfordSRH
Copy link

josephcrawfordSRH commented Mar 5, 2024

I give up, my guess is the auto session plugin is just broken or something when it comes to neo-tree integration

I get this after setting up several projects. Seems to happen when I save a session with open buffers. Everything works if I save with no buffers open.

Screenshot 2024-03-05 at 9 28 20 AM

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 5, 2024

As I said, put the vim script in init.lua / init.vim and please do nothing else.

Also please delete all existing sessions while you have no neovim instance opened.
If you ever source any of the old sessions or have a living neovim instance while you delete all of them, sessionopts will be overwritten from the session file and will propagate to the next sessions, no matter what you put in the config, which is the problem.
You should not have localoptions in the list.

@josephcrawfordSRH
Copy link

will try it now

@josephcrawfordSRH
Copy link

josephcrawfordSRH commented Mar 5, 2024

I did exactly as you stated, closed all nvim instances, deleted sessions, removed localoptions, opened nvim, opened a buffer, saved the session, closed nvim, went to a new project, opened nvim, opened a buffer, saved the project. Switched to my other project just to see the following.

Screen.Recording.2024-03-05.at.10.06.13.AM.mp4

@josephcrawfordSRH
Copy link

josephcrawfordSRH commented Mar 5, 2024

After a few more tests it kind of works but the buffers are hidden while the tree is full-size. I close the tree it shows my open buffer, i re-open the tree it is full-size.

Screen.Recording.2024-03-05.at.10.24.24.AM.mp4

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 5, 2024

Let me reiterate. Do not use vim.o.

If you really want to use lua for whatever reason, use vim.opt and :append. Do not reset the whole value. Please read :h vim.opt.

It looks like you still have vim.o in your auto-session config function. Didn't you say you deleted that? PLEASE DELETE THAT LINE. Search for sessionoptions in the entire config and be exactly sure that you don't have it set other than init.lua.

And use :append because I asked you to run set sessionoptions+=, not set which is only available with vim.opt and not vim.o.

If you don't understand the difference between vim.o and vim.opt, THEY ARE DIFFERENT. Please don't self judge and do what you think is correct.

@josephcrawfordSRH
Copy link

I had deleted it from the auto-sessions.lua file, here is a screen recording of what you have asked. Sorry for thinking that .o and .opt were the same, I am still new to vim and it is getting frustrating :D

Screen.Recording.2024-03-05.at.11.18.25.AM.mp4

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 5, 2024

Thank you. Finally we are on the same table.

I can see the issue but I cannot reproduce it on my end.

Why do you have neo-tree opened right after neovim is launched with n? You did delete all the session files right?

Why do you not have the welcome screen that should be installed with LazyVim by default?

Could you zip your config and send it to me again? I think you made some changes from last time.

@josephcrawfordSRH
Copy link

josephcrawfordSRH commented Mar 5, 2024

@pysan3 this is my alias for n : alias n="nvim ."
I did delete all the session files, and also made sure i had no neovim instances running before I deleted them.

I think the tree opens because of my alias, this is how I open my project folders.
I believe due to my alias I do not have the welcome screen.

Attached is my config again.

nvim-config.zip

I just cleared my sessions and tested again using simply the nvim command in my project directory. This seems to work just fine, I can jump between projects and when I open the tree it in-fact is changed. It would be nice if this could work with the nvim . command as well though.

I did find one issue where when my initial session was in ~/.config after jumping back since the file I was viewing was in ~/.config/nvim the tree put me in that directory rather than leaving me in ~/config

Screen.Recording.2024-03-05.at.3.50.05.PM.mp4

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 7, 2024

@josephcrawfordSRH

It would be nice if this could work with the nvim . command as well though.

True, but this is not as easy due to how session files are constructed.
Let me postpone this as a TODO until we make it an official feature.

I did find one issue where when my initial session was in ~/.config after jumping back since the file I was viewing was in ~/.config/nvim the tree put me in that directory rather than leaving me in ~/config

  • Move vim.opt.sessionoptions after require("config.lazy")
  • lazy = false for auto-session

And I know it's tedious but please don't forget to delete the session dir again...

Here is the config after I made a couple of changes (will extract to ./restore/).
nvim-config-pysan3.zip

@josephcrawfordSRH
Copy link

The most tedious part is having to have auto-session lazy=false as I have to manually load it all the time

@pysan3
Copy link
Collaborator Author

pysan3 commented Mar 11, 2024

I think it's the other way around. Lazy = true won't load the plugin on startup and you have to manually load it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants