Add a --match argument to limit what windows are saved by save_as_session

This commit is contained in:
Kovid Goyal 2025-08-19 21:53:49 +05:30
parent 89145e6a55
commit e43d894dda
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 17 additions and 4 deletions

View file

@ -504,10 +504,11 @@ def list_os_windows(
def serialize_state_as_session(self, session_path: str = '', ser_opts: SaveAsSessionOptions | None = None) -> Iterator[str]:
if ser_opts is None:
ser_opts = default_save_as_session_opts()
matched_windows = frozenset(self.match_windows(ser_opts.match)) if ser_opts.match else None
s = {current_focused_os_window_id(): 2, last_focused_os_window_id(): 1}
for i, os_window_id in enumerate(sorted(self.os_window_map, key=lambda wid: s.get(wid, 0))):
tm = self.os_window_map[os_window_id]
yield from tm.serialize_state_as_session(session_path, is_first=i==0, ser_opts=ser_opts)
yield from tm.serialize_state_as_session(session_path, matched_windows, is_first=i==0, ser_opts=ser_opts)
@property
def all_tab_managers(self) -> Iterator[TabManager]:

View file

@ -510,6 +510,13 @@ def save_as_session_options() -> str:
When saving the working directory for windows, do so as paths relative to the directory in which
the session file will be saved. This allows the session file to work even when its containing
directory is moved elsewhere.
--match
If specified, only save all windows (and their parent tabs/OS Windows) that match the specified
search expression. See :ref:`search_syntax` for details on the search language. In particular if
you want to only save windows that are present in the currently active session,
use :code:`--match=session:.`.
'''

View file

@ -295,7 +295,7 @@ def serialize_state(self) -> dict[str, Any]:
'name': self.name,
}
def serialize_state_as_session(self, session_path: str, ser_opts: SaveAsSessionOptions) -> list[str]:
def serialize_state_as_session(self, session_path: str, matched_windows: frozenset[Window] | None, ser_opts: SaveAsSessionOptions) -> list[str]:
import shlex
launch_cmds = []
active_idx = self.windows.active_group_idx
@ -311,6 +311,8 @@ def make_relative(cwd: str) -> str:
for i, g in enumerate(groups):
gw: list[str] = []
for window in g:
if matched_windows is not None and window not in matched_windows:
continue
cwd = cwds[window.id]
lc = window.as_launch_command(ser_opts, '' if cwd == most_common_cwd else cwd, is_overlay=bool(gw))
if lc:
@ -1227,7 +1229,10 @@ def serialize_state(self) -> dict[str, Any]:
'active_tab_idx': self.active_tab_idx,
}
def serialize_state_as_session(self, session_path: str, ser_opts: SaveAsSessionOptions, is_first: bool = False) -> list[str]:
def serialize_state_as_session(
self, session_path: str, matched_windows: frozenset[Window] | None, ser_opts: SaveAsSessionOptions,
is_first: bool = False
) -> list[str]:
ans = []
hmap = {tab_id: i for i, tab_id in enumerate(self.active_tab_history)}
if (at := self.active_tab) is not None:
@ -1235,7 +1240,7 @@ def serialize_state_as_session(self, session_path: str, ser_opts: SaveAsSessionO
def skey(tab: Tab) -> int:
return hmap.get(tab.id, -1)
for tab in sorted(self, key=skey):
ans.extend(tab.serialize_state_as_session(session_path, ser_opts))
ans.extend(tab.serialize_state_as_session(session_path, matched_windows, ser_opts))
if ans:
prefix = [] if is_first else ['', '', 'new_os_window']
if self.wm_class and self.wm_class != appname: