Persisted.nvim is a simple lua plugin for working with sessions in Neovim
(Forked from Persistence.nvim)
- ๐ฒ Supports sessions across multiple git branches
- ๐ญ Telescope extension to work with saved sessions
- ๐๏ธ Custom events which users can hook into for tighter integration
- ๐ Simple API to save/stop/restore/delete/list the current session(s)
- ๐ Supports autosaving and autoloading of sessions with allowed/ignored directories
- ๐พ Automatically saves the active session under
.local/share/nvim/sessions
on exiting Neovim
- Neovim >= 0.8.0
Install the plugin with your preferred package manager:
-- Lua
{
"olimorris/persisted.nvim",
config = true
}
Note
The lazy = true
option may be useful if you use a dashboard
-- Lua
use({
"olimorris/persisted.nvim",
config = function()
require("persisted").setup()
end,
})
" Vim Script
Plug 'olimorris/persisted.nvim'
lua << EOF
require("persisted").setup {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
}
EOF
If you wish to use session autoloading alongside a dashboard plugin, it is recommended that you give this plugin a greater loading priority. With Packer the after
config option can be used and in Lazy.nvim, the priority
property.
Ensure that the telescope extension is loaded with:
require("telescope").load_extension("persisted")
The layout can then be customised from within Telescope:
require('telescope').setup({
defaults = {
โฆ
},
extensions = {
persisted = {
layout_config = { width = 0.55, height = 0.55 }
}
}
})
The plugin comes with a number of commands:
:SessionToggle
- Determines whether to load, start or stop a session:SessionStart
- Start recording a session. Useful ifautosave = false
:SessionStop
- Stop recording a session:SessionSave
- Save the current session:SessionLoad
- Load the session for the current directory and current branch (ifgit_use_branch = true
):SessionLoadLast
- Load the most recent session:SessionLoadFromFile
- Load a session from a given path:SessionDelete
- Delete the current session
The Telescope extension may be opened via :Telescope persisted
. The available actions are:
<CR>
- Open/source the session file<C-b>
- Add/update the git branch for the session file<C-c>
- Copy the session file<C-d>
- Delete the session file
The plugin sets a number of global variables throughout its lifecycle:
vim.g.persisting
- (bool) Determines if the plugin is active for the current sessionvim.g.persisted_exists
- (bool) Determines if a session exists for the current working directoryvim.g.persisted_loaded_session
- (string) The file path to the current session
The plugin comes with the following defaults:
require("persisted").setup({
save_dir = vim.fn.expand(vim.fn.stdpath("data") .. "/sessions/"), -- directory where session files are saved
silent = false, -- silent nvim message when sourcing session file
use_git_branch = false, -- create session files based on the branch of a git enabled repository
default_branch = "main", -- the branch to load if a session file is not found for the current branch
autosave = true, -- automatically save session files when exiting Neovim
should_autosave = nil, -- function to determine if a session should be autosaved
autoload = false, -- automatically load the session for the cwd on Neovim startup
on_autoload_no_session = nil, -- function to run when `autoload = true` but there is no session to load
follow_cwd = true, -- change session file name to match current working directory if it changes
allowed_dirs = nil, -- table of dirs that the plugin will auto-save and auto-load from
ignored_dirs = nil, -- table of dirs that are ignored when auto-saving and auto-loading
telescope = {
reset_prompt = true, -- Reset the Telescope prompt after an action?
},
})
As the plugin uses Vim's :mksession
command then you may change the vim.o.sessionoptions
value to determine what to write into the session. Please see :h sessionoptions
for more information.
Note
The author uses: vim.o.sessionoptions = "buffers,curdir,folds,tabpages,winpos,winsize"
The location of the session files may be changed by altering the save_dir
configuration option. For example:
require("persisted").setup({
save_dir = vim.fn.expand(vim.fn.stdpath("data") .. "/sessions/"), -- Resolves to ~/.local/share/nvim/sessions/
})
Note
The plugin may be unable to find existing sessions if the save_dir
value is changed
One of the plugin's core features is the ability to have multiple session files for a given project, by using git branches. To enable git branching:
require("persisted").setup({
use_git_branch = true,
})
By default, the plugin will automatically save a Neovim session to disk when the VimLeavePre
event is triggered. Autosaving can be turned off by:
require("persisted").setup({
autosave = false,
})
Autosaving can be further controlled for certain directories by specifying allowed_dirs
and ignored_dirs
.
There may be occasions when you do not wish to autosave; perhaps when a dashboard or a certain buftype is present. To control this, a callback function, should_autosave
, may be used which should return a boolean value.
require("persisted").setup({
should_autosave = function()
-- do not autosave if the alpha dashboard is the current filetype
if vim.bo.filetype == "alpha" then
return false
end
return true
end,
})
Of course, if you wish to manually save the session when autosaving is disabled, the :SessionSave
command can be used.
Note
If autosave = false
then the should_autosave
callback will not be executed.
The plugin can be enabled to automatically load sessions when Neovim is started. Whilst off by default, this can be turned on by:
require("persisted").setup({
autoload = true,
})
You can also provide a function to run when autoload = true
but there is no session to be loaded:
require("persisted").setup({
autoload = true,
on_autoload_no_session = function()
vim.notify("No existing session to load.")
end
})
Autoloading can be further controlled for certain directories by specifying allowed_dirs
and ignored_dirs
.
Note
Autoloading will not occur if the plugin is lazy loaded or a user opens Neovim with arguments other than a single directory argument. For example: nvim some_file.rb
will not result in autoloading but nvim some/existing/path
or nvim .
will.
There may be a need to change the working directory to quickly access files in other directories without changing the current session's name on save. This behavior can be configured with follow_cwd = false
.
By default, the session name will match the current working directory:
require("persisted").setup({
follow_cwd = true,
})
Note
If follow_cwd = false
the session name is stored upon loading under the global variable vim.g.persisting_session
. This variable can be manually adjusted if changes to the session name are needed. Alternatively, if follow_cwd = true
then vim.g.persisting_session = nil
.
You may specify a table of directories for which the plugin will autosave and/or autoload from. For example:
require("persisted").setup({
allowed_dirs = {
"~/.dotfiles",
"~/Code",
},
})
Specifying ~/Code
will autosave and autoload from that directory as well as all its sub-directories.
Note
If allowed_dirs
is left at its default value and autosave
and/or autoload
are set to true
, then the plugin will autoload/autosave from any directory
You may specify a table of directories for which the plugin will never autosave and autoload from. For example:
require("persisted").setup({
ignored_dirs = {
"~/.config",
"~/.local/nvim"
},
})
Specifying ~/.config
will prevent any autosaving and autoloading from that directory as well as all its sub-directories.
You can also specify exact directory matches to ignore. In this case, unlike the default behavior which ignores all children of the ignored directory, this will ignore only the specified child. For example:
require("persisted").setup({
ignored_dirs = {
"~/.config",
"~/.local/nvim",
{ "/", exact = true },
{ "/tmp", exact = true }
},
})
In this setup, ~/.config
and ~/.local/nvim
are still going to behave in their default setting (ignoring all listed directory and its children), however /
and /tmp
will only ignore those directories exactly.
The plugin fires events at various points during its lifecycle:
PersistedLoadPre
- For before a session is loadedPersistedLoadPost
- For after a session is loadedPersistedTelescopeLoadPre
- For before a session is loaded via TelescopePersistedTelescopeLoadPost
- For after a session is loaded via TelescopePersistedSavePre
- For before a session is savedPersistedSavePost
- For after a session is savedPersistedDeletePre
- For before a session is deletedPersistedDeletePost
- For after a session is deletedPersistedStateChange
- For when a session is started or stoppedPersistedToggled
- For when a session is toggled
These events can be consumed anywhere within your configuration by utilising the vim.api.nvim_create_autocmd
function.
A commonly requested example is to use the Telescope extension to load a session, saving the current session before clearing all of the open buffers:
local group = vim.api.nvim_create_augroup("PersistedHooks", {})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "PersistedTelescopeLoadPre",
group = group,
callback = function(session)
-- Save the currently loaded session using a global variable
require("persisted").save({ session = vim.g.persisted_loaded_session })
-- Delete all of the open buffers
vim.api.nvim_input("<ESC>:%bd!<CR>")
end,
})
When certain events are fired, session data is made available for the user to consume, for example:
{
branch = "main",
dir_path = "Code/Neovim/persisted.nvim",
file_path = "/Users/Oli/.local/share/nvim/sessions/%Users%Oli%Code%Neovim%persisted.nvim@@main.vim",
name = "Code/Neovim/persisted.nvim@@main",
}
To consume this data, use the session.data
table in your autocmd:
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "PersistedLoadPost",
group = group,
callback = function(session)
print(session.data.branch)
end,
})
Note
This data is available for the PersistedLoad
, PersistedDelete
and PersistedTelescope
events