Merge branch 'session-add-focus-tab' of https://github.com/jackielii/kitty
This commit is contained in:
commit
1866ffe99e
4 changed files with 54 additions and 4 deletions
|
|
@ -184,6 +184,11 @@ Detailed list of changes
|
|||
- Fix a regression in 0.43.0 that caused :opt:`tab_bar_margin_width` to be
|
||||
doubled on the right edge of the tab bar (:iss:`9154`)
|
||||
|
||||
- Session files: Add a new ``focus_tab`` command to specify which tab should be
|
||||
active when a session is loaded. Accepts either a plain number (0-based index)
|
||||
or a match expression for flexible tab selection, allowing sessions to preserve
|
||||
the active tab state (:doc:`sessions`)
|
||||
|
||||
0.43.1 [2025-10-01]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -154,6 +154,14 @@ all the major keywords you can use in kitty session files:
|
|||
focus_os_window
|
||||
launch emacs
|
||||
|
||||
# Create another tab
|
||||
new_tab logs
|
||||
launch tail -f /var/log/syslog
|
||||
|
||||
# Focus the first tab (index 0) when the session loads
|
||||
# You can also use a match expression like: focus_tab title:logs
|
||||
focus_tab 0
|
||||
|
||||
# Create a complex layout using multiple splits. Creates two columns of
|
||||
# windows with two windows in each column. The windows in the first column are
|
||||
# split 50:50. In the second column the windows are not evenly split.
|
||||
|
|
@ -272,6 +280,15 @@ documentation for them.
|
|||
otherwise the window manager might block changing focus to prevent *focus
|
||||
stealing*.
|
||||
|
||||
``focus_tab [tab specifier]``
|
||||
Set which tab should be active (focused) in the current OS Window. The tab
|
||||
specifier can be either a plain number (treated as a 0-based index) or a
|
||||
match expression. For example, ``focus_tab 0`` will focus the first tab,
|
||||
``focus_tab 1`` the second tab, and ``focus_tab title:logs`` will focus the
|
||||
tab whose title matches "logs". See :ref:`search_syntax` for the full syntax
|
||||
of match expressions. This is useful for session files that create multiple
|
||||
tabs and want to ensure a specific tab is active when the session is loaded.
|
||||
|
||||
``enabled_layouts comma separated list of layout names``
|
||||
Set the layouts allowed in the current tab. Same syntax as
|
||||
:opt:`enabled_layouts`.
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ class Session:
|
|||
def __init__(self, default_title: str | None = None):
|
||||
self.tabs: list[Tab] = []
|
||||
self.active_tab_idx = 0
|
||||
self.focus_tab_spec: str | None = None
|
||||
self.default_title = default_title
|
||||
self.os_window_size: WindowSizes | None = None
|
||||
self.os_window_class: str | None = None
|
||||
|
|
@ -177,6 +178,9 @@ def focus(self) -> None:
|
|||
self.active_tab_idx = max(0, len(self.tabs) - 1)
|
||||
self.tabs[-1].active_window_idx = max(0, len(self.tabs[-1].windows) - 1)
|
||||
|
||||
def focus_tab(self, spec: str) -> None:
|
||||
self.focus_tab_spec = spec
|
||||
|
||||
def set_enabled_layouts(self, raw: str) -> None:
|
||||
self.tabs[-1].enabled_layouts = to_layout_names(raw)
|
||||
if self.tabs[-1].layout not in self.tabs[-1].enabled_layouts:
|
||||
|
|
@ -250,6 +254,8 @@ def finalize_session(ans: Session) -> Session:
|
|||
ans.add_window(rest, expand)
|
||||
elif cmd == 'focus':
|
||||
ans.focus()
|
||||
elif cmd == 'focus_tab':
|
||||
ans.focus_tab(rest)
|
||||
elif cmd == 'focus_os_window':
|
||||
ans.focus_os_window = True
|
||||
elif cmd == 'enabled_layouts':
|
||||
|
|
@ -372,8 +378,9 @@ def skey(w: WindowType) -> float:
|
|||
seen_session_paths: dict[str, str] = {}
|
||||
|
||||
|
||||
def create_session(boss: BossType, path: str) -> str:
|
||||
def create_session(boss: BossType, path: str) -> tuple[str, bool]:
|
||||
session_name = ''
|
||||
created_new_os_window = False
|
||||
for i, s in enumerate(create_sessions(get_options(), default_session=path)):
|
||||
if i == 0:
|
||||
session_name = s.session_name
|
||||
|
|
@ -382,14 +389,16 @@ def create_session(boss: BossType, path: str) -> str:
|
|||
tm = boss.active_tab_manager
|
||||
if tm is None:
|
||||
os_window_id = boss.add_os_window(s)
|
||||
created_new_os_window = True
|
||||
else:
|
||||
os_window_id = tm.os_window_id
|
||||
tm.add_tabs_from_session(s, session_name)
|
||||
else:
|
||||
os_window_id = boss.add_os_window(s)
|
||||
created_new_os_window = True
|
||||
if s.focus_os_window:
|
||||
boss.focus_os_window(os_window_id)
|
||||
return session_name
|
||||
return session_name, created_new_os_window
|
||||
|
||||
|
||||
goto_session_history: list[str] = []
|
||||
|
|
@ -569,14 +578,15 @@ def goto_session(boss: BossType, cmdline: Sequence[str]) -> None:
|
|||
if switch_to_session(boss, session_name):
|
||||
return
|
||||
try:
|
||||
session_name = create_session(boss, path)
|
||||
session_name, created_new_os_window = create_session(boss, path)
|
||||
except Exception:
|
||||
import traceback
|
||||
tb = traceback.format_exc()
|
||||
boss.show_error(_('Failed to create session'), _('Could not create session from {0} with error:\n{1}').format(path, tb))
|
||||
else:
|
||||
# Ensure newly created session is focused needed when it doesn't create its own OS Windows.
|
||||
switch_to_session(boss, session_name)
|
||||
if not created_new_os_window:
|
||||
switch_to_session(boss, session_name)
|
||||
|
||||
|
||||
save_as_session_message = '''\
|
||||
|
|
|
|||
|
|
@ -1064,6 +1064,24 @@ def add_tabs_from_session(self, session: SessionType, session_name: str = '') ->
|
|||
self._add_tab(tab)
|
||||
if i == session.active_tab_idx:
|
||||
active_tab = tab
|
||||
|
||||
# Handle focus_tab_spec if specified
|
||||
if session.focus_tab_spec is not None:
|
||||
spec = session.focus_tab_spec.strip()
|
||||
# Try to parse as a plain number (index)
|
||||
try:
|
||||
idx = int(spec)
|
||||
# Clamp to valid range
|
||||
idx = max(0, min(idx, len(self.tabs) - 1))
|
||||
active_tab = self.tabs[idx]
|
||||
except ValueError:
|
||||
# Not a plain number, treat as match expression
|
||||
from .fast_data_types import get_boss
|
||||
boss = get_boss()
|
||||
matched_tabs = list(boss.match_tabs(spec, self.tabs))
|
||||
if matched_tabs:
|
||||
active_tab = matched_tabs[0]
|
||||
|
||||
if active_tab is not None:
|
||||
idx = self.tabs.index(active_tab)
|
||||
self._set_active_tab(idx)
|
||||
|
|
|
|||
Loading…
Reference in a new issue