mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Sessions: A new command focus_matching_window to shift focus to a specific window, useful when creating complex layouts with splits
This commit is contained in:
@@ -76,6 +76,8 @@ Detailed list of changes
|
||||
|
||||
- Add NERD fonts builtin so that users don't have to install them to use NERD symbols in kitty. The builtin font is used only if the symbols are not available in some system font
|
||||
|
||||
- Sessions: A new command ``focus_matching_window`` to shift focus to a specific window, useful when creating complex layouts with splits (:disc:`7635`)
|
||||
|
||||
- Wayland: Allow fractional scales less than one (:pull:`7549`)
|
||||
|
||||
- Wayland: Fix specifying the output name for the panel kitten not working (:iss:`7573`)
|
||||
|
||||
@@ -176,6 +176,25 @@ option in :file:`kitty.conf`. An example, showing all available commands:
|
||||
focus_os_window
|
||||
launch emacs
|
||||
|
||||
# Create a complex layout using multiple splits. Creates two columns of
|
||||
# windows with two windows in each column. The windows in the firt column are
|
||||
# split 50:50. In the second column the windows are not evenly split.
|
||||
new_tab complex tab
|
||||
layout splits
|
||||
# First window, set a user variable on it so we can focus it later
|
||||
launch --var window=first
|
||||
# Create the second column by splitting the first window vertically
|
||||
launch --location=vsplit
|
||||
# Create the third window in the second column by splitting the second window horizontally
|
||||
launch --location=hsplit
|
||||
# Make the third window shorter so that the split is not even
|
||||
resize_window shorter 5
|
||||
# Go back to focusing the first window, so that we can split it
|
||||
focus_matching_window var:window=first
|
||||
# Create the final window in the first column
|
||||
launch --location=hsplit
|
||||
|
||||
|
||||
.. note::
|
||||
The :doc:`launch <launch>` command when used in a session file cannot create
|
||||
new OS windows, or tabs.
|
||||
|
||||
@@ -39,6 +39,7 @@ class WindowSpec:
|
||||
def __init__(self, launch_spec: Union['LaunchSpec', 'SpecialWindowInstance']):
|
||||
self.launch_spec = launch_spec
|
||||
self.resize_spec: Optional[ResizeSpec] = None
|
||||
self.focus_matching_window_spec: str = ''
|
||||
self.is_background_process = False
|
||||
if hasattr(launch_spec, 'opts'): # LaunchSpec
|
||||
from .launch import LaunchSpec
|
||||
@@ -51,6 +52,7 @@ class Tab:
|
||||
def __init__(self, opts: Options, name: str):
|
||||
self.windows: List[WindowSpec] = []
|
||||
self.pending_resize_spec: Optional[ResizeSpec] = None
|
||||
self.pending_focus_matching_window: str = ''
|
||||
self.name = name.strip()
|
||||
self.active_window_idx = 0
|
||||
self.enabled_layouts = opts.enabled_layouts
|
||||
@@ -122,6 +124,9 @@ class Session:
|
||||
if t.pending_resize_spec is not None:
|
||||
t.windows[-1].resize_spec = t.pending_resize_spec
|
||||
t.pending_resize_spec = None
|
||||
if t.pending_focus_matching_window:
|
||||
t.windows[-1].focus_matching_window_spec = t.pending_focus_matching_window
|
||||
t.pending_focus_matching_window = ''
|
||||
|
||||
def resize_window(self, args: List[str]) -> None:
|
||||
s = resize_window('resize_window', shlex.join(args))[1]
|
||||
@@ -132,6 +137,13 @@ class Session:
|
||||
else:
|
||||
t.pending_resize_spec = spec
|
||||
|
||||
def focus_matching_window(self, spec: str) -> None:
|
||||
t = self.tabs[-1]
|
||||
if t.windows:
|
||||
t.windows[-1].focus_matching_window_spec = spec
|
||||
else:
|
||||
t.pending_focus_matching_window = spec
|
||||
|
||||
def add_special_window(self, sw: 'SpecialWindowInstance') -> None:
|
||||
self.tabs[-1].windows.append(WindowSpec(sw))
|
||||
|
||||
@@ -202,6 +214,8 @@ def parse_session(raw: str, opts: Options, environ: Optional[Mapping[str, str]]
|
||||
ans.os_window_state = rest
|
||||
elif cmd == 'resize_window':
|
||||
ans.resize_window(rest.split())
|
||||
elif cmd == 'focus_matching_window':
|
||||
ans.focus_matching_window(rest)
|
||||
else:
|
||||
raise ValueError(f'Unknown command in session file: {cmd}')
|
||||
yield finalize_session(ans)
|
||||
|
||||
@@ -39,6 +39,7 @@ from .fast_data_types import (
|
||||
attach_window,
|
||||
current_focused_os_window_id,
|
||||
detach_window,
|
||||
focus_os_window,
|
||||
get_boss,
|
||||
get_click_interval,
|
||||
get_options,
|
||||
@@ -211,15 +212,29 @@ class Tab: # {{{
|
||||
self.mark_tab_bar_dirty()
|
||||
|
||||
def startup(self, session_tab: 'SessionTab') -> None:
|
||||
target_tab = self
|
||||
boss = get_boss()
|
||||
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(), spec.opts, spec.args, target_tab=self, force_target_tab=True)
|
||||
launched_window = launch(boss, spec.opts, spec.args, target_tab=target_tab, force_target_tab=True)
|
||||
if window.resize_spec is not None:
|
||||
self.resize_window(*window.resize_spec)
|
||||
if window.focus_matching_window_spec:
|
||||
for w in boss.match_windows(window.focus_matching_window_spec, launched_window or boss.active_window):
|
||||
tab = w.tabref()
|
||||
if tab:
|
||||
target_tab = tab or self
|
||||
tm = tab.tab_manager_ref()
|
||||
if tm and boss.active_tab is not target_tab:
|
||||
tm.set_active_tab(target_tab)
|
||||
if target_tab.active_window is not w:
|
||||
target_tab.set_active_window(w)
|
||||
if current_focused_os_window_id() != w.os_window_id:
|
||||
focus_os_window(w.os_window_id, True)
|
||||
|
||||
with suppress(IndexError):
|
||||
self.windows.set_active_window_group_for(self.windows.all_windows[session_tab.active_window_idx])
|
||||
|
||||
Reference in New Issue
Block a user