セッション復元機能付き再起動コマンドの作成
20 days前に投稿
if vim.fn.exists(':restart') >= 1 then local M = {} -- 保存先(Neovimの state ディレクトリ配下) local base = vim.fn.stdpath("state") .. "/autorestore" local session = base .. "/last_session.vim" local flag = base .. "/restore.flag" local function ensure_dir() if vim.fn.isdirectory(base) == 0 then vim.fn.mkdir(base, "p") end end local function file_exists(path) return vim.uv.fs_stat(path) ~= nil end local function rm(path) -- 存在しない場合のエラーは無視したいので pcall pcall(vim.uv.fs_unlink, path) end -- -------------------------------------- -- 1) 再起動前に状態を保存してフラグを立てる function M.save_for_restart() ensure_dir() -- セッションに必要なオプション(端末バッファも復元したい場合は 'terminal' を入れる) vim.opt.sessionoptions:append("terminal") vim.opt.sessionoptions:append("buffers") vim.opt.sessionoptions:append("resize") vim.opt.sessionoptions:append("tabpages") -- セッション + shada 保存 vim.cmd("silent! mksession! " .. vim.fn.fnameescape(session)) vim.cmd("silent! wshada!") -- フラグ作成(軽いメタ情報) local cwd = (vim.uv.cwd and vim.uv.cwd()) or vim.fn.getcwd() or "" vim.fn.writefile({ ("cwd=%s"):format(cwd), ("time=%s"):format(os.date("!%Y-%m-%dT%H:%M:%SZ")), ("nvim=%s"):format(vim.v.progpath or vim.v.progname or "nvim"), }, flag) if vim.fn.exists(":restart") == 2 then vim.notify("State saved. Restarting Neovim…", vim.log.levels.INFO) vim.cmd('silent! wall') vim.defer_fn(function() vim.cmd("silent! restart") end, 1000) else vim.notify("State saved. Quit and start Neovim again to auto-restore.", vim.log.levels.INFO) end end -- 2) 起動時に自動で復元 function M.maybe_restore_on_start() if not (file_exists(flag) and file_exists(session)) then return end -- LSP 警告回避のため、関数ラップで渡す pcall(function() vim.cmd("silent! rshada!") end) pcall(function() vim.cmd("silent! source " .. vim.fn.fnameescape(session)) end) -- 片付け rm(flag) rm(session) vim.schedule(function() vim.notify("Restored previous session.", vim.log.levels.INFO) end) end vim.api.nvim_create_user_command("RestartWithRestore", function() M.save_for_restart() end, { desc = "Save session+shada and restart (or prompt manual restart)" }) vim.api.nvim_create_autocmd("VimEnter", { callback = function() vim.schedule(M.maybe_restore_on_start) end, }) return M end
設定の概要
Neovim v0.12 で :restart コマンドが導入されましたが、このコマンド単体では再起動前の状態を復元する機能はありません。そこで、:restart コマンドの前後にセッション保存・自動復元の処理を追加し、Neovim を再起動しても作業状態をなるべくそのまま戻せるようにしています。
この設定を入れると、:RestartWithRestore というユーザーコマンドが使えるようになります。
実装の解説
実行すると、まず stdpath("state") 配下に専用ディレクトリを作成し、現在のセッションを mksession! で保存します。あわせて wshada! も実行するため、レジスタや履歴など Shada に保存される情報も明示的に書き出します。
セッション保存時には、sessionoptions に terminal、buffers、resize、tabpages を追加しています。そのため、通常のバッファだけでなく、タブページ構成やウィンドウサイズ、端末バッファも復元対象に含めることを意図しています。
保存が終わると、v0.12 以降で :restart が利用できる環境では :wall で変更済みバッファを保存したうえで、少し待ってから :restart を実行します。再起動後は VimEnter のタイミングでフラグファイルとセッションファイルの有無を確認し、前回保存した Shada とセッションを読み込んで、直前の作業状態を復元します。
また、:restart が存在しない環境では、セッションと Shada の保存だけを行い、「Neovim を終了して起動し直せば自動復元できる」というフォールバック動作になります。コード全体も vim.fn.exists(':restart') >= 1 で囲まれているため、v0.12 以前の環境でもエラーになりません。
コメントを投稿するにはログインが必要です