diff --git a/kitty/rc/__init__.py b/kitty/rc/__init__.py index e69de29bb..8b1378917 100644 --- a/kitty/rc/__init__.py +++ b/kitty/rc/__init__.py @@ -0,0 +1 @@ + diff --git a/kitty/rc/base.py b/kitty/rc/base.py index 0c7bd18ce..ab0f7a239 100644 --- a/kitty/rc/base.py +++ b/kitty/rc/base.py @@ -15,9 +15,10 @@ if TYPE_CHECKING: from kitty.boss import Boss from kitty.window import Window - Boss, Window + from kitty.tabs import Tab + Boss, Window, Tab else: - Boss = Window = None + Boss = Window = Tab = None class NoResponse: @@ -90,24 +91,6 @@ def __call__(self, key: str, opt_name: Optional[str] = None, missing: Any = None ''' -def windows_for_payload(boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> Tuple['Window', ...]: - if payload_get('all'): - windows = tuple(boss.all_windows) - else: - windows = (window or boss.active_window,) - if payload_get('match_window'): - windows = tuple(boss.match_windows(payload_get('match_window'))) - if not windows: - raise MatchError(payload_get('match_window')) - if payload_get('match_tab'): - tabs = tuple(boss.match_tabs(payload_get('match_tab'))) - if not tabs: - raise MatchError(payload_get('match_tab'), 'tabs') - for tab in tabs: - windows += tuple(tab) - return windows - - class RemoteCommand: name: str = '' @@ -139,10 +122,61 @@ def get_default(self, name: str, missing: Any = None) -> Any: return self.defaults.get(name, missing) return missing + def windows_for_match_payload(self, boss: 'Boss', window: Optional['Window'], payload_get: PayloadGetType) -> List['Window']: + if payload_get('all'): + windows = list(boss.all_windows) + else: + if payload_get('self') in (None, True): + window = window or boss.active_window + else: + window = boss.active_window or window + windows = [window] if window else [] + if payload_get('match'): + windows = list(boss.match_windows(payload_get('match'))) + if not windows: + raise MatchError(payload_get('match')) + return windows + + def tabs_for_match_payload(self, boss: 'Boss', window: Optional['Window'], payload_get: PayloadGetType) -> List['Tab']: + if payload_get('all'): + return list(boss.all_tabs) + match = payload_get('match') + if match: + tabs = list(boss.match_tabs(match)) + if not tabs: + raise MatchError(match, 'tabs') + return tabs + if window and payload_get('self') in (None, True): + q = boss.tab_for_window(window) + if q: + return [q] + t = boss.active_tab + if t: + return [t] + return [] + + def windows_for_payload(self, boss: 'Boss', window: Optional['Window'], payload_get: PayloadGetType) -> List['Window']: + if payload_get('all'): + windows = list(boss.all_windows) + else: + window = window or boss.active_window + windows = [window] if window else [] + if payload_get('match_window'): + windows = list(boss.match_windows(payload_get('match_window'))) + if not windows: + raise MatchError(payload_get('match_window')) + if payload_get('match_tab'): + tabs = tuple(boss.match_tabs(payload_get('match_tab'))) + if not tabs: + raise MatchError(payload_get('match_tab'), 'tabs') + for tab in tabs: + windows += list(tab) + return windows + def message_to_kitty(self, global_opts: RCOptions, opts: Any, args: ArgsType) -> PayloadType: raise NotImplementedError() - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: 'Boss', window: Optional['Window'], payload_get: PayloadGetType) -> ResponseType: raise NotImplementedError() diff --git a/kitty/rc/close_tab.py b/kitty/rc/close_tab.py index 60d84736e..963378e74 100644 --- a/kitty/rc/close_tab.py +++ b/kitty/rc/close_tab.py @@ -3,11 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, + RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -32,15 +32,8 @@ class CloseTab(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'match': opts.match, 'self': opts.self} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - tabs = list(boss.match_tabs(match)) - if not tabs: - raise MatchError(match, 'tabs') - else: - tabs = [boss.tab_for_window(window) if window and payload_get('self') else boss.active_tab] - for tab in tabs: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + for tab in self.tabs_for_match_payload(boss, window, payload_get): if window: if tab: boss.close_tab(tab) diff --git a/kitty/rc/close_window.py b/kitty/rc/close_window.py index aa6dfe640..b34a82eec 100644 --- a/kitty/rc/close_window.py +++ b/kitty/rc/close_window.py @@ -3,11 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, + RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -31,15 +31,8 @@ class CloseWindow(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'match': opts.match, 'self': opts.self} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - windows = list(boss.match_windows(match)) - if not windows: - raise MatchError(match) - else: - windows = [window if window and payload_get('self') else boss.active_window] - for window in windows: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + for window in self.windows_for_match_payload(boss, window, payload_get): if window: boss.close_window(window) diff --git a/kitty/rc/create_marker.py b/kitty/rc/create_marker.py index 614b20482..9ca5d1879 100644 --- a/kitty/rc/create_marker.py +++ b/kitty/rc/create_marker.py @@ -2,12 +2,12 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from kitty.config import parse_marker_spec from .base import ( - MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, + MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, Window ) @@ -41,17 +41,9 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg parse_marker_spec(args[0], args[1:]) return {'match': opts.match, 'self': opts.self, 'marker_spec': args} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - windows = tuple(boss.match_windows(match)) - if not windows: - raise MatchError(match) - else: - windows = tuple(window if window and payload_get('self') else boss.active_window) + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: args = payload_get('marker_spec') - - for window in windows: + for window in self.windows_for_match_payload(boss, window, payload_get): window.set_marker(args) diff --git a/kitty/rc/detach_tab.py b/kitty/rc/detach_tab.py index e961b82cc..c3168c647 100644 --- a/kitty/rc/detach_tab.py +++ b/kitty/rc/detach_tab.py @@ -2,7 +2,7 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, @@ -36,15 +36,18 @@ class DetachTab(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'match': opts.match, 'target': opts.target_tab, 'self': opts.self} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: match = payload_get('match') if match: - tabs = tuple(boss.match_tabs(match)) + tabs = list(boss.match_tabs(match)) if not tabs: raise MatchError(match) else: - tab = window.tabref() - tabs = tuple(tab if payload_get('self') and window and tab else boss.active_tab) + if payload_get('self') and window: + tab = window.tabref() or boss.active_tab + else: + tab = boss.active_tab + tabs = [tab] if tab else [] match = payload_get('target_tab') kwargs = {} if match: diff --git a/kitty/rc/detach_window.py b/kitty/rc/detach_window.py index 7609d0cf7..80a0b309f 100644 --- a/kitty/rc/detach_window.py +++ b/kitty/rc/detach_window.py @@ -2,7 +2,7 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional, Union from .base import ( MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, @@ -38,27 +38,20 @@ class DetachWindow(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'match': opts.match, 'target': opts.target_tab, 'self': opts.self} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - windows = tuple(boss.match_windows(match)) - if not windows: - raise MatchError(match) - else: - windows = tuple(window if window and payload_get('self') else boss.active_window) + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + windows = self.windows_for_match_payload(boss, window, payload_get) match = payload_get('target_tab') - kwargs = {} + target_tab_id: Optional[Union[str, int]] = None + newval: Union[str, int] = 'new' if match: if match == 'new': - kwargs['target_tab_id'] = 'new' + target_tab_id = newval else: tabs = tuple(boss.match_tabs(match)) if not tabs: raise MatchError(match, 'tabs') - kwargs['target_tab_id'] = tabs[0].id - if not kwargs: - kwargs['target_os_window_id'] = 'new' - + target_tab_id = tabs[0].id + kwargs = {'target_os_window_id': newval} if target_tab_id is None else {'target_tab_id': target_tab_id} for window in windows: boss._move_window_to(window=window, **kwargs) diff --git a/kitty/rc/disable_ligatures.py b/kitty/rc/disable_ligatures.py index fbab742e7..0d1c86eb2 100644 --- a/kitty/rc/disable_ligatures.py +++ b/kitty/rc/disable_ligatures.py @@ -3,12 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window, - windows_for_payload + PayloadType, RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -51,8 +50,8 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg 'all': opts.all, } - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - windows = windows_for_payload(boss, window, payload_get) + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + windows = self.windows_for_payload(boss, window, payload_get) boss.disable_ligatures_in(windows, payload_get('strategy')) # }}} diff --git a/kitty/rc/focus_tab.py b/kitty/rc/focus_tab.py index 5cd953ae7..145fba408 100644 --- a/kitty/rc/focus_tab.py +++ b/kitty/rc/focus_tab.py @@ -3,11 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, + RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -37,16 +37,10 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg global_opts.no_command_response = True return {'match': opts.match} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - tabs = tuple(boss.match_tabs(match)) - else: - tabs = tuple(boss.tab_for_window(window) if window else boss.active_tab) - if not tabs: - raise MatchError(match, 'tabs') - tab = tabs[0] - boss.set_active_tab(tab) + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + tabs = self.tabs_for_match_payload(boss, window, payload_get) + if tabs: + boss.set_active_tab(tabs[0]) focus_tab = FocusTab() diff --git a/kitty/rc/focus_window.py b/kitty/rc/focus_window.py index 8c618ddd6..49e35b9ae 100644 --- a/kitty/rc/focus_window.py +++ b/kitty/rc/focus_window.py @@ -3,13 +3,13 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from kitty.fast_data_types import focus_os_window from .base import ( - MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, + RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -37,14 +37,8 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg global_opts.no_command_response = True return {'match': opts.match, 'no_response': opts.no_response} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - windows = [window or boss.active_window] - match = payload_get('match') - if match: - windows = [boss.match_windows(match)] - if not windows: - raise MatchError(match) - for window in windows: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + for window in self.windows_for_match_payload(boss, window, payload_get): if window: os_window_id = boss.set_active_window(window) if os_window_id: diff --git a/kitty/rc/get_colors.py b/kitty/rc/get_colors.py index 7c797769c..8f4c7e133 100644 --- a/kitty/rc/get_colors.py +++ b/kitty/rc/get_colors.py @@ -2,14 +2,14 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from kitty.rgb import Color, color_as_sharp, color_from_int from kitty.utils import natsort_ints from .base import ( - MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, + RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -39,14 +39,10 @@ class GetColors(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'configured': opts.configured, 'match': opts.match} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: ans = {k: getattr(boss.opts, k) for k in boss.opts if isinstance(getattr(boss.opts, k), Color)} if not payload_get('configured'): - windows = [window or boss.active_window] - if payload_get('match'): - windows = list(boss.match_windows(payload_get('match'))) - if not windows: - raise MatchError(payload_get('match')) + windows = self.windows_for_match_payload(boss, window, payload_get) ans.update({k: color_from_int(v) for k, v in windows[0].current_colors.items()}) all_keys = natsort_ints(ans) maxlen = max(map(len, all_keys)) diff --git a/kitty/rc/get_text.py b/kitty/rc/get_text.py index 0cd8b3b6e..9462d838a 100644 --- a/kitty/rc/get_text.py +++ b/kitty/rc/get_text.py @@ -3,11 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, + RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -48,15 +48,8 @@ class GetText(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'match': opts.match, 'extent': opts.extent, 'ansi': opts.ansi, 'self': opts.self} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - windows = tuple(boss.match_windows(match)) - if not windows: - raise MatchError(match) - else: - windows = tuple(window if window and payload_get('self') else boss.active_window) - window = windows[0] + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + window = self.windows_for_match_payload(boss, window, payload_get)[0] if payload_get('extent') == 'selection': ans = window.text_for_selection() else: diff --git a/kitty/rc/goto_layout.py b/kitty/rc/goto_layout.py index bd96696b2..d5fa64d6e 100644 --- a/kitty/rc/goto_layout.py +++ b/kitty/rc/goto_layout.py @@ -2,11 +2,11 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, PayloadType, - RCOptions, RemoteCommand, ResponseType, UnknownLayout, Window + MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, + RemoteCommand, ResponseType, UnknownLayout, Window ) if TYPE_CHECKING: @@ -34,17 +34,8 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg except IndexError: raise self.fatal('No layout specified') - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - if match == 'all': - tabs = tuple(boss.all_tabs) - else: - tabs = tuple(boss.match_tabs(match)) - if not tabs: - raise MatchError(match, 'tabs') - else: - tabs = tuple(boss.tab_for_window(window) if window else boss.active_tab) + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + tabs = self.tabs_for_match_payload(boss, window, payload_get) for tab in tabs: if tab: try: diff --git a/kitty/rc/kitten.py b/kitty/rc/kitten.py index 24d6afca8..48f4001bb 100644 --- a/kitty/rc/kitten.py +++ b/kitty/rc/kitten.py @@ -2,7 +2,7 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, @@ -36,7 +36,7 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg self.fatal('Must specify kitten name') return {'match': opts.match, 'args': list(args)[1:], 'kitten': args[0]} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: windows = [window or boss.active_window] match = payload_get('match') if match: diff --git a/kitty/rc/last_used_layout.py b/kitty/rc/last_used_layout.py index fcb01a61b..fa0d98262 100644 --- a/kitty/rc/last_used_layout.py +++ b/kitty/rc/last_used_layout.py @@ -3,11 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, + RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -17,30 +17,23 @@ class LastUsedLayout(RemoteCommand): ''' match: Which tab to change the layout of + all: Boolean to match all tabs ''' short_desc = 'Switch to the last used layout' desc = ( 'Switch to the last used window layout in the specified tab (or the active tab if not specified).' - ' You can use special match value :italic:`all` to set the layout in all tabs.' ) - options_spec = MATCH_TAB_OPTION + options_spec = '''\ +--all -a +type=bool-set +Change the layout in all tabs.''' + '\n\n\n' + MATCH_TAB_OPTION def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: - return {'match': opts.match} + return {'match': opts.match, 'all': opts.all} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - if match == 'all': - tabs = tuple(boss.all_tabs) - else: - tabs = tuple(boss.match_tabs(match)) - if not tabs: - raise MatchError(match, 'tabs') - else: - tabs = tuple(boss.tab_for_window(window) if window else boss.active_tab) - for tab in tabs: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + for tab in self.tabs_for_match_payload(boss, window, payload_get): if tab: tab.last_used_layout() diff --git a/kitty/rc/launch.py b/kitty/rc/launch.py index c3fdb4684..017304afb 100644 --- a/kitty/rc/launch.py +++ b/kitty/rc/launch.py @@ -3,7 +3,7 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from kitty.launch import ( LaunchCLIOptions, launch as do_launch, options_spec as launch_options_spec, @@ -11,7 +11,7 @@ ) from .base import ( - MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, PayloadType, + MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, Window ) @@ -70,7 +70,7 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg ans[attr] = val return ans - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: default_opts = parse_launch_args()[0] opts = LaunchCLIOptions() for key, default_value in default_opts.__dict__.items(): @@ -78,16 +78,7 @@ def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: Paylo if val is None: val = default_value setattr(opts, key, val) - match = payload_get('match') - if match: - tabs = list(boss.match_tabs(match)) - if not tabs: - raise MatchError(match, 'tabs') - else: - tabs = [boss.active_tab] - if payload_get('self') and window and window.tabref(): - tabs = [window.tabref()] - tab = tabs[0] + tab = self.tabs_for_match_payload(boss, window, payload_get)[0] w = do_launch(boss, opts, payload_get('args') or [], target_tab=tab) return None if payload_get('no_response') else str(getattr(w, 'id', 0)) diff --git a/kitty/rc/ls.py b/kitty/rc/ls.py index a954d413a..0c0cd7179 100644 --- a/kitty/rc/ls.py +++ b/kitty/rc/ls.py @@ -3,7 +3,7 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal import json -from typing import Any +from typing import Any, Optional from kitty.constants import appname @@ -32,7 +32,7 @@ class LS(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: Any, args: ArgsType) -> PayloadType: pass - def response_from_kitty(self, boss: 'Boss', window: '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()) return json.dumps(data, indent=2, sort_keys=True) diff --git a/kitty/rc/new_window.py b/kitty/rc/new_window.py index 7ccc744bf..455e4fc6e 100644 --- a/kitty/rc/new_window.py +++ b/kitty/rc/new_window.py @@ -2,14 +2,14 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from kitty.fast_data_types import focus_os_window from kitty.tabs import SpecialWindow from .base import ( - MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, PayloadType, - RCOptions, RemoteCommand, ResponseType, Window + MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, + RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -86,36 +86,29 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg 'window_type': opts.window_type, 'no_response': opts.no_response, 'keep_focus': opts.keep_focus, 'args': args or []} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: w = SpecialWindow(cmd=payload_get('args') or None, override_title=payload_get('title'), cwd=payload_get('cwd')) old_window = boss.active_window if payload_get('new_tab'): boss._new_tab(w) tab = boss.active_tab - if payload_get('tab_title'): + if payload_get('tab_title') and tab: tab.set_title(payload_get('tab_title')) - wid = boss.active_window.id + aw = boss.active_window if payload_get('keep_focus') and old_window: boss.set_active_window(old_window) - return None if payload_get('no_response') else str(wid) + return None if not aw or payload_get('no_response') else str(aw.id) if payload_get('window_type') == 'os': boss._new_os_window(w) - wid = boss.active_window.id + aw = boss.active_window if payload_get('keep_focus') and old_window: os_window_id = boss.set_active_window(old_window) if os_window_id: focus_os_window(os_window_id) - return None if payload_get('no_response') else str(wid) + return None if not aw or payload_get('no_response') else str(aw.id) - match = payload_get('match') - if match: - tabs = list(boss.match_tabs(match)) - if not tabs: - raise MatchError(match, 'tabs') - else: - tabs = [boss.active_tab] - tab = tabs[0] + tab = self.tabs_for_match_payload(boss, window, payload_get)[0] ans = tab.new_special_window(w) if payload_get('keep_focus') and old_window: boss.set_active_window(old_window) diff --git a/kitty/rc/remove_marker.py b/kitty/rc/remove_marker.py index eb5a04aad..719876408 100644 --- a/kitty/rc/remove_marker.py +++ b/kitty/rc/remove_marker.py @@ -3,11 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, + RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -32,16 +32,8 @@ class RemoveMarker(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'match': opts.match, 'self': opts.self} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - windows = tuple(boss.match_windows(match)) - if not windows: - raise MatchError(match) - else: - windows = tuple(window if window and payload_get('self') else boss.active_window) - - for window in windows: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + for window in self.windows_for_match_payload(boss, window, payload_get): window.remove_marker() diff --git a/kitty/rc/resize_window.py b/kitty/rc/resize_window.py index 7b8d4428b..d0b167b7b 100644 --- a/kitty/rc/resize_window.py +++ b/kitty/rc/resize_window.py @@ -2,10 +2,10 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, + MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, Window ) @@ -53,14 +53,8 @@ class ResizeWindow(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'match': opts.match, 'increment': opts.increment, 'axis': opts.axis, 'self': opts.self} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - windows = list(boss.match_windows(match)) - if not windows: - raise MatchError(match) - else: - windows = [window if window and payload_get('self') else boss.active_window] + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + windows = self.windows_for_match_payload(boss, window, payload_get) resized = False if windows and windows[0]: resized = boss.resize_layout_window( diff --git a/kitty/rc/scroll_window.py b/kitty/rc/scroll_window.py index dc8ed695a..2eaf24e6f 100644 --- a/kitty/rc/scroll_window.py +++ b/kitty/rc/scroll_window.py @@ -45,7 +45,7 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg return {'match': opts.match, 'amount': amount} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: windows = [window or boss.active_window] match = payload_get('match') amt = payload_get('amount') diff --git a/kitty/rc/send_text.py b/kitty/rc/send_text.py index 3a525ebc0..48c7a5bc8 100644 --- a/kitty/rc/send_text.py +++ b/kitty/rc/send_text.py @@ -5,7 +5,7 @@ import base64 import os import sys -from typing import TYPE_CHECKING, Dict, Generator +from typing import TYPE_CHECKING, Dict, Generator, Optional from kitty.config import parse_send_text_bytes @@ -108,7 +108,7 @@ def chain() -> Generator[Dict, None, None]: yield from src return chain() - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: windows = [boss.active_window] match = payload_get('match') if match: diff --git a/kitty/rc/set_background_image.py b/kitty/rc/set_background_image.py index 3095476f3..0de0ef5e6 100644 --- a/kitty/rc/set_background_image.py +++ b/kitty/rc/set_background_image.py @@ -10,8 +10,7 @@ from .base import ( MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, - RCOptions, RemoteCommand, ResponseType, Window, - windows_for_payload + RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -90,7 +89,7 @@ def file_pipe(path: str) -> Generator[Dict, None, None]: yield ret return file_pipe(path) - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: data = payload_get('data') if data != '-': img_id = payload_get('img_id') @@ -102,7 +101,7 @@ def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: Paylo set_background_image.current_file_obj.write(standard_b64decode(data)) return None - windows = windows_for_payload(boss, window, payload_get) + windows = self.windows_for_payload(boss, window, payload_get) os_windows = tuple({w.os_window_id for w in windows}) layout = payload_get('layout') if data == '-': diff --git a/kitty/rc/set_background_opacity.py b/kitty/rc/set_background_opacity.py index 8686cda96..9db59b3a2 100644 --- a/kitty/rc/set_background_opacity.py +++ b/kitty/rc/set_background_opacity.py @@ -3,12 +3,12 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, OpacityError, PayloadGetType, PayloadType, RCOptions, RemoteCommand, ResponseType, - Window, windows_for_payload + Window ) if TYPE_CHECKING: @@ -47,10 +47,10 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg 'all': opts.all, 'match_tab': opts.match_tab } - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: if not boss.opts.dynamic_background_opacity: raise OpacityError('You must turn on the dynamic_background_opacity option in kitty.conf to be able to set background opacity') - windows = windows_for_payload(boss, window, payload_get) + windows = self.windows_for_payload(boss, window, payload_get) for os_window_id in {w.os_window_id for w in windows}: boss._set_os_window_background_opacity(os_window_id, payload_get('opacity')) diff --git a/kitty/rc/set_colors.py b/kitty/rc/set_colors.py index 91902b498..be6781d14 100644 --- a/kitty/rc/set_colors.py +++ b/kitty/rc/set_colors.py @@ -12,8 +12,7 @@ from .base import ( MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window, - windows_for_payload + PayloadType, RCOptions, RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -84,8 +83,8 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg del ans['dummy'] return ans - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - windows = windows_for_payload(boss, window, payload_get) + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + windows = self.windows_for_payload(boss, window, payload_get) colors = payload_get('colors') cursor_text_color = payload_get('cursor_text_color') or False if payload_get('reset'): diff --git a/kitty/rc/set_font_size.py b/kitty/rc/set_font_size.py index a17ec2fb0..b88a81b5b 100644 --- a/kitty/rc/set_font_size.py +++ b/kitty/rc/set_font_size.py @@ -2,7 +2,7 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, RemoteCommand, @@ -45,7 +45,7 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg inc = fs[0] if fs and fs[0] in '+-' else None return {'size': abs(float(fs)), 'all': opts.all, 'increment_op': inc} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: boss.change_font_size( payload_get('all'), payload_get('increment_op'), payload_get('size')) diff --git a/kitty/rc/set_tab_title.py b/kitty/rc/set_tab_title.py index 8e6b39052..3959770e0 100644 --- a/kitty/rc/set_tab_title.py +++ b/kitty/rc/set_tab_title.py @@ -3,11 +3,11 @@ # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( - MATCH_TAB_OPTION, ArgsType, Boss, MatchError, PayloadGetType, - PayloadType, RCOptions, RemoteCommand, ResponseType, Window + MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions, + RemoteCommand, ResponseType, Window ) if TYPE_CHECKING: @@ -34,15 +34,8 @@ class SetTabTitle(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'title': ' '.join(args), 'match': opts.match} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - tabs = tuple(boss.match_tabs(match)) - if not tabs: - raise MatchError(match, 'tabs') - else: - tabs = tuple(boss.tab_for_window(window) if window else boss.active_tab) - for tab in tabs: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: + for tab in self.tabs_for_match_payload(boss, window, payload_get): if tab: tab.set_title(payload_get('title')) diff --git a/kitty/rc/set_window_title.py b/kitty/rc/set_window_title.py index 4c2af7e58..f4ff237c8 100644 --- a/kitty/rc/set_window_title.py +++ b/kitty/rc/set_window_title.py @@ -2,7 +2,7 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from .base import ( MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError, PayloadGetType, @@ -40,7 +40,7 @@ class SetWindowTitle(RemoteCommand): def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: return {'title': ' '.join(args), 'match': opts.match, 'temporary': opts.temporary} - def response_from_kitty(self, boss: 'Boss', window: 'Window', payload_get: PayloadGetType) -> ResponseType: + def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: windows = [window or boss.active_window] match = payload_get('match') if match: