kitty @ ls output session

This commit is contained in:
zhaolei
2025-08-07 10:03:00 +08:00
parent 9a2de7bf66
commit 92ff8f9160
3 changed files with 51 additions and 22 deletions

View File

@@ -2,12 +2,16 @@
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net> # License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
import json import json
import os
from collections.abc import Callable from collections.abc import Callable
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Sequence
from kitty.constants import appname from kitty.constants import appname
from .base import MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, Tab, Window from .base import MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, Tab, Window
from ..boss import OSWindowDict
from ..child import ProcessDesc
from ..launch import is_excluded_env_var
if TYPE_CHECKING: if TYPE_CHECKING:
from kitty.cli_stub import LSRCOptions as CLIOptions from kitty.cli_stub import LSRCOptions as CLIOptions
@@ -19,6 +23,7 @@ class LS(RemoteCommand):
match/str: Window to change colors in match/str: Window to change colors in
match_tab/str: Tab to change colors in match_tab/str: Tab to change colors in
self/bool: Boolean indicating whether to list only the window the command is run in self/bool: Boolean indicating whether to list only the window the command is run in
output_format/str: Output in json or session format
''' '''
short_desc = 'List tabs/windows' short_desc = 'List tabs/windows'
@@ -41,6 +46,13 @@ Show all environment variables in output, not just differing ones.
--self --self
type=bool-set type=bool-set
Only list the window this command is run in. Only list the window this command is run in.
--output-format
type=choices
choices=json,session
default=json
Output in json or session format
''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t', 1) ''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t', 1)
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
@@ -49,6 +61,7 @@ Only list the window this command is run in.
def response_from_kitty(self, boss: Boss, window: Window | None, payload_get: PayloadGetType) -> ResponseType: def response_from_kitty(self, boss: Boss, window: Window | None, payload_get: PayloadGetType) -> ResponseType:
tab_filter: Callable[[Tab], bool] | None = None tab_filter: Callable[[Tab], bool] | None = None
window_filter: Callable[[Window], bool] | None = None window_filter: Callable[[Window], bool] | None = None
output_session: bool = False
if payload_get('self'): if payload_get('self'):
def wf(w: Window) -> bool: def wf(w: Window) -> bool:
@@ -59,6 +72,10 @@ Only list the window this command is run in.
def wf(w: Window) -> bool: def wf(w: Window) -> bool:
return w.id in window_ids return w.id in window_ids
window_filter = wf window_filter = wf
elif payload_get('output_format') == 'session':
output_session = True
if not output_session:
data = list(boss.list_os_windows(window, tab_filter, window_filter)) data = list(boss.list_os_windows(window, tab_filter, window_filter))
if not payload_get('all_env_vars'): if not payload_get('all_env_vars'):
all_env_blocks: list[dict[str, str]] = [] all_env_blocks: list[dict[str, str]] = []
@@ -79,6 +96,8 @@ Only list the window this command is run in.
for r in remove_env_vars: for r in remove_env_vars:
env.pop(r, None) env.pop(r, None)
return json.dumps(data, indent=2, sort_keys=True) return json.dumps(data, indent=2, sort_keys=True)
else:
return "\n".join(boss.serialize_state_as_session())
ls = LS() ls = LS()

View File

@@ -1,6 +1,7 @@
#!/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 re import re
import stat import stat
@@ -304,6 +305,7 @@ class Tab: # {{{
if lc: if lc:
gw.append(shlex.join(lc)) gw.append(shlex.join(lc))
launch_cmds.extend(gw) launch_cmds.extend(gw)
launch_cmds.append(f'set_layout_state {json.dumps(self.serialize_state()["layout_state"])}\n')
return (ans + launch_cmds) if launch_cmds else [] return (ans + launch_cmds) if launch_cmds else []
def active_window_changed(self) -> None: def active_window_changed(self) -> None:
@@ -1170,7 +1172,7 @@ class TabManager: # {{{
'is_active': tab is active_tab, 'is_active': tab is active_tab,
'title': tab.name or tab.title, 'title': tab.name or tab.title,
'layout': str(tab.current_layout.name), 'layout': str(tab.current_layout.name),
'layout_state': tab.current_layout.layout_state(), 'layout_state': tab.current_layout.serialize(tab.windows),
'layout_opts': tab.current_layout.layout_opts.serialized(), 'layout_opts': tab.current_layout.layout_opts.serialized(),
'enabled_layouts': tab.enabled_layouts, 'enabled_layouts': tab.enabled_layouts,
'windows': windows, 'windows': windows,

View File

@@ -233,6 +233,9 @@ class WindowDict(TypedDict):
id: int id: int
is_focused: bool is_focused: bool
is_active: bool is_active: bool
is_actions_on_close: bool
is_actions_on_focus_change: bool
is_actions_on_removal: bool
title: str title: str
pid: int | None pid: int | None
cwd: str cwd: str
@@ -821,6 +824,9 @@ class Window:
'id': self.id, 'id': self.id,
'is_focused': is_focused, 'is_focused': is_focused,
'is_active': is_active, 'is_active': is_active,
'is_actions_on_close': self in self.actions_on_close,
'is_actions_on_focus_change': self in self.actions_on_focus_change,
'is_actions_on_removal': self in self.actions_on_removal,
'title': self.title, 'title': self.title,
'pid': self.child.pid, 'pid': self.child.pid,
'cwd': self.child.current_cwd or self.child.cwd, 'cwd': self.child.current_cwd or self.child.cwd,
@@ -1978,6 +1984,8 @@ class Window:
ans.append('--hold-after-ssh') ans.append('--hold-after-ssh')
for k, v in self.user_vars.items(): for k, v in self.user_vars.items():
ans.append(f'--var={k}={v}') ans.append(f'--var={k}={v}')
if 'kitty_serialize_window_id' not in self.user_vars:
ans.append(f'--var=kitty_serialize_window_id={self.id}')
ans.extend(self.padding.as_launch_args()) ans.extend(self.padding.as_launch_args())
ans.extend(self.margin.as_launch_args('margin')) ans.extend(self.margin.as_launch_args('margin'))
if self.override_title: if self.override_title: