Open cseickel opened 2 years ago
@bennypowers I am trying out auto-session
and I really like it. Unfortunately I can get this or my old session manager to restore the tree windows at all, not even as empty buffers. It is just completely omitted from the session restore.
Is it just me or does that happen to you as well with the latest updates?
The way I got around this with auto-session
was to use the command hooks.
pre_save_cmds
to do tabdo NeoTreeClose
post_save_cmds
to do tabdo NeoTreeReveal
post_restore_cmds
to do tabdo NeoTreeReveal
Sorry I can't provide an example setup I switched to neovim-session-manager
yesterday
It closes the neo-tree before saving the session, then opens it again whenever it finds a session
this is ok. I'd rather it only open a session IFF the tree was open when it saved the session
edit: made a little progress i suppose, but my tree state is always false. In other words I'm missing a handy way to determine whether or not any filesystem tree is currently open.
local TREE_STATE = '__AS_NT_FS_Open'
local function has_tree()
local manager = require 'neo-tree.sources.manager'
local states = manager.get_state 'filesystem'
vim.api.nvim_set_var(TREE_STATE, #states > 0)
end
local function close_neo_tree()
local manager = require 'neo-tree.sources.manager'
has_tree()
manager.close_all()
end
local function open_neo_tree()
if vim.api.nvim_get_var(TREE_STATE) then
require 'neo-tree.sources.manager'.show('filesystem')
end
end
require 'auto-session'.setup {
auto_session_create_enabled = false,
auto_save_enabled = true,
auto_restore_enabled = true,
auto_session_use_git_branch = true,
bypass_session_save_file_types = {
"neo-tree",
"tsplayground",
"query",
},
pre_save_cmds = {
close_neo_tree,
},
post_restore_cmds = {
open_neo_tree,
}
}
so what is the status of this?
@nmsobri It's not something that I'm looking at, and it's not something I'm interested in because I don't want the tree saved as part of the session. Someone else would have to volunteer to do work in this area for it to ever get done.
@cseickel alright.. can you point me to the direction on how I can achieve this?
I think the most important thing to know with regards to sessions is that neo-tree will create several buffer local variables that you can use to save and restore the state:
vim.api.nvim_buf_set_var(state.bufnr, "neo_tree_source", state.name)
vim.api.nvim_buf_set_var(state.bufnr, "neo_tree_tabnr", state.tabnr)
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)
You can use this information in a pre-session save function that iterates over all open buffers that are displayed in a window to save the state.
If your session creation method includes saving buffer local variables, then you can either create your own autocmd or submit a PR here that reads in those variables and opens a new neo-tree instance to replace it.
nvm, i figure it out using shada
I've just started out using Neovim, and encountered this issue too. I'm using bufferline, so I just have a single neo-tree buffer. This means in my case, there's no need to store the information @cseickel suggested in the previous post. However I did want to save:
Through looking at the neo-tree source and really helpful comments above, I did manage to achieve this. I had to use the possession plugin, which offers saving user-specified custom data in the session file.
My config is as follows:
--[[ *possession* ]]
neo_expand_dirs = function(dir_paths, dir_i)
if dir_i > #dir_paths then
return
end
local cur_dir_path = dir_paths[dir_i]
vim.loop.fs_opendir(cur_dir_path, function(err, dir)
if err then
print(cur_dir_path, ': ', err)
neo_expand_dirs(dir_paths, dir_i + 1)
return
end
vim.loop.fs_readdir(dir, function(err, entries)
if entries[1] ~= nil then
vim.schedule(function()
local utils = require('neo-tree.utils')
local manager = require('neo-tree.sources.manager')
local filesystem = require('neo-tree.sources.filesystem')
local state = manager.get_state('filesystem')
local child_path = utils.path_join(cur_dir_path, entries[1].name)
filesystem._navigate_internal(state, state.path, child_path, function()
state.explicitly_opened_directories = state.explicitly_opened_directories or {}
state.explicitly_opened_directories[cur_dir_path] = true
neo_expand_dirs(dir_paths, dir_i + 1)
end)
end)
end
end)
end)
end
neo_get_state = function()
for _, buf_i in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_get_option(buf_i, 'filetype') == 'neo-tree' and next(vim.fn.win_findbuf(buf_i)) then
local utils = require('neo-tree.utils')
local manager = require('neo-tree.sources.manager')
local filesystem = require('neo-tree.sources.filesystem')
local state = manager.get_state('filesystem')
local expanded_dirs = {}
if state.explicitly_opened_directories ~= nil then
for cur_dir, is_expanded in pairs(state.explicitly_opened_directories) do
if is_expanded then
table.insert(expanded_dirs, cur_dir)
end
end
end
return { path = state.path, expanded_dirs = expanded_dirs, show_hidden = state.filtered_items.visible }
end
end
end
neo_set_state = function(data)
require('neo-tree.command').execute({
action = 'show',
dir = data['path'],
})
if data['show_hidden'] then
local manager = require('neo-tree.sources.manager')
local state = manager.get_state('filesystem')
state.filtered_items.visible = true
end
neo_expand_dirs(data['expanded_dirs'], 1)
end
require('possession').setup({
autosave = {
current = true,
},
commands = {
save = 'SSave',
load = 'SLoad',
rename = 'SRename',
close = 'SClose',
delete = 'SDelete',
show = 'SShow',
list = 'SList',
migrate = 'SMigrate',
},
hooks = {
before_save = function(name)
local res = {}
local neo_state = neo_get_state()
if neo_state ~= nil then
res['neo_tree'] = neo_state
end
return res
end,
after_save = function(name, user_data, aborted) end,
before_load = function(name, user_data) return user_data end,
after_load = function(name, user_data)
if user_data['neo_tree'] ~= nil then
neo_set_state(user_data['neo_tree'])
end
end,
},
plugins = {
delete_hidden_buffers = false, -- For *bufferline*
},
})
@cseickel I wonder if you're open to a PR to include the neo_expand_dirs()
function? It just expands a list of user-specified directories. I think it's quite a useful function for config files.
Even better if there's a better way to do what I wrote.
I would accept a PR that adds an api method to save and restore this state, but I don't think that most of the work you are doing in neo_expand_dirs()
is necessary. I'm pretty sure this could be done just by setting the entire explicitly_opened_directories
object as-is and doing one navigate.
Hm the only place I see in the code that reads explicitly_opened_directories
is https://github.com/nvim-neo-tree/neo-tree.nvim/blob/7e2a3caf999e2028abb643eb0472f351b2777591/lua/neo-tree/sources/filesystem/init.lua#L71. I think it depends on expanded_nodes
being set.
I tried the following, which does nothing:
neo_expand_dirs = function(dir_paths, dir_i)
local utils = require('neo-tree.utils')
local manager = require('neo-tree.sources.manager')
local filesystem = require('neo-tree.sources.filesystem')
local state = manager.get_state('filesystem')
for _, cur_dir_path in ipairs(dir_paths) do
state.explicitly_opened_directories = state.explicitly_opened_directories or {}
state.explicitly_opened_directories[cur_dir_path] = true
end
end
You're right, that property is actually the entirely wrong thing to use. See this code that actually clones the state of the tree into a new window:
What you really want to do is to get the opened directories like this:
renderer.get_expanded_nodes(old_state.tree)
and restore that output to
state.force_open_folders
Ah thanks a lot for that. That simplified my code heaps. Now it's just:
--[[ *possession* ]]
neo_is_open = function()
for _, buf_i in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_get_option(buf_i, 'filetype') == 'neo-tree' and next(vim.fn.win_findbuf(buf_i)) then
return true
end
end
end
neo_get_state = function()
if not neo_is_open() then
return
end
local manager = require('neo-tree.sources.manager')
local renderer = require('neo-tree.ui.renderer')
local state = manager.get_state('filesystem')
local expanded_nodes = renderer.get_expanded_nodes(state.tree)
return { path = state.path, expanded_nodes = expanded_nodes, show_hidden = state.filtered_items.visible }
end
neo_set_state = function(data)
local command = require('neo-tree.command')
local manager = require('neo-tree.sources.manager')
local state = manager.get_state('filesystem')
command.execute({
action = 'show',
dir = data['path'],
})
state.filtered_items.visible = data['show_hidden']
state.force_open_folders = data['expanded_nodes']
end
Hi, I found this thread useful as I'm currently exploring session management with rmagatti/auto-session
and neo-tree.
I decided to try and persist the open/closed state of Neo-tree when exiting vim. I use a global variable to track whether neo-tree was opened on last SessionSave. I needed to call vim.cmd":wshada" in the pre_save_cmds
hook in order for the variable to be saved to the shada file. Similarly, I lazy-load auto-session on the "UIEnter" event to make sure that the global variable is restored when I reopen Neo-tree.
It is good to know that the full tree-state can be persisted & restored efficiently with Possession which seem more straightforward than using the global variable.
And it is good to know that there is a proposed enhancement to have Neo-tree restore itself on session load.
Could somebody include full instructions for this please? maybe using rmagatti/auto-session
?
https://github.com/nvim-neo-tree/neo-tree.nvim/discussions/126 this is from their project
@PixsaOJ The possession can be configured to use some Neotree hooks on save/restore to save its state as steven showed. But I didn't find a session-plugin that does this automatically yet. Like this .
Edit: I published my session-config as a plugin. It depends on Neotree + Bufferline but it's all in the readme. It's not very configurable but it does restore buffers & the Neotree buffer on restarts. Make sure that the $XDG_CONFIG_HOME/nvim-data/sessions folder exists.
Discussed in https://github.com/nvim-neo-tree/neo-tree.nvim/discussions/126