diff --git a/docs/changelog.rst b/docs/changelog.rst index 9d253f522..ac0af4400 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -43,6 +43,8 @@ Detailed list of changes - Wayland: Fix a regression in the previous release that caused mouse cursor animation and keyboard repeat to stop working when switching seats (:iss:`5188`) +- Allow resizing windows created in session files (:pull:`5196`) + 0.25.2 [2022-06-07] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/overview.rst b/docs/overview.rst index 84fe0d9a3..ea55921f2 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -161,6 +161,8 @@ option in :file:`kitty.conf`. For example: # Set the --class for the new OS window os_window_class mywindow launch sh + # Resize the current window (see the resize_window action for details) + resize_window wider 2 # Make the current window the active (focused) window focus launch emacs diff --git a/kitty/session.py b/kitty/session.py index 2a1dc776a..71ab71e0c 100644 --- a/kitty/session.py +++ b/kitty/session.py @@ -3,7 +3,7 @@ import shlex import sys -from typing import TYPE_CHECKING, Generator, Iterator, List, Optional, Union +from typing import TYPE_CHECKING, Generator, Iterator, List, Optional, Union, Tuple from .cli_stub import CLIOptions from .constants import kitty_exe @@ -16,6 +16,7 @@ from .utils import log_error, resolved_shell if TYPE_CHECKING: from .window import CwdRequest + from .launch import LaunchSpec def get_os_window_sizing_data(opts: Options, session: Optional['Session'] = None) -> WindowSizeData: @@ -26,11 +27,21 @@ def get_os_window_sizing_data(opts: Options, session: Optional['Session'] = None return WindowSizeData(sizes, opts.remember_window_size, opts.single_window_margin_width, opts.window_margin_width, opts.window_padding_width) +ResizeSpec = Tuple[str, int] + + +class WindowSpec: + + def __init__(self, launch_spec: Union['LaunchSpec', 'SpecialWindowInstance']): + self.launch_spec = launch_spec + self.resize_spec: Optional[ResizeSpec] = None + + class Tab: def __init__(self, opts: Options, name: str): - from .launch import LaunchSpec - self.windows: List[Union[LaunchSpec, 'SpecialWindowInstance']] = [] + self.windows: List[WindowSpec] = [] + self.pending_resize_spec: Optional[ResizeSpec] = None self.name = name.strip() self.active_window_idx = 0 self.enabled_layouts = opts.enabled_layouts @@ -70,11 +81,25 @@ class Session: if t.next_title and not spec.opts.window_title: spec.opts.window_title = t.next_title spec.opts.cwd = spec.opts.cwd or t.cwd - t.windows.append(spec) + t.windows.append(WindowSpec(spec)) t.next_title = None + if t.pending_resize_spec is not None: + t.windows[-1].resize_spec = t.pending_resize_spec + t.pending_resize_spec = None + + def resize_window(self, args: List[str]) -> None: + steps = 1 + if len(args) > 1: + steps = int(args[1]) + t = self.tabs[-1] + spec = args[0], steps + if t.windows: + t.windows[-1].resize_spec = spec + else: + t.pending_resize_spec = spec def add_special_window(self, sw: 'SpecialWindowInstance') -> None: - self.tabs[-1].windows.append(sw) + self.tabs[-1].windows.append(WindowSpec(sw)) def focus(self) -> None: self.active_tab_idx = max(0, len(self.tabs) - 1) @@ -95,7 +120,7 @@ def parse_session(raw: str, opts: Options) -> Generator[Session, None, None]: from .tabs import SpecialWindow for t in ans.tabs: if not t.windows: - t.windows.append(SpecialWindow(cmd=resolved_shell(opts))) + t.windows.append(WindowSpec(SpecialWindow(cmd=resolved_shell(opts)))) return ans ans = Session() @@ -132,6 +157,8 @@ def parse_session(raw: str, opts: Options) -> Generator[Session, None, None]: ans.os_window_size = WindowSizes(WindowSize(*w), WindowSize(*h)) elif cmd == 'os_window_class': ans.os_window_class = rest + elif cmd == 'resize_window': + ans.resize_window(rest.split()) else: raise ValueError(f'Unknown command in session file: {cmd}') yield finalize_session(ans) diff --git a/kitty/tabs.py b/kitty/tabs.py index 334eb490a..a51e15961 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -168,12 +168,16 @@ class Tab: # {{{ self.mark_tab_bar_dirty() def startup(self, session_tab: 'SessionTab') -> None: - for cmd in session_tab.windows: - if isinstance(cmd, SpecialWindowInstance): - self.new_special_window(cmd) + for window in session_tab.windows: + spec = window.launch_spec + if isinstance(spec, SpecialWindowInstance): + self.new_special_window(spec) else: from .launch import launch - launch(get_boss(), cmd.opts, cmd.args, target_tab=self, force_target_tab=True) + launch(get_boss(), spec.opts, spec.args, target_tab=self, force_target_tab=True) + if window.resize_spec is not None: + self.resize_window(*window.resize_spec) + self.windows.set_active_window_group_for(self.windows.all_windows[session_tab.active_window_idx]) def serialize_state(self) -> Dict[str, Any]: