-
Notifications
You must be signed in to change notification settings - Fork 255
Restore tree state in session restore #128
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
Comments
@bennypowers I am trying out Is it just me or does that happen to you as well with the latest updates? |
The way I got around this with |
This is my current config:local function close_neo_tree()
require 'neo-tree.sources.manager'.close_all()
end
local function open_neo_tree()
require 'neo-tree.sources.manager'.show('filesystem')
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,
}
} 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 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 |
Hm the only place I see in the code that reads
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: neo-tree.nvim/lua/neo-tree/setup/init.lua Lines 340 to 346 in 7e2a3ca
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 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 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 #126 this is from their project |
@PixsaOJ 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 #126
Originally posted by bennypowers February 6, 2022
Hello!
I'm using neo-tree with
auto-session
andbufferline.nvim
, and notice the following:quitall
neo-tree filesystem [1]
I'd like instead for the session to restore as is, i.e.
quitall
Should I hook into auto-session to prevent saving buffers with type
neo-tree
and to focus the active buffer on startup?The text was updated successfully, but these errors were encountered: