Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: #208 stop LSs when restoring session #395

Merged
merged 3 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,14 @@ Here are the default settings:
auto_restore_last_session = false, -- On startup, loads the last saved session if session for cwd does not exist
use_git_branch = false, -- Include git branch name in session name
lazy_support = true, -- Automatically detect if Lazy.nvim is being used and wait until Lazy is done to make sure session is restored correctly. Does nothing if Lazy isn't being used. Can be disabled if a problem is suspected or for debugging
bypass_save_filetypes = nil, -- List of file types to bypass auto save when the only buffer open is one of the file types listed, useful to ignore dashboards
bypass_save_filetypes = nil, -- List of filetypes to bypass auto save when the only buffer open is one of the file types listed, useful to ignore dashboards
close_unsupported_windows = true, -- Close windows that aren't backed by normal file before autosaving a session
args_allow_single_directory = true, -- Follow normal sesion save/load logic if launched with a single directory as the only argument
args_allow_files_auto_save = false, -- Allow saving a session even when launched with a file argument (or multiple files/dirs). It does not load any existing session first. While you can just set this to true, you probably want to set it to a function that decides when to save a session when launched with file args. See documentation for more detail
continue_restore_on_error = true, -- Keep loading the session even if there's an error
show_auto_restore_notif = false, -- Whether to show a notification when auto-restoring
cwd_change_handling = false, -- Follow cwd changes, saving a session before change and restoring after
lsp_stop_on_restore = false, -- Should language servers be stopped when restoring a session. Can also be a function that will be called if set. Not called on autorestore from startup
log_level = "error", -- Sets the log level of the plugin (debug, info, warn, error).

