From 0719c7f8bb242fefe5729a53efc3b57f16082eb1 Mon Sep 17 00:00:00 2001 From: pagedown Date: Sun, 1 May 2022 23:04:50 +0800 Subject: [PATCH] DRYer: Use window matching function in remote commands --- kitty/rc/create_marker.py | 3 ++- kitty/rc/detach_tab.py | 19 +++++-------------- kitty/rc/detach_window.py | 3 ++- kitty/rc/get_colors.py | 11 ++++++----- kitty/rc/get_text.py | 6 +++++- kitty/rc/kitten.py | 8 +------- kitty/rc/launch.py | 8 +++++--- kitty/rc/new_window.py | 12 +++++++----- kitty/rc/remove_marker.py | 3 ++- kitty/rc/resize_os_window.py | 2 +- kitty/rc/scroll_window.py | 11 +++-------- kitty/rc/set_background_image.py | 2 +- kitty/rc/set_background_opacity.py | 2 +- kitty/rc/set_colors.py | 9 +++++---- kitty/rc/set_spacing.py | 9 +++++---- kitty/rc/set_window_logo.py | 3 ++- kitty/rc/set_window_title.py | 10 +++------- kitty/rc/signal_child.py | 11 +++-------- 18 files changed, 59 insertions(+), 73 deletions(-) diff --git a/kitty/rc/create_marker.py b/kitty/rc/create_marker.py index 82077bbe1..7b5d04cc5 100644 --- a/kitty/rc/create_marker.py +++ b/kitty/rc/create_marker.py @@ -46,7 +46,8 @@ Apply marker to the window this command is run in, rather than the active window def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: args = payload_get('marker_spec') for window in self.windows_for_match_payload(boss, window, payload_get): - window.set_marker(args) + if window: + window.set_marker(args) return None diff --git a/kitty/rc/detach_tab.py b/kitty/rc/detach_tab.py index 2174a68ee..9fd3926b8 100644 --- a/kitty/rc/detach_tab.py +++ b/kitty/rc/detach_tab.py @@ -36,27 +36,18 @@ Detach the tab this command is run in, rather than the active tab. return {'match': opts.match, 'target_tab': opts.target_tab, 'self': opts.self} def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: - match = payload_get('match') - if match: - tabs = list(boss.match_tabs(match)) - if not tabs: - raise MatchError(match) - else: - 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: targets = tuple(boss.match_tabs(match)) if not targets: raise MatchError(match, 'tabs') - kwargs['target_os_window_id'] = targets[0].os_window_id + if targets[0]: + kwargs['target_os_window_id'] = targets[0].os_window_id - for tab in tabs: - boss._move_tab_to(tab=tab, **kwargs) + for tab in self.tabs_for_match_payload(boss, window, payload_get): + if tab: + boss._move_tab_to(tab=tab, **kwargs) return None diff --git a/kitty/rc/detach_window.py b/kitty/rc/detach_window.py index 97c99b6e3..8529ba3ba 100644 --- a/kitty/rc/detach_window.py +++ b/kitty/rc/detach_window.py @@ -54,7 +54,8 @@ Detach the window this command is run in, rather than the active window. 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) + if window: + boss._move_window_to(window=window, **kwargs) return None diff --git a/kitty/rc/get_colors.py b/kitty/rc/get_colors.py index 08fff0ede..b510beed5 100644 --- a/kitty/rc/get_colors.py +++ b/kitty/rc/get_colors.py @@ -45,11 +45,12 @@ configured colors. ans = {k: getattr(opts, k) for k in opts if isinstance(getattr(opts, k), Color)} if not payload_get('configured'): windows = self.windows_for_match_payload(boss, window, payload_get) - for k, v in windows[0].current_colors.items(): - if v is None: - ans.pop(k, None) - else: - ans[k] = color_from_int(v) + if windows and windows[0]: + for k, v in windows[0].current_colors.items(): + if v is None: + ans.pop(k, None) + else: + ans[k] = color_from_int(v) all_keys = natsort_ints(ans) maxlen = max(map(len, all_keys)) return '\n'.join(('{:%ds} {}' % maxlen).format(key, color_as_sharp(ans[key])) for key in all_keys) diff --git a/kitty/rc/get_text.py b/kitty/rc/get_text.py index 2ad8e6b54..401867c48 100644 --- a/kitty/rc/get_text.py +++ b/kitty/rc/get_text.py @@ -80,7 +80,11 @@ Get text from the window this command is run in, rather than the active window. def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: from kitty.window import CommandOutput - window = self.windows_for_match_payload(boss, window, payload_get)[0] + windows = self.windows_for_match_payload(boss, window, payload_get) + if windows and windows[0]: + window = windows[0] + else: + return None if payload_get('extent') == 'selection': ans = window.text_for_selection(as_ansi=payload_get('ansi')) elif payload_get('extent') == 'first_cmd_output_on_screen': diff --git a/kitty/rc/kitten.py b/kitty/rc/kitten.py index ae857977c..38d0bae97 100644 --- a/kitty/rc/kitten.py +++ b/kitty/rc/kitten.py @@ -38,14 +38,8 @@ class Kitten(RemoteCommand): return {'match': opts.match, 'args': list(args)[1:], 'kitten': args[0]} 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: - windows = list(boss.match_windows(match)) - if not windows: - raise MatchError(match) retval = None - for window in windows: + for window in self.windows_for_match_payload(boss, window, payload_get): if window: retval = boss._run_kitten(payload_get('kitten'), args=tuple(payload_get('args') or ()), window=window) break diff --git a/kitty/rc/launch.py b/kitty/rc/launch.py index 4d9706340..45bff9beb 100644 --- a/kitty/rc/launch.py +++ b/kitty/rc/launch.py @@ -81,9 +81,11 @@ instead of the active tab if val is None: val = default_value setattr(opts, key, val) - 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)) + tabs = self.tabs_for_match_payload(boss, window, payload_get) + if tabs and tabs[0]: + w = do_launch(boss, opts, payload_get('args') or [], target_tab=tabs[0]) + return None if payload_get('no_response') else str(getattr(w, 'id', 0)) + return None launch = Launch() diff --git a/kitty/rc/new_window.py b/kitty/rc/new_window.py index 2448750dc..8884e606d 100644 --- a/kitty/rc/new_window.py +++ b/kitty/rc/new_window.py @@ -105,11 +105,13 @@ the id of the new window will not be printed out. focus_os_window(os_window_id) return None if not aw or payload_get('no_response') else str(aw.id) - 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) - return None if payload_get('no_response') else str(ans.id) + tabs = self.tabs_for_match_payload(boss, window, payload_get) + if tabs and tabs[0]: + ans = tabs[0].new_special_window(w) + if payload_get('keep_focus') and old_window: + boss.set_active_window(old_window) + return None if payload_get('no_response') else str(ans.id) + return None new_window = NewWindow() diff --git a/kitty/rc/remove_marker.py b/kitty/rc/remove_marker.py index b60042cc7..3d30ed489 100644 --- a/kitty/rc/remove_marker.py +++ b/kitty/rc/remove_marker.py @@ -33,7 +33,8 @@ Apply marker to the window this command is run in, rather than the active window 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() + if window: + window.remove_marker() return None diff --git a/kitty/rc/resize_os_window.py b/kitty/rc/resize_os_window.py index 7a79b9410..62a1d5dd9 100644 --- a/kitty/rc/resize_os_window.py +++ b/kitty/rc/resize_os_window.py @@ -84,7 +84,7 @@ using this option means that you will not be notified of failures. windows = self.windows_for_match_payload(boss, window, payload_get) if windows: ac = payload_get('action') - for os_window_id in {w.os_window_id for w in windows}: + for os_window_id in {w.os_window_id for w in windows if w}: if ac == 'resize': boss.resize_os_window( os_window_id, width=payload_get('width'), height=payload_get('height'), diff --git a/kitty/rc/scroll_window.py b/kitty/rc/scroll_window.py index c631c5897..e92bc975c 100644 --- a/kitty/rc/scroll_window.py +++ b/kitty/rc/scroll_window.py @@ -46,17 +46,12 @@ class ScrollWindow(RemoteCommand): q = int(amt.rstrip('+-plu')) amount = q * mult, 'p' if pages else ('u' if unscroll else 'l') - return {'match': opts.match, 'amount': amount} + # defaults to scroll the window this command is run in + return {'match': opts.match, 'amount': amount, 'self': True} 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') - if match: - windows = list(boss.match_windows(match)) - if not windows: - raise MatchError(match) - for window in windows: + for window in self.windows_for_match_payload(boss, window, payload_get): if window: if amt[0] in ('start', 'end'): getattr(window, {'start': 'scroll_home'}.get(amt[0], 'scroll_end'))() diff --git a/kitty/rc/set_background_image.py b/kitty/rc/set_background_image.py index 491e11f49..b0019bc1a 100644 --- a/kitty/rc/set_background_image.py +++ b/kitty/rc/set_background_image.py @@ -104,7 +104,7 @@ failed, the command will exit with a success code. return AsyncResponse() windows = self.windows_for_payload(boss, window, payload_get) - os_windows = tuple({w.os_window_id for w in windows}) + os_windows = tuple({w.os_window_id for w in windows if w}) layout = payload_get('layout') if data == '-': path = None diff --git a/kitty/rc/set_background_opacity.py b/kitty/rc/set_background_opacity.py index bfc437931..b68136d79 100644 --- a/kitty/rc/set_background_opacity.py +++ b/kitty/rc/set_background_opacity.py @@ -51,7 +51,7 @@ cause background opacity to be changed in all windows. if not get_options().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 = self.windows_for_payload(boss, window, payload_get) - for os_window_id in {w.os_window_id for w in windows}: + for os_window_id in {w.os_window_id for w in windows if w}: boss._set_os_window_background_opacity(os_window_id, payload_get('opacity')) return None diff --git a/kitty/rc/set_colors.py b/kitty/rc/set_colors.py index 6faea427d..14b8eb9e4 100644 --- a/kitty/rc/set_colors.py +++ b/kitty/rc/set_colors.py @@ -113,14 +113,15 @@ this option, any color arguments are ignored and :option:`kitty @ set-colors --c if payload_get('reset'): colors = {k: int(v) for k, v in boss.startup_colors.items()} colors['cursor_text_color'] = None if boss.startup_cursor_text_color is None else int(boss.startup_cursor_text_color) - profiles = tuple(w.screen.color_profile for w in windows) + profiles = tuple(w.screen.color_profile for w in windows if w) patch_color_profiles(colors, profiles, payload_get('configured')) boss.patch_colors(colors, payload_get('configured')) default_bg_changed = 'background' in colors for w in windows: - if default_bg_changed: - boss.default_bg_changed_for(w.id) - w.refresh() + if w: + if default_bg_changed: + boss.default_bg_changed_for(w.id) + w.refresh() return None diff --git a/kitty/rc/set_spacing.py b/kitty/rc/set_spacing.py index 318bbae52..792d66b7d 100644 --- a/kitty/rc/set_spacing.py +++ b/kitty/rc/set_spacing.py @@ -112,10 +112,11 @@ windows). patch_configured_edges(get_options(), settings) for w in windows: - patch_window_edges(w, settings) - tab = w.tabref() - if tab is not None: - dirtied_tabs[tab.id] = tab + if w: + patch_window_edges(w, settings) + tab = w.tabref() + if tab is not None: + dirtied_tabs[tab.id] = tab for tab in dirtied_tabs.values(): tab.relayout() diff --git a/kitty/rc/set_window_logo.py b/kitty/rc/set_window_logo.py index c188fa865..3091bcc44 100644 --- a/kitty/rc/set_window_logo.py +++ b/kitty/rc/set_window_logo.py @@ -113,7 +113,8 @@ failed, the command will exit with a success code. alpha = float(payload_get('alpha', '-1')) position = payload_get('position') or '' for window in self.windows_for_match_payload(boss, window, payload_get): - window.set_logo(path, position, alpha) + if window: + window.set_logo(path, position, alpha) return None diff --git a/kitty/rc/set_window_title.py b/kitty/rc/set_window_title.py index a5c626a6b..a587cfa1e 100644 --- a/kitty/rc/set_window_title.py +++ b/kitty/rc/set_window_title.py @@ -40,16 +40,12 @@ again. If you want to allow other programs to change it afterwards, use this opt title = ' '.join(args) if title: ans['title'] = title + # defaults to set the window title this command is run in + ans['self'] = True return ans 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: - windows = list(boss.match_windows(match)) - if not windows: - raise MatchError(match) - for window in windows: + for window in self.windows_for_match_payload(boss, window, payload_get): if window: if payload_get('temporary'): window.override_title = None diff --git a/kitty/rc/signal_child.py b/kitty/rc/signal_child.py index 5efa5bf28..2d75968db 100644 --- a/kitty/rc/signal_child.py +++ b/kitty/rc/signal_child.py @@ -33,18 +33,13 @@ class SignalChild(RemoteCommand): argspec = '[SIGNAL_NAME ...]' def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: - return {'match': opts.match, 'signals': [x.upper() for x in args] or ['SIGINT']} + # defaults to signal the window this command is run in + return {'match': opts.match, 'self': True, 'signals': [x.upper() for x in args] or ['SIGINT']} def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: import signal - windows = [window or boss.active_window] - match = payload_get('match') - if match: - windows = list(boss.match_windows(match)) - if not windows: - raise MatchError(match) signals = tuple(getattr(signal, x) for x in payload_get('signals')) - for window in windows: + for window in self.windows_for_match_payload(boss, window, payload_get): if window: window.signal_child(*signals) return None