3 min read

ToyChest.nvim, a Neovim session manager

This post documents a small Lua plugin I wrote to enhance the quality of life when working with sessions in Neovim.
ToyChest.nvim, a Neovim session manager
高美溼地 (Gaomei Wetlands)
GitHub - limxingzhi/toychest.nvim: A barely opinionated session manager for nvim.
A barely opinionated session manager for nvim. Contribute to limxingzhi/toychest.nvim development by creating an account on GitHub.

ToyChest.nvim is a Lua wrapper around the vim sessions commands

Vim sessions, what are they

Vim sessions are great. They save the current context of your workspace in a small text file so you can come back to it later. Things like your opened buffers, tabs and windows, code folding, etc., are saved so you can pop back into the same flow later on. But the usage is verbose.

To save a session, you have to do :mks or :mks!. By default, it saves to the current directory, so you either need to .gitignore or save it to a home path. A realistic usage looks something like:

:mks! ~/.vsess/dialog-24

saves the session for 'dialog-24' (where 24 might be a jira ticket) to your home directory at .vsess

And to retrieve it, you can do either on the CLI:

$ nvim -S ~/.vsess/dialog-24

run Neovim with the -S flag

Or do it within Neovim with the source command:

:source ~/.vsess/dialog-24

you know what this does at this point

Either way, that is a lot of things to type.

Making a Lua wrapper

To make things easier for me, I wrote a Lua wrapper as a plugin, ToyChest.nvim.

-- for lazy.nvim
{
  "limxingzhi/toychest.nvim",
  config = function()
    require("toychest").setup()
  end
},

Installing my session plugin via lazy.nvim

The usage is simple, you just do :Sesw dialog-24 to write the current session into ~/.vim_sessions/dialog-24 and :Sesr dialog-24 to read the session. They are just wrappers around :mks and :source, but they solve all of the annoyances I have with the original commands. They automatically save in a dedicated folder in my home path, so I don't need to tiptoe around my working repo. They have autocomplete the files with vim.fn.glob.

They are exposed via a Lua interface, so you can programmatically trigger it via keybinds or build integrations with your workflow.

:Sesr dialog-24
:Sesw dialog-24

reading and writing from 'dialog-24' session with ToyChest.nvim

You can also interact with it with Lua:

local tc = require('toychest')

tc.save_session('debugging-dialog')
tc.restore_session('debugging-dialog')

interacting with Lua

Here's a sample config that I built with ChatGPT that retrieves and stores sessions based on your branch name, attached to a keybind of <leader>vsw:

{
  "limxingzhi/toychest.nvim",
  config = function()
    require("toychest").setup()

    local function assert_is_repo()
      local isGitRepo = vim.fn.system("git rev-parse --is-inside-work-tree 2>/dev/null"):gsub("%s+", "")
      if isGitRepo ~= "true" then
        error("The current directory is not a Git repository.")
        return
      end
    end

    local function get_name()
      assert_is_repo()
      local currentDir = vim.fn.getcwd()
      local folderName = vim.fn.fnamemodify(currentDir, ":t")
      local branchName = vim.fn.system("git rev-parse --abbrev-ref HEAD 2>/dev/null"):gsub("%s+", "")
      return folderName .. '__' .. branchName
    end

    vim.keymap.set({ "n" }, "<leader>vsw", function()
      require("toychest").save_session(get_name())
    end)

    -- "vim session read" : restore current session based on branch name
    vim.keymap.set({ "n" }, "<leader>vsr", function()
      require("toychest").restore_session(get_name())
    end)
  end
},

save and restore sessions with names based on the current directory and git branch

You can also hook this into the VimLeavePre hook.

Additional features with fzf

If you are not familiar with fzf, its a fuzzy finder that, well, does all sorts of fuzzy finder stuff for you on the command line. I made a simple bash function to quickly launch Neovim instances.

VIM_SESS_DIR="$HOME/.vim_sessions"

# quick function to open neovim with specific session "open vim session"
ovss() {
  if [[ $# -eq 1 ]] then
    local SESS="$VIM_SESS_DIR/$1"
    if [[ -f $SESS ]] then
      nvim -S $SESS
    else
      echo Invalid Vim session: $SESS
    fi
  else
    # use fzf to search for files within the sessions directory
    local SESS=$(find $VIM_SESS_DIR -type f -print | fzf)
    if [[ -n "$SESS" ]] then
      nvim -S "$SESS"
    else
      echo Invalid Vim session
    fi
  fi
}

small bash function I wrote to fuzzy find a Neovim session to launch into

It lists every file in the ~/.vim_sessions directory, fuzzy finds one and launch it:

$ nvim -S session-66

Meanwhile, I currently work at a bank where I use VSCode and IntelliJ on over a Windows VMs for most of my work.