session_lens = {
Expand Down
33 changes: 21 additions & 12 deletions doc/auto-session.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ AutoSession.Config *AutoSession.Config*
{show_auto_restore_notif?} (boolean) Whether to show a notification when auto-restoring
{log_level?} (string|integer) "debug", "info", "warn", "error" or vim.log.levels.DEBUG, vim.log.levels.INFO, vim.log.levels.WARN, vim.log.levels.ERROR
{cwd_change_handling?} (boolean) Follow cwd changes, saving a session before change and restoring after
{lsp_stop_on_restore?} (boolean|function) Should language servers be stopped when restoring a session. Can also be a function that will be called if set. Not called on autorestore from startup
{session_lens?} (SessionLens) Session lens configuration options
{pre_save_cmds?} (table) executes before a session is saved

Expand Down Expand Up @@ -124,11 +125,12 @@ AutoSession.AutoSaveSession() *AutoSession.AutoSaveSession*


*AutoSession.AutoRestoreSession*
AutoSession.AutoRestoreSession({session_name?})
AutoSession.AutoRestoreSession({session_name?}, {is_startup?})
Function called by AutoSession when automatically restoring a session.

Parameters: ~
{session_name?} (string) An optional session to load
{session_name?} (string) An optional session to load
{is_startup?} (boolean|nil) Is this autorestore happening on startup

Returns: ~
(boolean) returns whether restoring the session was successful or not.
Expand Down Expand Up @@ -161,34 +163,41 @@ AutoSession.SaveSessionToDir({session_dir}, {session_name?}, {show_message?})
(boolean)


RestoreOpts *RestoreOpts*

Fields: ~
{show_message} (boolean|nil) Should messages be shown
{is_startup_autorestore} (boolean|nil) True if this is the the startup autorestore


*AutoSession.RestoreSession*
AutoSession.RestoreSession({session_name?}, {show_message?})
AutoSession.RestoreSession({session_name?}, {opts?})
Restores a session from the passed in directory. If no optional session name
is passed in, it uses the cwd as the session name

Parameters: ~
{session_name?} (string|nil) Optional session name
{show_message?} (boolean) Optional, whether to show a message on restore (true by default)
{session_name?} (string|nil) Optional session name
{opts?} (RestoreOpts|nil) restore options


*AutoSession.RestoreSessionFromDir*
AutoSession.RestoreSessionFromDir({session_dir}, {session_name?}, {show_message?})
AutoSession.RestoreSessionFromDir({session_dir}, {session_name?}, {opts?})
Restores a session from the passed in directory. If no optional session name
is passed in, it uses the cwd as the session name

Parameters: ~
{session_dir} (string) Directory to write the session file to
{session_name?} (string|nil) Optional session name
{show_message?} (boolean) Optional, whether to show a message on restore (true by default)
{session_dir} (string) Directory to write the session file to
{session_name?} (string|nil) Optional session name
{opts?} (RestoreOpts|nil) restore options


*AutoSession.RestoreSessionFile*
AutoSession.RestoreSessionFile({session_path}, {show_message?})
AutoSession.RestoreSessionFile({session_path}, {opts?})
Restores a session from a specific file

Parameters: ~
{session_path} (string) The session file to load
{show_message?} (boolean) Optional, whether to show a message on restore (true by default)
{session_path} (string) The session file to load
{opts?} (RestoreOpts|nil) restore options

Returns: ~
(boolean) a session restored
Expand Down
2 changes: 2 additions & 0 deletions lua/auto-session/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ local M = {}
---@field show_auto_restore_notif? boolean Whether to show a notification when auto-restoring
---@field log_level? string|integer "debug", "info", "warn", "error" or vim.log.levels.DEBUG, vim.log.levels.INFO, vim.log.levels.WARN, vim.log.levels.ERROR
---@field cwd_change_handling? boolean Follow cwd changes, saving a session before change and restoring after
---@field lsp_stop_on_restore? boolean|function Should language servers be stopped when restoring a session. Can also be a function that will be called if set. Not called on autorestore from startup
---@field session_lens? SessionLens Session lens configuration options
---
---Hooks
Expand Down Expand Up @@ -79,6 +80,7 @@ local defaults = {
continue_restore_on_error = true, -- Keep loading the session even if there's an error
show_auto_restore_notif = false, -- Whether to show a notification when auto-restoring
cwd_change_handling = false, -- Follow cwd changes, saving a session before change and restoring after
lsp_stop_on_restore = false, -- Should language servers be stopped when restoring a session. Can also be a function that will be called if set. Not called on autorestore from startup
log_level = "error", -- Sets the log level of the plugin (debug, info, warn, error).

---@type SessionLens
Expand Down
65 changes: 48 additions & 17 deletions lua/auto-session/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,19 @@ end

---Function called by AutoSession when automatically restoring a session.
---@param session_name? string An optional session to load
---@param is_startup? boolean|nil Is this autorestore happening on startup
---@return boolean boolean returns whether restoring the session was successful or not.
function AutoSession.AutoRestoreSession(session_name)
function AutoSession.AutoRestoreSession(session_name, is_startup)
-- WARN: should this be checking is_allowed_dir as well?
if not is_enabled() or not auto_restore() or suppress_session(session_name) then
return false
end

return AutoSession.RestoreSession(session_name, Config.show_auto_restore_notif)
local opts = {
show_message = Config.show_auto_restore_notif,
is_startup_autorestore = is_startup,
}
return AutoSession.RestoreSession(session_name, opts)
end

---@private
Expand All @@ -471,7 +476,7 @@ function AutoSession.auto_restore_session_at_vim_enter()
local session_name = Lib.remove_trailing_separator(vim.fn.fnamemodify(launch_argv[1], ":p"))
Lib.logger.debug("Launched with single directory, using as session_dir: " .. session_name)

if AutoSession.AutoRestoreSession(session_name) then
if AutoSession.AutoRestoreSession(session_name, true) then
return true
end

Expand All @@ -482,7 +487,7 @@ function AutoSession.auto_restore_session_at_vim_enter()
Config.auto_save = false
end
else
if AutoSession.AutoRestoreSession() then
if AutoSession.AutoRestoreSession(nil, true) then
return true
end

Expand All @@ -493,7 +498,12 @@ function AutoSession.auto_restore_session_at_vim_enter()
local last_session_name = Lib.get_latest_session(AutoSession.get_root_dir())
if last_session_name then
Lib.logger.debug("Found last session: " .. last_session_name)
if AutoSession.RestoreSession(last_session_name, Config.show_auto_restore_notif) then
if
AutoSession.RestoreSession(
last_session_name,
{ show_message = Config.show_auto_restore_notif, is_startup_autorestore = true }
)
then
return true
end
end
Expand Down Expand Up @@ -576,21 +586,26 @@ function AutoSession.SaveSessionToDir(session_dir, session_name, show_message)
return true
end

---@class RestoreOpts
---@field show_message boolean|nil Should messages be shown
---@field is_startup_autorestore boolean|nil True if this is the the startup autorestore

---Restores a session from the passed in directory. If no optional session name
---is passed in, it uses the cwd as the session name
---@param session_name? string|nil Optional session name
---@param show_message? boolean Optional, whether to show a message on restore (true by default)
function AutoSession.RestoreSession(session_name, show_message)
return AutoSession.RestoreSessionFromDir(AutoSession.get_root_dir(), session_name, show_message)
---@param opts? RestoreOpts|nil restore options
function AutoSession.RestoreSession(session_name, opts)
return AutoSession.RestoreSessionFromDir(AutoSession.get_root_dir(), session_name, opts)
end

---Restores a session from the passed in directory. If no optional session name
---is passed in, it uses the cwd as the session name
---@param session_dir string Directory to write the session file to
---@param session_name? string|nil Optional session name
---@param show_message? boolean Optional, whether to show a message on restore (true by default)
function AutoSession.RestoreSessionFromDir(session_dir, session_name, show_message)
---@param opts? RestoreOpts|nil restore options
function AutoSession.RestoreSessionFromDir(session_dir, session_name, opts)
Lib.logger.debug("RestoreSessionFromDir start", { session_dir, session_name })
opts = opts or {}
-- Canonicalize and create session_dir if needed
session_dir = Lib.validate_root_dir(session_dir)
Lib.logger.debug("RestoreSessionFromDir validated session_dir: ", session_dir)
Expand Down Expand Up @@ -623,7 +638,7 @@ function AutoSession.RestoreSessionFromDir(session_dir, session_name, show_messa
local legacy_session_path = session_dir .. legacy_escaped_session_name

if vim.fn.filereadable(legacy_session_path) ~= 1 then
if show_message == nil or show_message then
if opts.show_message == nil or opts.show_message then
vim.notify("Could not restore session: " .. Lib.get_session_display_name(escaped_session_name))
end
return false
Expand Down Expand Up @@ -653,18 +668,34 @@ function AutoSession.RestoreSessionFromDir(session_dir, session_name, show_messa
end
end

return AutoSession.RestoreSessionFile(session_path, show_message)
return AutoSession.RestoreSessionFile(session_path, opts)
end

---Restores a session from a specific file
---@param session_path string The session file to load
---@param show_message? boolean Optional, whether to show a message on restore (true by default)
---@param opts? RestoreOpts|nil restore options
---@return boolean Was a session restored
function AutoSession.RestoreSessionFile(session_path, show_message)
AutoSession.run_cmds "pre_restore"

function AutoSession.RestoreSessionFile(session_path, opts)
Lib.logger.debug("RestoreSessionFile restoring session from: " .. session_path)
opts = opts or {}

AutoSession.run_cmds "pre_restore"

-- Stop any language servers if config is set but don't do
-- this on startup as it causes a perceptible delay (and we
-- know there aren't any language servers anyway)
if not opts.is_startup_autorestore then
if Config.lsp_stop_on_restore then
if type(Config.lsp_stop_on_restore) == "function" then
Config.lsp_stop_on_restore()
else
local clients = vim.lsp.get_clients()
if #clients > 0 then
vim.lsp.stop_client(clients)
end
end
end
end
-- Vim cmds require escaping any % with a \ but we don't want to do that
-- for direct filesystem operations (like in save_extra_cmds_new) so we
-- that here, as late as possible and only for this operation
Expand Down Expand Up @@ -709,7 +740,7 @@ Error: ]] .. result)

local session_name = Lib.escaped_session_name_to_session_name(vim.fn.fnamemodify(session_path, ":t"))
Lib.logger.debug("Restored session: " .. session_name)
if show_message == nil or show_message then
if opts.show_message == nil or opts.show_message then
vim.notify("Restored session: " .. session_name)
end

Expand Down
35 changes: 35 additions & 0 deletions tests/ls_stop_on_restore_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
local TL = require "tests/test_lib"

describe("lsp_stop_on_restore", function()
local as = require "auto-session"
as.setup {}
TL.clearSessionFilesAndBuffers()
vim.cmd("e " .. TL.test_file)
as.SaveSession()

it("calls user function on restore", function()
local stop_called = false
as.setup {
lsp_stop_on_restore = function()
stop_called = true
end,
}

as.RestoreSession()

assert.True(stop_called)
end)

it("doesn't try to stop ls on initial autorestore", function()
local stop_called = false
as.setup {
lsp_stop_on_restore = function()
stop_called = true
end,
}

as.auto_restore_session_at_vim_enter()

assert.False(stop_called)
end)
end)
1 change: 1 addition & 0 deletions tests/test_lib.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "plenary"
local asLib = require "auto-session.lib"
local M = {}

Expand Down