Implement session command to set layout state

This commit is contained in:
Kovid Goyal
2025-08-06 20:30:00 +05:30
parent bc8fc6642c
commit 97f1d7f436
3 changed files with 14 additions and 3 deletions

View File

@@ -354,6 +354,7 @@ class Tall(Layout):
def set_layout_state(self, layout_state: dict[str, Any], map_group_id: WindowMapper) -> bool: def set_layout_state(self, layout_state: dict[str, Any], map_group_id: WindowMapper) -> bool:
self.main_bias = layout_state['main_bias'] self.main_bias = layout_state['main_bias']
self.biased_map = layout_state['biased_map'] self.biased_map = layout_state['biased_map']
self.layout_opts = TallLayoutOpts(layout_state['opts'])
return True return True

View File

@@ -1,13 +1,14 @@
#!/usr/bin/env python #!/usr/bin/env python
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
import json
import os import os
import shlex import shlex
import sys import sys
from collections.abc import Callable, Generator, Iterator, Mapping from collections.abc import Callable, Generator, Iterator, Mapping
from contextlib import suppress from contextlib import suppress
from functools import partial from functools import partial
from typing import TYPE_CHECKING, Optional, Union from typing import TYPE_CHECKING, Any, Optional, Union
from .cli_stub import CLIOptions from .cli_stub import CLIOptions
from .layout.interface import all_layouts from .layout.interface import all_layouts
@@ -58,6 +59,7 @@ class Tab:
self.active_window_idx = 0 self.active_window_idx = 0
self.enabled_layouts = opts.enabled_layouts self.enabled_layouts = opts.enabled_layouts
self.layout = (self.enabled_layouts or ['tall'])[0] self.layout = (self.enabled_layouts or ['tall'])[0]
self.layout_state: dict[str, Any] | None = None
self.cwd: str | None = None self.cwd: str | None = None
self.next_title: str | None = None self.next_title: str | None = None
@@ -101,6 +103,9 @@ class Session:
raise ValueError(f'{val} is not a valid layout') raise ValueError(f'{val} is not a valid layout')
self.tabs[-1].layout = val self.tabs[-1].layout = val
def set_layout_state(self, val: str) -> None:
self.tabs[-1].layout_state = json.loads(val)
def add_window(self, cmd: None | str | list[str], expand: Callable[[str], str] = lambda x: x) -> None: def add_window(self, cmd: None | str | list[str], expand: Callable[[str], str] = lambda x: x) -> None:
from .launch import parse_launch_args from .launch import parse_launch_args
needs_expandvars = False needs_expandvars = False
@@ -185,7 +190,7 @@ def parse_session(raw: str, opts: Options, environ: Mapping[str, str] | None = N
else: else:
cmd, rest = parts cmd, rest = parts
cmd, rest = cmd.strip(), rest.strip() cmd, rest = cmd.strip(), rest.strip()
if cmd != 'launch': if cmd not in ('launch', 'set_layout_state'):
rest = expand(rest) rest = expand(rest)
if cmd == 'new_tab': if cmd == 'new_tab':
ans.add_tab(opts, rest) ans.add_tab(opts, rest)
@@ -220,6 +225,8 @@ def parse_session(raw: str, opts: Options, environ: Mapping[str, str] | None = N
ans.resize_window(rest.split()) ans.resize_window(rest.split())
elif cmd == 'focus_matching_window': elif cmd == 'focus_matching_window':
ans.focus_matching_window(rest) ans.focus_matching_window(rest)
elif cmd == 'set_layout_state':
ans.set_layout_state(rest)
else: else:
raise ValueError(f'Unknown command in session file: {cmd}') raise ValueError(f'Unknown command in session file: {cmd}')
yield finalize_session(ans) yield finalize_session(ans)

View File

@@ -237,7 +237,7 @@ class Tab: # {{{
self._current_layout_name = layout_name self._current_layout_name = layout_name
self.mark_tab_bar_dirty() self.mark_tab_bar_dirty()
def startup(self, session_tab: 'SessionTab') -> None: def startup(self, session_tab: SessionTab) -> None:
target_tab = self target_tab = self
boss = get_boss() boss = get_boss()
for window in session_tab.windows: for window in session_tab.windows:
@@ -264,6 +264,9 @@ class Tab: # {{{
with suppress(IndexError): with suppress(IndexError):
self.windows.set_active_window_group_for(self.windows.all_windows[session_tab.active_window_idx]) self.windows.set_active_window_group_for(self.windows.all_windows[session_tab.active_window_idx])
if session_tab.layout_state:
if self.current_layout.unserialize(session_tab.layout_state, self.windows):
self.relayout()
def serialize_state(self) -> dict[str, Any]: def serialize_state(self) -> dict[str, Any]:
return { return {