persisted.nvim

repository·main·Indexed 19 days ago

https://github.com/olimorris/persisted.nvim

A Neovim plugin for managing workspace sessions. It enables users to save, restore, and switch between sessions with built-in support for Git branches and a Telescope extension for session picking. Features include automatic starting and loading based on current working directory, configurable allowed and ignored directories, and custom user events for integration with other workflows.

Tokens
2.9K
Snippets
9
Records
12
Agent score
19%

What's inside persisted.nvim

  1. How to use allowed_dirs and ignored_dirs

    main

    You can control where persisted.nvim automatically starts or loads sessions using allowed_dirs and ignored_dirs.

    Allowed Directories: Specifying a directory in allowed_dirs will cause the plugin to start and autoload from that directory and all its sub-directories.

    allowed_dirs = {
      "~/.dotfiles",
      "~/Code",
    }

    Ignored Directories: Directories in ignored_dirs will never be used for starting or autoloading. By default, this ignores the directory and all its children. To ignore only an exact directory match, use the { "path", exact = true } syntax.

    ignored_dirs = {
      "~/.config",
      "~/.local/nvim",
      { "/", exact = true },
      { "/tmp", exact = true }
    }
  2. Extend persisted.nvim with custom autoloading logic

    main

    You can implement custom logic to decide when a session should be automatically loaded. For example, you can use a VimEnter autocmd to check if Neovim was started with specific arguments or if it's a directory, and then call persisted.autoload({ force = true }) accordingly.

    local persisted = require("persisted")
    vim.api.nvim_create_autocmd("VimEnter", {
      nested = true,
      callback = function()
        if vim.g.started_with_stdin then
          return
        end
    
        local forceload = false
        if vim.fn.argc() == 0 then
          forceload = true
        elseif vim.fn.argc() == 1 then
          local dir = vim.fn.expand(vim.fn.argv(0))
          if dir == '.' then
            dir = vim.fn.getcwd()
          end
    
          if vim.fn.isdirectory(dir) ~= 0 then
            forceload = true
          end
        end
    
        persisted.autoload({ force = forceload })
      end,
    })
  3. Install the Telescope extension for persisted.nvim

    main

    To manage sessions via Telescope, you must load the extension in your Telescope configuration:

    require("telescope").load_extension("persisted")

    You can also customize the Telescope layout specifically for the persisted extension:

    require('telescope').setup({
      extensions = {
        persisted = {
          layout_config = { width = 0.55, height = 0.55 }
        }
      }
    })
  4. Install persisted.nvim

    main

    Install and configure persisted.nvim using your preferred Neovim package manager. For lazy.nvim, it is recommended to use the BufReadPre event to ensure the plugin loads only when a buffer is loaded.

    -- Lazy.nvim
    {
      "olimorris/persisted.nvim",
      event = "BufReadPre",
      opts = {
        -- Your config goes here ...
      },
    }
  5. Manage sessions with the Telescope extension

    main

    Open the session picker using :Telescope persisted. While navigating the picker, use the following default mappings:

    • <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
  6. Use should_save to filter session saving

    main

    The should_save option in the setup function allows you to define custom criteria for when a session should be persisted. You can use this to:

    1. Check buffer count: Only save if a minimum number of valid buffers are present.
    2. Restrict directories: Only save if the current working directory matches an allowed list using utils.dirs_match.
    -- Example: Only save if at least one valid buffer is present
    persisted.setup({
      should_save = function()
        local bufs = vim.tbl_filter(function(b) 
          if vim.bo[b].buftype ~= "" or vim.tbl_contains({ "gitcommit", "gitrebase", "jj" }, vim.bo[b].filetype) then
            return false
          end
          return vim.api.nvim_buf_get_name(b) ~= ""
        end, vim.api.nvim_list_bufs())
        return #bufs >= 1
      end,
    })
    
    -- Example: Only save in specific directories
    local utils = require("persisted.utils")
    local allowed_dirs = {"~/code", "~/notes/api"}
    persisted.setup({
      should_save = function()
        return utils.dirs_match(vim.fn.getcwd(), allowed_dirs)
      end,
    })
  7. Configure persisted.nvim options

    main

    The plugin is configured via the setup() function. Key configuration options include:

    • autostart (bool): Automatically start the plugin on load? (Default: true)
    • autoload (bool): Automatically load the session for the cwd on Neovim startup? (Default: false)
    • use_git_branch (bool): Include the git branch in the session file name? (Default: false)
    • follow_cwd (bool): Change the session file to match any change in the cwd? (Default: true)
    • save_dir (string): Directory where session files are saved. Defaults to vim.fn.expand(vim.fn.stdpath("data") .. "/sessions/").
    • should_save (function): A function returning a boolean to determine if a session should be saved.
    • on_autoload_no_session (function): Callback run when autoload = true but no session exists.
    • allowed_dirs (table): Directories from which the plugin will start and autoload.
    • ignored_dirs (table): Directories that are ignored for starting and autoloading.
    • telescope (table): Configuration for Telescope mappings and icons.
    require("persisted").setup({
      autostart = true,
      use_git_branch = true,
      autoload = true,
      -- ... other options
    })
  8. Fix Git branch detection in sub-directories

    main

    If you invoke Neovim from a sub-directory, the default git branch detection might fail. You can override persisted.branch with a custom function that uses git branch --show-current to ensure the correct branch is used for session naming.

    {
      "olimorris/persisted.nvim",
      lazy = false,
      opts = {
        autoload = true,
        autosave = true,
        use_git_branch = true,
      },
      config = function(_, opts)
        local persisted = require("persisted")
        persisted.branch = function()
          local branch = vim.fn.systemlist("git branch --show-current")[1]
          return vim.v.shell_error == 0 and branch or nil
        end
        persisted.setup(opts)
      end,
    }
  9. Ignore specific Git branches for sessions

    main

    To prevent certain branches (e.g., feature or bugfix branches) from being saved as sessions, you can check the current branch against an ignored list before calling persisted.start() in your configuration.

    {
      "olimorris/persisted.nvim",
      lazy = false,
      opts = {
        autostart = true,
        use_git_branch = true,
      },
      config = function(_, opts)
        local persisted = require("persisted")
        local utils = require("persisted.utils")
        local ignored_branches = {
          "feature_branch",
          "bug_fix_branch"
        }
    
        persisted.setup(opts)
    
        -- Only start the plugin if the branch isn't in the ignored list
        if not utils.in_table(persisted.branch(), ignored_branches) then
          persisted.start()
        end
      end
    }
  10. Listen to the PersistedDeletePost event

    main

    You can create an autocmd for the User event with the pattern PersistedDeletePost to perform actions (like showing a notification) whenever a session is deleted. The event.data.path field contains the path of the deleted session.

    local persisted = require("persisted").setup()
    
    vim.api.nvim_create_autocmd("User", {
      pattern = "PersistedDeletePost",
      callback = function(event)
        vim.notify("Session `'\" .. event.data.path .. "\" deleted")
      end,
    })
  11. Extend persisted.nvim with User Events

    main

    The plugin fires several custom events that you can hook into using vim.api.nvim_create_autocmd. This allows for tight integration with other plugins or custom workflows.

    Available Events:

    • PersistedDeletePre / PersistedDeletePost - Before/after a session is deleted
    • PersistedLoadPre / PersistedLoadPost - Before/after a session is loaded
    • PersistedSavePre / PersistedSavePost - Before/after a session is saved
    • PersistedSelectPre / PersistedSelectPost - Before/after a session is selected via :SessionSelect
    • PersistedStart - When a session has started
    • PersistedStop - When a session has stopped
    • PersistedToggle - When a session is toggled
    • PersistedTelescopeLoadPre / PersistedTelescopeLoadPost - Before/after a session is loaded via Telescope

    Example: Save current session before loading a new one via Telescope

    vim.api.nvim_create_autocmd("User", {
      pattern = "PersistedTelescopeLoadPre",
      callback = function(session)
        -- Save the currently loaded session passing in the path to the current session
        require("persisted").save({ session = vim.g.persisted_loaded_session })
    
        -- Delete all of the open buffers
        vim.api.nvim_input("<ESC>:%bd!<CR>")
      end,
    })
    vim.api.nvim_create_autocmd("User", {
      pattern = "PersistedTelescopeLoadPre",
      callback = function(session)
        require("persisted").save({ session = vim.g.persisted_loaded_session })
        vim.api.nvim_input("<ESC>:%bd!<CR>")
      end,
    })
  12. Use persisted.nvim commands

    main

    The plugin provides several commands to manage sessions manually:

    • :Persisted toggle - Determines whether to load, start or stop a session
    • :Persisted start - Start recording a session (useful if autostart = false)
    • :Persisted stop - Stop recording a session
    • :Persisted save - Save the current session
    • :Persisted select - Load a session from a list (alternative to Telescope)
    • :Persisted load - Load the session for the current directory and current branch (if use_git_branch = true)
    • :Persisted load_last - Load the most recent session
    • :Persisted delete - Delete a session from a list
    • :Persisted delete_current - Delete the current session