Skip to content

Commit 9848758

Browse files
committed
Add DirChangedPre and DirChanged handling
This commit adds handling for when the cwd changes by setting callbacks to both `DirChangedPre` and `DirChanged` autocmds. Handling is as follows DirChangedPre: - Save the current session - Clear all buffers `%bd!`. This guarantees buffers don't bleed to the next session. - Clear jumps. Also done so there is no bleading between sessions. - Run the `pre_cwd_changed_hook` DirChanged: - Restore session using new cwd - Run the `post_cwd_changed_hook` Now when the user changes the cwd with `:cd some/new/dir` auto-session handles it gracefully, saving the current session so there aren't losses and loading the session for the upcoming cwd if it exists. Closes #102.
1 parent 79ae9f7 commit 9848758

File tree

3 files changed

+87
-14
lines changed

3 files changed

+87
-14
lines changed

Diff for: lua/auto-session-autocmds.lua

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
local Lib = require "auto-session-library"
2+
3+
local M = {}
4+
5+
M.setup_autocmds = function(config, AutoSession)
6+
if vim.tbl_isempty(config.cwd_change_handling) or config.cwd_change_handling == nil then
7+
return
8+
end
9+
10+
local conf = config.cwd_change_handling
11+
12+
vim.api.nvim_create_autocmd("DirChangedPre", {
13+
callback = function()
14+
Lib.logger.debug "DirChangedPre"
15+
Lib.logger.debug("cwd: " .. vim.fn.getcwd())
16+
17+
AutoSession.AutoSaveSession()
18+
19+
-- Clear all buffers and jumps after session save so session doesn't blead over to next session.
20+
vim.cmd "%bd!"
21+
vim.cmd "clearjumps"
22+
23+
if type(conf.pre_cwd_changed_hook) == "function" then
24+
conf.pre_cwd_changed_hook()
25+
end
26+
end,
27+
pattern = "global",
28+
})
29+
30+
if conf.restore_upcoming_session then
31+
vim.api.nvim_create_autocmd("DirChanged", {
32+
callback = function()
33+
Lib.logger.debug "DirChanged"
34+
Lib.logger.debug("cwd: " .. vim.fn.getcwd())
35+
36+
-- Deferring to avoid otherwise there are tresitter highlighting issues
37+
vim.defer_fn(function()
38+
local success = AutoSession.AutoRestoreSession()
39+
40+
if not success then
41+
Lib.logger.info("Could not load session. A session file is likely missing for this cwd." .. vim.fn.getcwd())
42+
end
43+
44+
if type(conf.post_cwd_changed_hook) == "function" then
45+
conf.post_cwd_changed_hook()
46+
end
47+
end, 50)
48+
end,
49+
pattern = "global",
50+
})
51+
end
52+
end
53+
54+
return M

Diff for: lua/auto-session-library.lua

+4-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function Config.normalize(config, existing)
2828

2929
return conf
3030
end
31+
3132
-- ====================================================
3233

3334
-- Helper functions ===============================================================
@@ -188,20 +189,21 @@ end
188189
-- Logger =========================================================
189190
function Lib.logger.debug(...)
190191
if Lib.conf.log_level == "debug" then
191-
print('debug', ...)
192+
print("debug", ...)
192193
end
193194
end
194195

195196
function Lib.logger.info(...)
196197
local valid_values = { "info", "debug" }
197198
if has_value(valid_values, Lib.conf.log_level) then
198-
print('info', ...)
199+
print("info", ...)
199200
end
200201
end
201202

202203
function Lib.logger.error(...)
203204
error(...)
204205
end
206+
205207
-- =========================================================
206208

207209
return Lib

Diff for: lua/auto-session.lua

+29-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local Lib = require "auto-session-library"
2+
local autocmds = require "auto-session-autocmds"
23

34
-- Run comand hooks
45
local function run_hook_cmds(cmds, hook_name)
@@ -40,6 +41,11 @@ local defaultConf = {
4041

4142
local luaOnlyConf = {
4243
bypass_session_save_file_types = nil, -- Bypass auto save when only buffer open is one of these file types
44+
cwd_change_handling = { -- Config for handling the DirChangePre and DirChanged autocmds, can be set to nil to disable altogether
45+
restore_upcoming_session = true,
46+
pre_cwd_changed_hook = nil, -- lua function hook. This is called after auto_session code runs for the `DirChangedPre` autocmd
47+
post_cwd_changed_hook = nil, -- lua function hook. This is called after auto_session code runs for the `DirChanged` autocmd
48+
},
4349
}
4450

4551
-- Set default config on plugin load
@@ -57,6 +63,8 @@ function AutoSession.setup(config)
5763
Lib.setup {
5864
log_level = AutoSession.conf.log_level,
5965
}
66+
67+
autocmds.setup_autocmds(AutoSession.conf, AutoSession)
6068
end
6169

6270
local function is_enabled()
@@ -216,7 +224,7 @@ local function get_session_file_name(sessions_dir)
216224
-- When we get here session and sessions_dir either both point to a file or do not exist
217225
return session
218226
else
219-
local session_name = Lib.conf.last_loaded_session
227+
local session_name = AutoSession.conf.auto_session_enable_last_session and Lib.conf.last_loaded_session
220228
if not session_name then
221229
session_name = Lib.escaped_session_name_from_cwd()
222230
local branch_name = get_branch_name()
@@ -301,22 +309,25 @@ end
301309
--- Formats an autosession file name to be more presentable to a user
302310
---@param path string
303311
---@return string
304-
local function format_file_name(path)
312+
function AutoSession.format_file_name(path)
305313
return Lib.unescape_dir(path):match "(.+)%.vim"
306314
end
307315

308316
---@return PickerItem[]
309317
function AutoSession.get_session_files()
310318
local files = {}
311319
local sessions_dir = AutoSession.get_root_dir()
320+
312321
if not vim.fn.isdirectory(sessions_dir) then
313322
return files
314323
end
315-
local entries = vim.fn.readdir(sessions_dir, function (item)
324+
325+
local entries = vim.fn.readdir(sessions_dir, function(item)
316326
return vim.fn.isdirectory(item) == 0
317327
end)
318-
return vim.tbl_map(function (entry)
319-
return { display_name = format_file_name(entry), path = entry }
328+
329+
return vim.tbl_map(function(entry)
330+
return { display_name = AutoSession.format_file_name(entry), path = entry }
320331
end, entries)
321332
end
322333

@@ -342,9 +353,8 @@ local function handle_autosession_command(data)
342353
local files = AutoSession.get_session_files()
343354
if data.args:match "search" then
344355
open_picker(files, "Select a session:", function(choice)
345-
AutoSession.AutoSaveSession()
346-
vim.cmd "%bd!"
347-
AutoSession.RestoreSessionFromFile(choice.display_name)
356+
-- Change dir to selected session path, the DirChangePre and DirChange events will take care of the rest
357+
vim.fn.chdir(choice.display_name)
348358
end)
349359
elseif data.args:match "delete" then
350360
open_picker(files, "Delete a session:", function(choice)
@@ -374,7 +384,7 @@ end
374384
-- This function avoids calling RestoreSession automatically when argv is not nil.
375385
function AutoSession.AutoRestoreSession(sessions_dir)
376386
if is_enabled() and auto_restore() and not suppress_session() then
377-
AutoSession.RestoreSession(sessions_dir)
387+
return AutoSession.RestoreSession(sessions_dir)
378388
end
379389
end
380390

@@ -404,8 +414,8 @@ end
404414
-- TODO: make this more readable!
405415
-- Restores the session by sourcing the session file if it exists/is readable.
406416
function AutoSession.RestoreSession(sessions_dir_or_file)
407-
Lib.logger.debug("sessions dir or file", sessions_dir_or_file)
408417
local sessions_dir, session_file = extract_dir_or_file(sessions_dir_or_file)
418+
Lib.logger.debug("sessions_dir, session_file", sessions_dir, session_file)
409419

410420
local restore = function(file_path, session_name)
411421
local pre_cmds = AutoSession.get_cmds "pre_restore"
@@ -424,7 +434,10 @@ function AutoSession.RestoreSession(sessions_dir_or_file)
424434
end
425435

426436
Lib.logger.info("Session restored from " .. file_path)
427-
Lib.conf.last_loaded_session = session_name
437+
438+
if AutoSession.conf.auto_session_enable_last_session then
439+
Lib.conf.last_loaded_session = session_name
440+
end
428441

429442
local post_cmds = AutoSession.get_cmds "post_restore"
430443
run_hook_cmds(post_cmds, "post-restore")
@@ -433,7 +446,8 @@ function AutoSession.RestoreSession(sessions_dir_or_file)
433446
-- I still don't like reading this chunk, please cleanup
434447
if sessions_dir then
435448
Lib.logger.debug "==== Using session DIR"
436-
local session_name = Lib.conf.last_loaded_session
449+
450+
local session_name = AutoSession.conf.auto_session_enable_last_session and Lib.conf.last_loaded_session
437451
local session_file_path
438452
if not session_name then
439453
session_file_path = get_session_file_name(sessions_dir)
@@ -459,6 +473,7 @@ function AutoSession.RestoreSession(sessions_dir_or_file)
459473
end
460474
else
461475
Lib.logger.debug "File not readable, not restoring session"
476+
return false
462477
end
463478
end
464479
elseif session_file then
@@ -473,6 +488,8 @@ function AutoSession.RestoreSession(sessions_dir_or_file)
473488
else
474489
Lib.logger.error "Error while trying to parse session dir or file"
475490
end
491+
492+
return true
476493
end
477494

478495
local maybe_disable_autosave = function(session_name)

0 commit comments

Comments
 (0)