/persisted.nvim

💾 Simple session management for Neovim with git branching, autoloading and Telescope support

Primary LanguageLuaMIT LicenseMIT

Persisted.nvim

Persisted.nvim

Persisted.nvim is a simple lua plugin for working with sessions in Neovim
Forked from Persistence.nvim as active development had stopped

✨ Features

  • Automatically saves the active session under .local/share/nvim/sessions on exiting Neovim
  • Supports sessions across multiple git branches
  • Supports autosaving and autoloading of sessions with allowed/ignored directories
  • Simple API to save/stop/restore/delete/list the current session(s)
  • Custom events which users can hook into for greater integration
  • Telescope extension to work with saved sessions

âš¡ Requirements

  • Neovim >= 0.8.0

📦 Installation

Install the plugin with your preferred package manager:

Lazy.nvim

-- Lua
{
  "olimorris/persisted.nvim",
  config = true
}

Packer

-- Lua
use({
  "olimorris/persisted.nvim",
  config = function()
    require("persisted").setup()
  end,
})

Vim Plug

" 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.

Telescope extension

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

🚀 Usage

Default commands

The plugin comes with a number of commands:

  • :SessionToggle - Determines whether to load, start or stop a session
  • :SessionStart - Start recording a session. Useful if autosave = false
  • :SessionStop - Stop recording a session
  • :SessionSave - Save the current session
  • :SessionLoad - Load the session for the current directory and current branch (if git_use_branch = true)
  • :SessionLoadLast - Load the most recent session
  • :SessionLoadFromFile - Load a session from a given path
  • :SessionDelete - Delete the current session

Telescope

The Telescope extension may be opened via :Telescope persisted.

Once opened, the available keymaps are:

  • <CR> - Source the session file
  • <C-d> - Delete the session file

Statuslines

The plugin sets a global variable, vim.g.persisting, which is set to true when a session is started and false when it is stopped. Also, the plugin offers a PersistedStateChange event that can be hooked into via an autocmd (see the events/callbacks section).

🔧 Configuration

Defaults

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 the git enabled repository
  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 = { -- options for the telescope extension
    reset_prompt_after_deletion = true, -- whether to reset prompt after session deleted
  },
})

What is saved in the session?

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,globals,tabpages,winpos,winsize"

Session save location

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

Git branching

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

Note: If git branching is enabled on a non git enabled repo, then main will be used as the default branch

If you switch branches in a repository, the plugin will try to load a session which corresponds to that branch. If it can't find one, then it will load the session from the main branch.

Autosaving

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.

Autoloading

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 a user opens Neovim with arguments. For example: nvim some_file.rb

Following current working directory

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.

Allowed directories

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

Ignored directories

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.

Events / Callbacks

The plugin fires events at various points during its lifecycle which users can hook into:

  • PersistedLoadPre - For before a session is loaded
  • PersistedLoadPost - For after a session is loaded
  • PersistedTelescopeLoadPre - For before a session is loaded via Telescope
  • PersistedTelescopeLoadPost - For after a session is loaded via Telescope
  • PersistedSavePre - For before a session is saved
  • PersistedSavePost - For after a session is saved
  • PersistedDeletePre - For before a session is deleted
  • PersistedDeletePost - For after a session is deleted
  • PersistedStateChange - For when a session is started or stopped

For example, to ensure that the excellent minimap plugin is not saved into a session, an autocmd can be created to hook into the PersistedSavePre event:

local group = vim.api.nvim_create_augroup("PersistedHooks", {})

vim.api.nvim_create_autocmd({ "User" }, {
  pattern = "PersistedSavePre",
  group = group,
  callback = function()
    pcall(vim.cmd, "bw minimap")
  end,
})

Session data is also made available to the callbacks:

local group = vim.api.nvim_create_augroup("PersistedHooks", {})

vim.api.nvim_create_autocmd({ "User" }, {
  pattern = "PersistedTelescopeLoadPre",
  group = group,
  callback = function(session)
    print(session.data.branch) -- Print the session's branch
  end,
})

The session data available differs depending on the events that are hooked into. For non-telescope events, only the session's full path is available (via session.data). However for telescope events, the branch, name, file_path and dir_path are available.

Telescope extension

Telescope

The plugin contains an extension for telescope.nvim which allows the user to list all of the saved session files and source them via :Telescope persisted.

📃 License

MIT