mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-24 09:18:08 +02:00
@@ -45,6 +45,8 @@ Detailed list of changes
|
|||||||
|
|
||||||
- kitten @ ls: Add user variables set on windows to the output (:iss:`6502`)
|
- kitten @ ls: Add user variables set on windows to the output (:iss:`6502`)
|
||||||
|
|
||||||
|
- kitten @ ls: Allow limiting output to matched windows/tabs (:iss:`6520`)
|
||||||
|
|
||||||
- X11: Print an error to STDERR instead of refusing to start when the user sets a custom window icon larger than 128128 (:iss:`6507`)
|
- X11: Print an error to STDERR instead of refusing to start when the user sets a custom window icon larger than 128128 (:iss:`6507`)
|
||||||
|
|
||||||
0.29.2 [2023-07-27]
|
0.29.2 [2023-07-27]
|
||||||
|
|||||||
@@ -428,20 +428,26 @@ class Boss:
|
|||||||
self.os_window_map[os_window_id] = tm
|
self.os_window_map[os_window_id] = tm
|
||||||
return os_window_id
|
return os_window_id
|
||||||
|
|
||||||
def list_os_windows(self, self_window: Optional[Window] = None) -> Iterator[OSWindowDict]:
|
def list_os_windows(
|
||||||
|
self, self_window: Optional[Window] = None,
|
||||||
|
tab_filter: Optional[Callable[[Tab], bool]] = None,
|
||||||
|
window_filter: Optional[Callable[[Window], bool]] = None
|
||||||
|
) -> Iterator[OSWindowDict]:
|
||||||
with cached_process_data():
|
with cached_process_data():
|
||||||
active_tab_manager = self.active_tab_manager
|
active_tab_manager = self.active_tab_manager
|
||||||
for os_window_id, tm in self.os_window_map.items():
|
for os_window_id, tm in self.os_window_map.items():
|
||||||
yield {
|
tabs = list(tm.list_tabs(self_window, tab_filter, window_filter))
|
||||||
'id': os_window_id,
|
if tabs:
|
||||||
'platform_window_id': platform_window_id(os_window_id),
|
yield {
|
||||||
'is_active': tm is active_tab_manager,
|
'id': os_window_id,
|
||||||
'is_focused': current_focused_os_window_id() == os_window_id,
|
'platform_window_id': platform_window_id(os_window_id),
|
||||||
'last_focused': os_window_id == last_focused_os_window_id(),
|
'is_active': tm is active_tab_manager,
|
||||||
'tabs': list(tm.list_tabs(self_window)),
|
'is_focused': current_focused_os_window_id() == os_window_id,
|
||||||
'wm_class': tm.wm_class,
|
'last_focused': os_window_id == last_focused_os_window_id(),
|
||||||
'wm_name': tm.wm_name
|
'tabs': tabs,
|
||||||
}
|
'wm_class': tm.wm_class,
|
||||||
|
'wm_name': tm.wm_name
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def all_tab_managers(self) -> Iterator[TabManager]:
|
def all_tab_managers(self) -> Iterator[TabManager]:
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ from kitty.types import AsyncResponse
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from kitty.boss import Boss as B
|
from kitty.boss import Boss as B
|
||||||
from kitty.tabs import Tab
|
from kitty.tabs import Tab as T
|
||||||
from kitty.window import Window as W
|
from kitty.window import Window as W
|
||||||
Window = W
|
Window = W
|
||||||
Boss = B
|
Boss = B
|
||||||
Tab
|
Tab = T
|
||||||
else:
|
else:
|
||||||
Boss = Window = Tab = None
|
Boss = Window = Tab = None
|
||||||
RCOptions = R
|
RCOptions = R
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Set, Tuple
|
||||||
|
|
||||||
from kitty.constants import appname
|
from kitty.constants import appname
|
||||||
|
|
||||||
from .base import ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, Window
|
from .base import MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, Tab, Window
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from kitty.cli_stub import LSRCOptions as CLIOptions
|
from kitty.cli_stub import LSRCOptions as CLIOptions
|
||||||
@@ -15,29 +15,51 @@ if TYPE_CHECKING:
|
|||||||
class LS(RemoteCommand):
|
class LS(RemoteCommand):
|
||||||
protocol_spec = __doc__ = '''
|
protocol_spec = __doc__ = '''
|
||||||
all_env_vars/bool: Whether to send all environment variables for every window rather than just differing ones
|
all_env_vars/bool: Whether to send all environment variables for every window rather than just differing ones
|
||||||
|
match/str: Window 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
|
||||||
'''
|
'''
|
||||||
|
|
||||||
short_desc = 'List all tabs/windows'
|
short_desc = 'List tabs/windows'
|
||||||
desc = (
|
desc = (
|
||||||
'List all windows. The list is returned as JSON tree. The top-level is a list of'
|
'List windows. The list is returned as JSON tree. The top-level is a list of'
|
||||||
f' operating system {appname} windows. Each OS window has an :italic:`id` and a list'
|
f' operating system {appname} windows. Each OS window has an :italic:`id` and a list'
|
||||||
' of :italic:`tabs`. Each tab has its own :italic:`id`, a :italic:`title` and a list of :italic:`windows`.'
|
' of :italic:`tabs`. Each tab has its own :italic:`id`, a :italic:`title` and a list of :italic:`windows`.'
|
||||||
' Each window has an :italic:`id`, :italic:`title`, :italic:`current working directory`, :italic:`process id (PID)`,'
|
' Each window has an :italic:`id`, :italic:`title`, :italic:`current working directory`, :italic:`process id (PID)`,'
|
||||||
' :italic:`command-line` and :italic:`environment` of the process running in the window. Additionally, when'
|
' :italic:`command-line` and :italic:`environment` of the process running in the window. Additionally, when'
|
||||||
' running the command inside a kitty window, that window can be identified by the :italic:`is_self` parameter.\n\n'
|
' running the command inside a kitty window, that window can be identified by the :italic:`is_self` parameter.\n\n'
|
||||||
'You can use these criteria to select windows/tabs for the other commands.'
|
'You can use these criteria to select windows/tabs for the other commands.\n\n'
|
||||||
|
'You can limit the windows/tabs in the output by using the :option:`--match` and :option:`--match-tab` options.'
|
||||||
)
|
)
|
||||||
options_spec = '''\
|
options_spec = '''\
|
||||||
--all-env-vars
|
--all-env-vars
|
||||||
type=bool-set
|
type=bool-set
|
||||||
Show all environment variables in output, not just differing ones.
|
Show all environment variables in output, not just differing ones.
|
||||||
'''
|
|
||||||
|
|
||||||
|
--self
|
||||||
|
type=bool-set
|
||||||
|
Only list the window this command is run in.
|
||||||
|
''' + '\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:
|
||||||
return {'all_env_vars': opts.all_env_vars}
|
return {'all_env_vars': opts.all_env_vars, 'match': opts.match, 'match_tab': opts.match_tab}
|
||||||
|
|
||||||
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType:
|
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType:
|
||||||
data = list(boss.list_os_windows(window))
|
tab_filter: Optional[Callable[[Tab], bool]] = None
|
||||||
|
window_filter: Optional[Callable[[Window], bool]] = None
|
||||||
|
|
||||||
|
if payload_get('match') is not None:
|
||||||
|
window_ids = frozenset(w.id for w in self.windows_for_match_payload(boss, window, payload_get))
|
||||||
|
def wf(w: Window) -> bool:
|
||||||
|
return w.id in window_ids
|
||||||
|
window_filter = wf
|
||||||
|
if payload_get('match_tab') is not None:
|
||||||
|
tab_ids = frozenset(w.id for w in self.tabs_for_match_payload(boss, window, payload_get))
|
||||||
|
def tf(w: Tab) -> bool:
|
||||||
|
return w.id in tab_ids
|
||||||
|
tab_filter = tf
|
||||||
|
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]] = []
|
||||||
common_env_vars: Set[Tuple[str, str]] = set()
|
common_env_vars: Set[Tuple[str, str]] = set()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from operator import attrgetter
|
|||||||
from time import monotonic
|
from time import monotonic
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
|
Callable,
|
||||||
Deque,
|
Deque,
|
||||||
Dict,
|
Dict,
|
||||||
Generator,
|
Generator,
|
||||||
@@ -770,13 +771,14 @@ class Tab: # {{{
|
|||||||
def move_window_backward(self) -> None:
|
def move_window_backward(self) -> None:
|
||||||
self.move_window(-1)
|
self.move_window(-1)
|
||||||
|
|
||||||
def list_windows(self, self_window: Optional[Window] = None) -> Generator[WindowDict, None, None]:
|
def list_windows(self, self_window: Optional[Window] = None, window_filter: Optional[Callable[[Window], bool]] = None) -> Generator[WindowDict, None, None]:
|
||||||
active_window = self.active_window
|
active_window = self.active_window
|
||||||
for w in self:
|
for w in self:
|
||||||
yield w.as_dict(
|
if window_filter is None or window_filter(w):
|
||||||
is_active=w is active_window,
|
yield w.as_dict(
|
||||||
is_focused=w.os_window_id == current_focused_os_window_id() and w is active_window,
|
is_active=w is active_window,
|
||||||
is_self=w is self_window)
|
is_focused=w.os_window_id == current_focused_os_window_id() and w is active_window,
|
||||||
|
is_self=w is self_window)
|
||||||
|
|
||||||
def matches_query(self, field: str, query: str, active_tab_manager: Optional['TabManager'] = None) -> bool:
|
def matches_query(self, field: str, query: str, active_tab_manager: Optional['TabManager'] = None) -> bool:
|
||||||
if field == 'title':
|
if field == 'title':
|
||||||
@@ -1011,21 +1013,28 @@ class TabManager: # {{{
|
|||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return len(self.tabs)
|
return len(self.tabs)
|
||||||
|
|
||||||
def list_tabs(self, self_window: Optional[Window] = None) -> Generator[TabDict, None, None]:
|
def list_tabs(
|
||||||
|
self, self_window: Optional[Window] = None,
|
||||||
|
tab_filter: Optional[Callable[[Tab], bool]] = None,
|
||||||
|
window_filter: Optional[Callable[[Window], bool]] = None
|
||||||
|
) -> Generator[TabDict, None, None]:
|
||||||
active_tab = self.active_tab
|
active_tab = self.active_tab
|
||||||
for tab in self:
|
for tab in self:
|
||||||
yield {
|
if tab_filter is None or tab_filter(tab):
|
||||||
'id': tab.id,
|
windows = list(tab.list_windows(self_window, window_filter))
|
||||||
'is_focused': tab is active_tab and tab.os_window_id == current_focused_os_window_id(),
|
if windows:
|
||||||
'is_active': tab is active_tab,
|
yield {
|
||||||
'title': tab.name or tab.title,
|
'id': tab.id,
|
||||||
'layout': str(tab.current_layout.name),
|
'is_focused': tab is active_tab and tab.os_window_id == current_focused_os_window_id(),
|
||||||
'layout_state': tab.current_layout.layout_state(),
|
'is_active': tab is active_tab,
|
||||||
'layout_opts': tab.current_layout.layout_opts.serialized(),
|
'title': tab.name or tab.title,
|
||||||
'enabled_layouts': tab.enabled_layouts,
|
'layout': str(tab.current_layout.name),
|
||||||
'windows': list(tab.list_windows(self_window)),
|
'layout_state': tab.current_layout.layout_state(),
|
||||||
'active_window_history': list(tab.windows.active_window_history),
|
'layout_opts': tab.current_layout.layout_opts.serialized(),
|
||||||
}
|
'enabled_layouts': tab.enabled_layouts,
|
||||||
|
'windows': windows,
|
||||||
|
'active_window_history': list(tab.windows.active_window_history),
|
||||||
|
}
|
||||||
|
|
||||||
def serialize_state(self) -> Dict[str, Any]:
|
def serialize_state(self) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user