@@ -2,6 +2,7 @@ local M = {}
22
33local pending_config
44local current_session
5+ local tab_sessions = {}
56
67local function do_setup ()
78 if pending_config then
1920--- Get the name of the current session
2021--- @return string | nil
2122M .get_current = function ()
22- return current_session
23+ local tabpage = vim .api .nvim_get_current_tabpage ()
24+ return tab_sessions [tabpage ] or current_session
2325end
2426
2527--- Detach from the current session
2628M .detach = function ()
2729 current_session = nil
30+ local tabpage = vim .api .nvim_get_current_tabpage ()
31+ tab_sessions [tabpage ] = nil
2832end
2933
3034--- @class resession.ListOpts
@@ -59,6 +63,15 @@ M.list = function(opts)
5963 return ret
6064end
6165
66+ local function remove_tabpage_session (name )
67+ for k , v in pairs (tab_sessions ) do
68+ if v == name then
69+ tab_sessions [k ] = nil
70+ break
71+ end
72+ end
73+ end
74+
6275--- @class resession.DeleteOpts
6376--- @field dir nil | string Name of directory to save to (overrides config.dir )
6477
@@ -88,47 +101,33 @@ M.delete = function(name, opts)
88101 if current_session == name then
89102 current_session = nil
90103 end
104+ remove_tabpage_session (name )
91105end
92106
93- --- @class resession.SaveOpts
94- --- @field detach nil | boolean Immediately detach from the saved session
95- --- @field notify nil | boolean Notify on success
96- --- @field dir nil | string Name of directory to save to (overrides config.dir )
97-
98- --- @param name ? string
99- --- @param opts ? resession.SaveOpts
100- M .save = function (name , opts )
101- opts = vim .tbl_extend (" keep" , opts or {}, {
102- notify = true ,
103- })
104- if not name then
105- name = current_session
106- end
107- if not name then
108- vim .ui .input ({ prompt = " Session name" }, function (selected )
109- if selected then
110- M .save (selected , opts )
111- end
112- end )
113- return
114- end
107+ --- @param name string
108+ --- @param opts resession.SaveOpts
109+ --- @param target_tabpage ? integer
110+ local function save (name , opts , target_tabpage )
115111 local config = require (" resession.config" )
116112 local files = require (" resession.files" )
117113 local layout = require (" resession.layout" )
118114 local util = require (" resession.util" )
119115 local filename = util .get_session_file (name , opts .dir )
116+ local cwd
120117 local data = {
121118 buffers = {},
122119 tabs = {},
120+ tab_scoped = target_tabpage ~= nil ,
123121 global = {
124122 cwd = vim .fn .getcwd (- 1 , - 1 ),
125123 height = vim .o .lines - vim .o .cmdheight ,
126124 width = vim .o .columns ,
127- options = util .save_global_options (),
125+ -- Don't save global options for tab-scoped session
126+ options = target_tabpage and {} or util .save_global_options (),
128127 },
129128 }
130129 for _ , bufnr in ipairs (vim .api .nvim_list_bufs ()) do
131- if config . buffers . filter ( bufnr ) then
130+ if util . include_buf ( target_tabpage , bufnr ) then
132131 local buf = {
133132 name = vim .api .nvim_buf_get_name (bufnr ),
134133 loaded = vim .api .nvim_buf_is_loaded (bufnr ),
@@ -137,20 +136,24 @@ M.save = function(name, opts)
137136 table.insert (data .buffers , buf )
138137 end
139138 end
140- for _ , tabpage in ipairs (vim .api .nvim_list_tabpages ()) do
139+ local tabpages = target_tabpage and { target_tabpage } or vim .api .nvim_list_tabpages ()
140+ local buf_filter = function (bufnr )
141+ return util .include_buf (target_tabpage , bufnr )
142+ end
143+ for _ , tabpage in ipairs (tabpages ) do
141144 local tab = {}
142145 local tabnr = vim .api .nvim_tabpage_get_number (tabpage )
143- if vim .fn .haslocaldir (- 1 , tabnr ) == 1 then
146+ if target_tabpage or vim .fn .haslocaldir (- 1 , tabnr ) == 1 then
144147 tab .cwd = vim .fn .getcwd (- 1 , tabnr )
145148 end
146149 table.insert (data .tabs , tab )
147150 local winlayout = vim .fn .winlayout (tabnr )
148- tab .wins = layout .add_win_info_to_layout (tabnr , winlayout )
151+ tab .wins = layout .add_win_info_to_layout (tabnr , winlayout , buf_filter )
149152 end
150153
151- for ext_name in pairs (config .extensions ) do
154+ for ext_name , ext_config in pairs (config .extensions ) do
152155 local ext = util .get_extension (ext_name )
153- if ext then
156+ if ext and ( ext_config . enable_in_tab or not target_tabpage ) then
154157 local ok , ext_data = pcall (ext .on_save )
155158 if ok then
156159 data [ext_name ] = ext_data
@@ -164,21 +167,97 @@ M.save = function(name, opts)
164167 end
165168
166169 files .write_json_file (filename , data )
167- if not opts .detach then
168- current_session = name
169- end
170170 if opts .notify then
171171 vim .notify (string.format (" Saved session %s" , name ))
172172 end
173173end
174174
175+ --- @class resession.SaveOpts
176+ --- @field attach nil | boolean Stay attached to session after saving
177+ --- @field notify nil | boolean Notify on success
178+ --- @field dir nil | string Name of directory to save to (overrides config.dir )
179+
180+ --- @param name ? string
181+ --- @param opts ? resession.SaveOpts
182+ M .save = function (name , opts )
183+ opts = vim .tbl_extend (" keep" , opts or {}, {
184+ notify = true ,
185+ attach = true ,
186+ })
187+ if not name then
188+ -- If no name, default to the current session
189+ name = current_session
190+ end
191+ if not name then
192+ vim .ui .input ({ prompt = " Session name" }, function (selected )
193+ if selected then
194+ M .save (selected , opts )
195+ end
196+ end )
197+ return
198+ end
199+ save (name , opts )
200+ tab_sessions = {}
201+ if opts .attach then
202+ current_session = name
203+ else
204+ current_session = nil
205+ end
206+ end
207+
208+ --- Save a tab-scoped session
209+ --- @param name string
210+ --- @param opts ? resession.SaveOpts
211+ M .save_tab = function (name , opts )
212+ opts = vim .tbl_extend (" keep" , opts or {}, {
213+ notify = true ,
214+ attach = true ,
215+ })
216+ local cur_tabpage = vim .api .nvim_get_current_tabpage ()
217+ if not name then
218+ name = tab_sessions [cur_tabpage ]
219+ end
220+ if not name then
221+ vim .ui .input ({ prompt = " Session name" }, function (selected )
222+ if selected then
223+ M .save_tab (selected , opts )
224+ end
225+ end )
226+ return
227+ end
228+ save (name , opts , cur_tabpage )
229+ current_session = nil
230+ remove_tabpage_session (name )
231+ if opts .attach then
232+ tab_sessions [cur_tabpage ] = name
233+ else
234+ tab_sessions [cur_tabpage ] = nil
235+ end
236+ end
237+
238+ --- Save all current sessions to disk
239+ M .save_all = function (opts )
240+ opts = vim .tbl_extend (" keep" , opts or {}, {
241+ notify = true ,
242+ })
243+ if current_session then
244+ save (current_session , opts )
245+ else
246+ for tabpage , name in pairs (tab_sessions ) do
247+ save (name , opts , tabpage )
248+ end
249+ end
250+ end
251+
175252local function open_clean_tab ()
176253 -- Detect if we're already in a "clean" tab
177254 -- (one window, and one empty scratch buffer)
178255 if # vim .api .nvim_tabpage_list_wins (0 ) == 1 then
179256 if vim .api .nvim_buf_get_name (0 ) == " " then
180257 local lines = vim .api .nvim_buf_get_lines (0 , - 1 , 2 , false )
181- if # lines == 1 and lines [1 ] == " " then
258+ if vim .tbl_isempty (lines ) then
259+ vim .api .nvim_buf_set_option (0 , " buflisted" , false )
260+ vim .api .nvim_buf_set_option (0 , " bufhidden" , " wipe" )
182261 return
183262 end
184263 end
@@ -201,16 +280,17 @@ local function close_everything()
201280end
202281
203282--- @class resession.LoadOpts
204- --- @field detach nil | boolean Detach from session after loading
205- --- @field reset nil | boolean Close everthing before loading the session (default true )
283+ --- @field attach nil | boolean Attach to session after loading
284+ --- @field reset nil | boolean | " auto " Close everthing before loading the session (default " auto " )
206285--- @field silence_errors nil | boolean Don ' t error when trying to load a missing session
207286--- @field dir nil | string Name of directory to load from (overrides config.dir )
208287
209288--- @param name ? string
210289--- @param opts ? resession.LoadOpts
211290M .load = function (name , opts )
212291 opts = vim .tbl_extend (" keep" , opts or {}, {
213- reset = true ,
292+ reset = " auto" ,
293+ attach = true ,
214294 })
215295 local config = require (" resession.config" )
216296 local files = require (" resession.files" )
@@ -237,6 +317,9 @@ M.load = function(name, opts)
237317 end
238318 return
239319 end
320+ if opts .reset == " auto" then
321+ opts .reset = not data .tab_scoped
322+ end
240323 if opts .reset then
241324 close_everything ()
242325 else
@@ -248,7 +331,9 @@ M.load = function(name, opts)
248331 vim .o .columns / data .global .width ,
249332 (vim .o .lines - vim .o .cmdheight ) / data .global .height ,
250333 }
251- vim .cmd (string.format (" cd %s" , data .global .cwd ))
334+ if not data .tab_scoped then
335+ vim .cmd (string.format (" cd %s" , data .global .cwd ))
336+ end
252337 for _ , buf in ipairs (data .buffers ) do
253338 local bufnr = vim .fn .bufadd (buf .name )
254339 if buf .loaded then
@@ -294,10 +379,17 @@ M.load = function(name, opts)
294379 for k , v in pairs (data .global .options ) do
295380 vim .o [k ] = v
296381 end
297- if opts .detach then
298- current_session = nil
299- else
300- current_session = name
382+ current_session = nil
383+ if opts .reset then
384+ tab_sessions = {}
385+ end
386+ remove_tabpage_session (name )
387+ if opts .attach then
388+ if data .tab_scoped then
389+ tab_sessions [vim .api .nvim_get_current_tabpage ()] = name
390+ else
391+ current_session = name
392+ end
301393 end
302394end
303395
0 commit comments