diff --git a/lua/auto-session/autocmds.lua b/lua/auto-session/autocmds.lua index 1a656cd..5355769 100644 --- a/lua/auto-session/autocmds.lua +++ b/lua/auto-session/autocmds.lua @@ -6,7 +6,7 @@ local M = {} ---@param config table auto session config ---@param AutoSession table auto session instance M.setup_autocmds = function(config, AutoSession) - if not config.cwd_change_handling or vim.tbl_isempty(config.cwd_change_handling or {}) then + if not config.cwd_change_handling or not config.cwd_change_handling.restore_upcoming_session then Lib.logger.debug "cwd_change_handling is disabled, skipping setting DirChangedPre and DirChanged autocmd handling" return end @@ -30,10 +30,18 @@ M.setup_autocmds = function(config, AutoSession) return end + if AutoSession.restore_in_progress then + Lib.logger.debug "DirChangedPre: restore_in_progress is true, ignoring this event" + return + end + AutoSession.AutoSaveSession() -- Clear all buffers and jumps after session save so session doesn't blead over to next session. + -- NOTE: If the code in restore_selected_session that tries to keep matching buftypes open across + -- sessions actually works, we should also have that logic here. vim.cmd "%bd!" + vim.cmd "clearjumps" if type(conf.pre_cwd_changed_hook) == "function" then @@ -56,6 +64,11 @@ M.setup_autocmds = function(config, AutoSession) return end + if AutoSession.restore_in_progress then + Lib.logger.debug "DirChanged: restore_in_progress is true, ignoring this event" + return + end + -- all buffers should've been deleted in `DirChangedPre`, something probably went wrong if Lib.has_open_buffers() then Lib.logger.debug "Cancelling session restore" diff --git a/lua/auto-session/init.lua b/lua/auto-session/init.lua index a081c57..ddbdbb4 100644 --- a/lua/auto-session/init.lua +++ b/lua/auto-session/init.lua @@ -180,6 +180,7 @@ end -- get the current git branch name, if any, and only if configured to do so local function get_branch_name() if AutoSession.conf.auto_session_use_git_branch then + -- WARN: this assumes you want the branch of the cwd local out = vim.fn.systemlist "git rev-parse --abbrev-ref HEAD" if vim.v.shell_error ~= 0 then Lib.logger.debug(string.format("git failed with: %s", table.concat(out, "\n"))) @@ -479,11 +480,14 @@ function AutoSession.get_session_files() end local entries = vim.fn.readdir(sessions_dir, function(item) - return vim.fn.isdirectory(item) == 0 and not string.find(item, "x.vim$") + return Lib.is_session_file(sessions_dir, item) end) + -- Get cross platform path separator + local path_separator = Lib.get_path_separator() + return vim.tbl_map(function(entry) - return { display_name = AutoSession.format_file_name(entry), path = entry } + return { display_name = AutoSession.format_file_name(entry), path = sessions_dir .. path_separator .. entry } end, entries) end @@ -509,10 +513,7 @@ local function handle_autosession_command(data) local files = AutoSession.get_session_files() if data.args:match "search" then open_picker(files, "Select a session:", function(choice) - -- Change dir to selected session path, the DirChangePre and DirChange events will take care of the rest - -- BUG: The above is only true if cwd_change_handling is true which means sessions - -- won't be restored if cwd_change_handling is false - vim.fn.chdir(choice.display_name) + AutoSession.restore_selected_session(choice.path) end) elseif data.args:match "delete" then open_picker(files, "Delete a session:", function(choice) @@ -521,6 +522,52 @@ local function handle_autosession_command(data) end end +-- Handler for when a session is picked from the UI, either via Telescope or via AutoSession.select_session +-- We'll load the selected session file, setting restore_in_progress so DirChangedPre/DirChanged won't +-- also try to load the session when the directory is changed +function AutoSession.restore_selected_session(session_filename) + Lib.logger.debug("[restore_selected_session]: filename: " .. session_filename) + + AutoSession.AutoSaveSession() + + -- NOTE: + -- In theory, this is supposed to keep open buffers that are in buftypes_to_ignore. However, even if + -- we keep them open here, they'll be cleared when we source the session file sp I don't think + -- this code does anything. It also interrupts session loading if the buffer replaced is loaded + -- by another process. So, I've replaced it with %bd! which is what cwd_change_handling does. + -- This code and block should be removed when it's confirmed that no users are using it effectively + -- + -- local buffers = vim.api.nvim_list_bufs() + -- for _, bufn in pairs(buffers) do + -- if + -- not vim.tbl_contains( + -- AutoSession.conf.session_lens.buftypes_to_ignore, + -- vim.api.nvim_get_option_value("buftype", { buf = bufn }) + -- ) + -- then + -- vim.cmd("silent bwipeout!" .. bufn) + -- else + -- Lib.logger.debug "[restore_selected_session] Not closing buffer because it matches buftypes_to_ignore" + -- end + -- end + + vim.cmd "%bd!" + + -- Would it be better to always clear jumps in RestoreSession? + vim.cmd "clearjumps" + + -- Set restore_in_progress so cwd_change_handling won't also try to load the session when the directory is changed + -- And use a pcall to make sure we unset the flag whether loading was successful or not + AutoSession.restore_in_progress = true + local success, result = pcall(AutoSession.RestoreSession, session_filename) + AutoSession.restore_in_progress = false + + if not success or not result then + Lib.logger.info("Could not load session for filename: " .. session_filename) + return + end +end + vim.api.nvim_create_user_command("Autosession", handle_autosession_command, { nargs = 1 }) -- local function write_to_session_control(session_file_name) @@ -767,6 +814,7 @@ Disabling auto save. Please check for errors in your config. Error: elseif session_file then Lib.logger.debug "Using session FILE" local escaped_file = session_file:gsub("%%", "\\%%") + Lib.logger.debug("Using session FILE: " .. escaped_file) if Lib.is_readable(escaped_file) then Lib.logger.debug "isReadable, calling restore" RESTORED_WITH = restore(escaped_file) diff --git a/lua/auto-session/lib.lua b/lua/auto-session/lib.lua index c2d7c2c..df9a2f0 100644 --- a/lua/auto-session/lib.lua +++ b/lua/auto-session/lib.lua @@ -203,4 +203,37 @@ function Lib.close_unsupported_windows() end end +function Lib.get_path_separator() + -- Get cross platform path separator + return package.config:sub(1, 1) +end + +-- When Neovim makes a session file, it may save an additional x.vim file +-- with custom user commands. This function returns false if it's one of those files +function Lib.is_session_file(session_dir, file_path) + -- if it's a directory, don't include + if vim.fn.isdirectory(file_path) ~= 0 then + return false + end + + -- if it's a file that doesn't end in x.vim, include + if not string.find(file_path, "x.vim$") then + return true + end + + local path_separator = Lib.get_path_separator() + + -- the file ends in x.vim, make sure it has SessionLoad on the first line + local file = io.open(session_dir .. path_separator .. file_path, "r") + if not file then + Lib.logger.debug("Could not open file: " .. session_dir .. path_separator .. file_path) + return false + end + + local first_line = file:read "*line" + file:close() + + return first_line and string.find(first_line, "SessionLoad") ~= nil +end + return Lib diff --git a/lua/auto-session/session-lens/actions.lua b/lua/auto-session/session-lens/actions.lua index 225e856..f3d02b4 100644 --- a/lua/auto-session/session-lens/actions.lua +++ b/lua/auto-session/session-lens/actions.lua @@ -39,31 +39,7 @@ local function source_session(selection, prompt_bufnr) end vim.defer_fn(function() - local cwd_change_handling_conf = M.functions.conf.cwd_change_handling - - -- If cwd_change_handling is true, the current session will be saved in the DirChangedPre AutoCmd - -- and the new session will be restored in DirChanged - if type(cwd_change_handling_conf) == "table" and cwd_change_handling_conf.restore_upcoming_session then - -- Take advatage of cwd_change_handling behaviour for switching sessions - Lib.logger.debug "Triggering vim.fn.chdir since cwd_change_handling feature is enabled" - vim.fn.chdir(M.functions.format_file_name(type(selection) == "table" and selection.filename or selection)) - else - -- TODO: Since cwd_change_handling is disabled, we save and restore here. This would probably be better - -- handled in AutoSession itself since the same case comes up if the built in picker is used - -- (e.g. :Autosession search). - Lib.logger.debug "Triggering session-lens behaviour since cwd_change_handling feature is disabled" - M.functions.AutoSaveSession() - - local buffers = vim.api.nvim_list_bufs() - for _, bufn in pairs(buffers) do - if not vim.tbl_contains(M.conf.buftypes_to_ignore, vim.api.nvim_buf_get_option(bufn, "buftype")) then - vim.cmd("silent bwipeout!" .. bufn) - end - end - - vim.cmd "clearjumps" - M.functions.RestoreSession(type(selection) == "table" and selection.path or selection) - end + M.functions.restore_selected_session(type(selection) == "table" and selection.path) end, 50) end diff --git a/lua/auto-session/session-lens/init.lua b/lua/auto-session/session-lens/init.lua index 37c473b..f2aebc2 100644 --- a/lua/auto-session/session-lens/init.lua +++ b/lua/auto-session/session-lens/init.lua @@ -15,7 +15,7 @@ local SessionLens = { ---@field shorten_path boolean Deprecated, pass { 'shorten' } to path_display ---@field path_display table An array that specifies how to handle paths. Read :h telescope.defaults.path_display ---@field theme_conf table ----@field buftypes_to_ignore table +---@field buftypes_to_ignore table Deprecated, if you're using this please report your usage on github ---@field previewer boolean ---@field session_control session_control ---@field load_on_setup boolean @@ -37,6 +37,10 @@ function SessionLens.setup(auto_session) Lib.setup(SessionLens.conf, auto_session) Actions.setup(SessionLens.conf, auto_session) logger.log_level = auto_session.conf.log_level + + if SessionLens.conf.buftypes_to_ignore ~= nil and not vim.tbl_isempty(SessionLens.conf.buftypes_to_ignore) then + logger.warn('buftypes_to_ignore is deprecated. If you think you need this option, please file a bug on GitHub. If not, please remove it from your config') + end end ---Search session diff --git a/lua/auto-session/session-lens/library.lua b/lua/auto-session/session-lens/library.lua index bdaa5ed..b628103 100644 --- a/lua/auto-session/session-lens/library.lua +++ b/lua/auto-session/session-lens/library.lua @@ -36,6 +36,12 @@ end function Lib.make_entry.gen_from_file(opts) local root = Lib.functions.get_root_dir() return function(line) + -- Don't include x.vim files that nvim makes for custom user + -- commands + if not AutoSessionLib.is_session_file(root, line) then + return nil + end + return { ordinal = line, value = line,