🐱

vimを終了した時の状態に復元する

に公開

はじめに

環境はneovimかつ設定をluaで書く想定です。vimの機能なのでvimrc用に書き替えると動作するはずですが未検証です

セッションとは

sessionとは作業を中断するためにvimを終了させたとき、ファイルリスト、ウィンドウレイアウト、グローバル変数、オプションなど終了する前に編集していた状態を保持しておく機能です
これによりそのセッションを読み直すことで開いていたバッファや分割していたウィンドウの状態などを復元することが可能です

仕組み

仕組みはシンプルでhoge.vimに現在編集しているvimのメタデータを書き込んでおいて、ロードするとそのメタデータから復元します

sessionの使い方

最もベーシックな使い方は

:mksession vimbook.vim

のようにするとセッションが保存され

:source vimbook.vim

とするとそのセッション情報を読み復元します
またvimを起動するときにコマンドラインでセッションを呼び出すことも可能です

nvim -S vimbook.vim

使用例

正直セッションコマンドを毎回打つのはだるいし、vimを閉じてから復元したいなと思うことも多いです。そのためvimを終了したときに自動で保存してくれると嬉しい

簡単な使い方

以下のようにするとvimを終了したタイミングで自動でセッションを保存してくれます

vim.api.nvim_create_autocmd("VimLeavePre", {
  pattern = "*",
  command = "mksession! ~/.config/nvim/session.vim", -- ここではnvim設定配下にsession.vimを作成しています
})

また呼び出しはキーマップを作成しておくと便利です

vim.keymap.set("n", "<Leader>sl", '<Cmd>source ~/.config/nvim/session.vim<CR>', { noremap = true, desc = "セッションの復帰" })

ディレクトリごとでセッション管理

例えば複数のプロジェクトを同時に行っていたり、フロントエンドとバックエンドそれぞれのディレクトリ配下でセッションを持ちたいなど、それぞれの場所でセッション管理したいことがあると思います
その時はsession/project_dir/session.vimのように管理すると可能です

-- 関数などを入れるオブジェクト
local M = {} 

-- vim設定ディレクトリの配下のsessionsディレクトリ。~/.config/nvim/sessionsのように
local session_base = vim.fn.stdpath('config') .. '/sessions' 

-- 起動時のカレントディレクトリを記録
local initial_cwd = vim.fn.getcwd()

-- 起動時のディレクトリからセッションファイルパスを生成
function M.get_session_path()
  -- パスの / を _ に変換してファイル名として使える形に
  local project_name = initial_cwd:gsub('/', '_'):gsub('^_', '')
  local session_dir = session_base .. '/' .. project_name
  vim.fn.mkdir(session_dir, 'p')
  return session_dir .. '/session.vim'
end

-- セッションの保存
function M.save()
  local session_path = M.get_session_path()
  vim.api.nvim_command('mksession! ' .. session_path)
  print('Session saved: ' .. session_path)
end

-- セッションの復帰
function M.load()
  local session_path = M.get_session_path()
  if vim.fn.filereadable(session_path) == 1 then
    vim.api.nvim_command('source ' .. session_path)
  else
    print('Session not found: ' .. session_path)
  end
end

-- vimを閉じるときセッションを保存
vim.api.nvim_create_autocmd("VimLeavePre", {
  pattern = "*",
  callback = function()
    M.save()
  end,
})

-- ファイル分割している場合、Mを返却すると取り回しがいい
return M

そして先ほどと同様に復元のキーマップを作成しておくと便利

-- 呼び出しは適宜変更してください
local session = require('session')

vim.keymap.set("n", "<Leader>sl", session.load, { noremap = true, desc = "セッションの復帰" })

まとめ

個人的にsessionは地味ですがかなり便利な機能で、ないとストレスというレベルです
今回紹介した以外にもマーク位置の保存や1つのウィンドだけ保存などセッション回りの機能で便利なものはあります。適宜ドキュメントを参考にしながら設定してあげるとよいかと思います
ではよいvimライフを

参考

Discussion