Discard missing files from saved sessions

Sanitize nonexistent unmodified file buffers and stale argument-list entries after session load and before automatic save.
This commit is contained in:
Ray Elliott 2026-10-28 19:38:17 +00:00
commit aedc1d7b86
3 changed files with 62 additions and 6 deletions

View file

@ -104,6 +104,7 @@ vim.api.nvim_create_autocmd("FileType", {
-- Session management: auto-load on startup, auto-save on exit (only if Session.vim exists)
local session_aug = vim.api.nvim_create_augroup("SessionManagement", { clear = true })
local sanitize_session_files
-- Auto-load Session.vim if it exists in the current directory
vim.api.nvim_create_autocmd("VimEnter", {
@ -126,6 +127,8 @@ vim.api.nvim_create_autocmd("SessionLoadPost", {
group = session_aug,
pattern = "*",
callback = function()
sanitize_session_files()
-- Trigger BufReadPost for all loaded buffers to ensure Treesitter/LSP attach
vim.schedule(function()
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
@ -142,13 +145,17 @@ local function is_netrw_session_buffer(buf)
and (vim.bo[buf].filetype == "netrw" or vim.api.nvim_buf_get_name(buf):match("NetrwTreeListing$") ~= nil)
end
local function session_fallback_buffer()
local function session_fallback_buffer(excluded)
excluded = excluded or {}
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
local name = vim.api.nvim_buf_get_name(buf)
if
vim.api.nvim_buf_is_valid(buf)
and not excluded[buf]
and vim.bo[buf].buflisted
and vim.bo[buf].buftype == ""
and vim.api.nvim_buf_get_name(buf) ~= ""
and name ~= ""
and vim.uv.fs_stat(name) ~= nil
and not is_netrw_session_buffer(buf)
then
return buf
@ -158,6 +165,55 @@ local function session_fallback_buffer()
return vim.api.nvim_create_buf(true, false)
end
local function is_local_file_path(path)
return path ~= "" and path:match("^%a[%w+.-]*://") == nil
end
sanitize_session_files = function()
local missing = {}
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_valid(buf) and vim.bo[buf].buftype == "" then
local name = vim.api.nvim_buf_get_name(buf)
if is_local_file_path(name) and vim.uv.fs_stat(name) == nil and not vim.bo[buf].modified then
missing[buf] = true
end
end
end
if next(missing) then
local fallback
for _, win in ipairs(vim.api.nvim_list_wins()) do
local buf = vim.api.nvim_win_get_buf(win)
if missing[buf] then
fallback = fallback or session_fallback_buffer(missing)
vim.api.nvim_win_set_buf(win, fallback)
end
end
for buf in pairs(missing) do
if vim.api.nvim_buf_is_valid(buf) then
pcall(vim.api.nvim_buf_delete, buf, { force = true })
end
end
end
local args = vim.fn.argv()
local existing = {}
for _, arg in ipairs(args) do
local path = is_local_file_path(arg) and vim.fn.fnamemodify(arg, ":p") or nil
if not path or vim.uv.fs_stat(path) ~= nil then
table.insert(existing, arg)
end
end
if #existing ~= #args then
vim.cmd("%argdelete")
for _, arg in ipairs(existing) do
vim.cmd.argadd({ args = { arg } })
end
end
end
local function close_session_tab(tab)
if vim.api.nvim_tabpage_close then
pcall(vim.api.nvim_tabpage_close, tab, true)
@ -191,10 +247,7 @@ local function omit_netrw_from_session()
if vim.api.nvim_tabpage_is_valid(tab) then
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
if
vim.api.nvim_win_is_valid(win)
and is_netrw_session_buffer(vim.api.nvim_win_get_buf(win))
then
if vim.api.nvim_win_is_valid(win) and is_netrw_session_buffer(vim.api.nvim_win_get_buf(win)) then
if #vim.api.nvim_tabpage_list_wins(tab) > 1 then
pcall(vim.api.nvim_win_close, win, true)
elseif #vim.api.nvim_list_tabpages() > 1 then
@ -217,6 +270,7 @@ vim.api.nvim_create_autocmd("VimLeavePre", {
-- Only save if Session.vim exists (user manually created it)
if vim.fn.filereadable("Session.vim") == 1 then
omit_netrw_from_session()
sanitize_session_files()
vim.cmd("mksession! Session.vim")
end
end,