From c827a29a7b0f10e0a6d0bb4fe5ff3e4ac45c99e7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 24 May 2021 12:29:11 +0530 Subject: [PATCH] Use the new get_options() function Nicer than carrying around opts objects everywhere --- kittens/remote_file/main.py | 3 +- kitty/borders.py | 18 ++++----- kitty/boss.py | 63 ++++++++++++++--------------- kitty/child.py | 5 +-- kitty/launch.py | 6 ++- kitty/rc/get_colors.py | 4 +- kitty/rc/set_background_opacity.py | 3 +- kitty/rc/set_spacing.py | 3 +- kitty/tab_bar.py | 36 ++++++++--------- kitty/tabs.py | 43 ++++++++++---------- kitty/window.py | 64 ++++++++++++++++-------------- 11 files changed, 129 insertions(+), 119 deletions(-) diff --git a/kittens/remote_file/main.py b/kittens/remote_file/main.py index 3d1f4c189..021781129 100644 --- a/kittens/remote_file/main.py +++ b/kittens/remote_file/main.py @@ -317,7 +317,8 @@ def handle_action(action: str, cli_opts: RemoteFileCLIOptions) -> Result: @result_handler() def handle_result(args: List[str], data: Result, target_window_id: int, boss: BossType) -> None: if data: - cmd = command_for_open(boss.opts.open_url_with) + from kitty.fast_data_types import get_options + cmd = command_for_open(get_options().open_url_with) open_cmd(cmd, data) diff --git a/kitty/borders.py b/kitty/borders.py index bb42ccad7..e28531cc7 100644 --- a/kitty/borders.py +++ b/kitty/borders.py @@ -7,10 +7,9 @@ from itertools import chain from typing import Sequence, Tuple from .fast_data_types import ( - BORDERS_PROGRAM, add_borders_rect, compile_program, init_borders_program, - os_window_has_background_image + BORDERS_PROGRAM, add_borders_rect, compile_program, get_options, + init_borders_program, os_window_has_background_image ) -from .options_stub import Options from .typing import LayoutType from .utils import load_shaders from .window_list import WindowGroup, WindowList @@ -65,11 +64,9 @@ def load_borders_program() -> None: class Borders: - def __init__(self, os_window_id: int, tab_id: int, opts: Options): + def __init__(self, os_window_id: int, tab_id: int): self.os_window_id = os_window_id self.tab_id = tab_id - self.draw_active_borders = opts.active_border_color is not None - self.draw_minimal_borders = opts.draw_minimal_borders and max(opts.window_margin_width) < 1 def __call__( self, @@ -78,6 +75,9 @@ class Borders: extra_blank_rects: Sequence[Tuple[int, int, int, int]], draw_window_borders: bool = True, ) -> None: + opts = get_options() + draw_active_borders = opts.active_border_color is not None + draw_minimal_borders = opts.draw_minimal_borders and max(opts.window_margin_width) < 1 add_borders_rect(self.os_window_id, self.tab_id, 0, 0, 0, 0, BorderColor.default_bg) has_background_image = os_window_has_background_image(self.os_window_id) if not has_background_image: @@ -94,9 +94,9 @@ class Borders: for i, wg in enumerate(groups): window_bg = wg.default_bg window_bg = (window_bg << 8) | BorderColor.window_bg - if draw_borders and not self.draw_minimal_borders: + if draw_borders and not draw_minimal_borders: # Draw the border rectangles - if wg is active_group and self.draw_active_borders: + if wg is active_group and draw_active_borders: color = BorderColor.active else: color = BorderColor.bell if wg.needs_attention else BorderColor.inactive @@ -106,7 +106,7 @@ class Borders: colors = window_bg, window_bg, window_bg, window_bg draw_edges(self.os_window_id, self.tab_id, colors, wg) - if self.draw_minimal_borders: + if draw_minimal_borders: for border_line in current_layout.get_minimal_borders(all_windows): left, top, right, bottom = border_line.edges add_borders_rect(self.os_window_id, self.tab_id, left, top, right, bottom, border_line.color) diff --git a/kitty/boss.py b/kitty/boss.py index 4def050a2..81af8ad53 100755 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -32,7 +32,7 @@ from .fast_data_types import ( ChildMonitor, KeyEvent, add_timer, background_opacity_of, change_background_opacity, change_os_window_state, cocoa_set_menubar_title, create_os_window, current_application_quit_request, current_os_window, - destroy_global_data, focus_os_window, get_clipboard_string, + destroy_global_data, focus_os_window, get_clipboard_string, get_options, global_font_size, mark_os_window_for_close, os_window_font_size, patch_global_colors, safe_pipe, set_application_quit_request, set_background_image, set_boss, set_clipboard_string, set_in_sequence_mode, @@ -167,8 +167,8 @@ class Boss: talk_fd, listen_fd ) set_boss(self) - self.opts, self.args = opts, args - self.keymap = self.opts.keymap.copy() + self.args = args + self.keymap = get_options().keymap.copy() self.global_shortcuts_map = {v: KeyAction(k) for k, v in global_shortcuts.items()} for sc in global_shortcuts.values(): self.keymap.pop(sc, None) @@ -179,7 +179,7 @@ class Boss: cocoa_set_notification_activated_callback(notification_activated) def startup_first_child(self, os_window_id: Optional[int]) -> None: - startup_sessions = create_sessions(self.opts, self.args, default_session=self.opts.startup_session) + startup_sessions = create_sessions(get_options(), self.args, default_session=get_options().startup_session) for startup_session in startup_sessions: self.add_os_window(startup_session, os_window_id=os_window_id) os_window_id = None @@ -199,7 +199,7 @@ class Boss: startup_id: Optional[str] = None ) -> int: if os_window_id is None: - size_data = get_os_window_sizing_data(opts_for_size or self.opts, startup_session) + size_data = get_os_window_sizing_data(opts_for_size or get_options(), startup_session) wclass = wclass or getattr(startup_session, 'os_window_class', None) or self.args.cls or appname wname = wname or self.args.name or wclass with startup_notification_handler(do_notify=startup_id is not None, startup_id=startup_id) as pre_show_callback: @@ -210,7 +210,7 @@ class Boss: else: wname = self.args.name or self.args.cls or appname wclass = self.args.cls or appname - tm = TabManager(os_window_id, self.opts, self.args, wclass, wname, startup_session) + tm = TabManager(os_window_id, self.args, wclass, wname, startup_session) self.os_window_map[os_window_id] = tm return os_window_id @@ -317,7 +317,7 @@ class Boss: sw: Optional[SpecialWindowInstance] = args else: sw = self.args_to_special_window(args, cwd_from) if args else None - startup_session = next(create_sessions(self.opts, special_window=sw, cwd_from=cwd_from)) + startup_session = next(create_sessions(get_options(), special_window=sw, cwd_from=cwd_from)) return self.add_os_window(startup_session) def new_os_window(self, *args: str) -> None: @@ -347,7 +347,7 @@ class Boss: from .remote_control import handle_cmd response = None window = window or None - if self.opts.allow_remote_control == 'y' or from_peer or getattr(window, 'allow_remote_control', False): + if get_options().allow_remote_control == 'y' or from_peer or getattr(window, 'allow_remote_control', False): try: response = handle_cmd(self, window, cmd) except Exception as err: @@ -411,7 +411,7 @@ class Boss: args.directory = os.path.join(data['cwd'], args.directory) for session in create_sessions(opts, args, respect_cwd=True): os_window_id = self.add_os_window(session, wclass=args.cls, wname=args.name, opts_for_size=opts, startup_id=startup_id) - if opts.background_opacity != self.opts.background_opacity: + if opts.background_opacity != get_options().background_opacity: self._set_os_window_background_opacity(os_window_id, opts.background_opacity) if data.get('notify_on_os_window_death'): self.os_window_death_actions[os_window_id] = partial(self.notify_on_os_window_death, data['notify_on_os_window_death']) @@ -484,7 +484,7 @@ class Boss: def confirm_tab_close(self, tab: Tab) -> None: windows = tuple(tab) - needs_confirmation = self.opts.confirm_os_window_close > 0 and len(windows) >= self.opts.confirm_os_window_close + needs_confirmation = get_options().confirm_os_window_close > 0 and len(windows) >= get_options().confirm_os_window_close if not needs_confirmation: self.close_tab_no_confirm(tab) return @@ -521,9 +521,9 @@ class Boss: self.io_thread_started = True self.startup_first_child(first_os_window_id) - if self.opts.update_check_interval > 0 and not hasattr(self, 'update_check_started'): + if get_options().update_check_interval > 0 and not hasattr(self, 'update_check_started'): from .update_check import run_update_check - run_update_check(self.opts.update_check_interval * 60 * 60) + run_update_check(get_options().update_check_interval * 60 * 60) self.update_check_started = True def activate_tab_at(self, os_window_id: int, x: int, is_double: bool = False) -> int: @@ -561,14 +561,14 @@ class Boss: def increase_font_size(self) -> None: # legacy cfs = global_font_size() - self.set_font_size(min(self.opts.font_size * 5, cfs + 2.0)) + self.set_font_size(min(get_options().font_size * 5, cfs + 2.0)) def decrease_font_size(self) -> None: # legacy cfs = global_font_size() self.set_font_size(max(MINIMUM_FONT_SIZE, cfs - 2.0)) def restore_font_size(self) -> None: # legacy - self.set_font_size(self.opts.font_size) + self.set_font_size(get_options().font_size) def set_font_size(self, new_size: float) -> None: # legacy self.change_font_size(True, None, new_size) @@ -577,13 +577,13 @@ class Boss: def calc_new_size(old_size: float) -> float: new_size = old_size if amt == 0: - new_size = self.opts.font_size + new_size = get_options().font_size else: if increment_operation: new_size += (1 if increment_operation == '+' else -1) * amt else: new_size = amt - new_size = max(MINIMUM_FONT_SIZE, min(new_size, self.opts.font_size * 5)) + new_size = max(MINIMUM_FONT_SIZE, min(new_size, get_options().font_size * 5)) return new_size if all_windows: @@ -633,7 +633,7 @@ class Boss: window = self.active_window if window is None or not opacity: return - if not self.opts.dynamic_background_opacity: + if not get_options().dynamic_background_opacity: self.show_error( _('Cannot change background opacity'), _('You must set the dynamic_background_opacity option in kitty.conf to be able to change background opacity')) @@ -645,7 +645,7 @@ class Boss: return fin_opacity = old_opacity + float(opacity) elif opacity == 'default': - fin_opacity = self.opts.background_opacity + fin_opacity = get_options().background_opacity else: fin_opacity = float(opacity) self._set_os_window_background_opacity(os_window_id, fin_opacity) @@ -672,7 +672,7 @@ class Boss: # Handles shortcuts, return True if the key was consumed key_action = get_shortcut(self.keymap, ev) if key_action is None: - sequences = get_shortcut(self.opts.sequence_map, ev) + sequences = get_shortcut(get_options().sequence_map, ev) if sequences and not isinstance(sequences, KeyAction): self.pending_sequences = sequences set_in_sequence_mode(True) @@ -710,8 +710,8 @@ class Boss: if w is None: return overlay_window = self._run_kitten('resize_window', args=[ - '--horizontal-increment={}'.format(self.opts.window_resize_step_cells), - '--vertical-increment={}'.format(self.opts.window_resize_step_lines) + '--horizontal-increment={}'.format(get_options().window_resize_step_cells), + '--vertical-increment={}'.format(get_options().window_resize_step_lines) ]) if overlay_window is not None: overlay_window.allow_remote_control = True @@ -813,7 +813,7 @@ class Boss: def confirm_os_window_close(self, os_window_id: int) -> None: tm = self.os_window_map.get(os_window_id) - needs_confirmation = tm is not None and self.opts.confirm_os_window_close > 0 and tm.number_of_windows >= self.opts.confirm_os_window_close + needs_confirmation = tm is not None and get_options().confirm_os_window_close > 0 and tm.number_of_windows >= get_options().confirm_os_window_close if not needs_confirmation: mark_os_window_for_close(os_window_id) return @@ -850,7 +850,7 @@ class Boss: num = 0 for q in self.os_window_map.values(): num += q.number_of_windows - needs_confirmation = tm is not None and self.opts.confirm_os_window_close > 0 and num >= self.opts.confirm_os_window_close + needs_confirmation = tm is not None and get_options().confirm_os_window_close > 0 and num >= get_options().confirm_os_window_close if not needs_confirmation: set_application_quit_request(IMPERATIVE_CLOSE_REQUESTED) return @@ -889,7 +889,7 @@ class Boss: confpath = prepare_config_file_for_editing() # On macOS vim fails to handle SIGWINCH if it occurs early, so add a # small delay. - cmd = [kitty_exe(), '+runpy', 'import os, sys, time; time.sleep(0.05); os.execvp(sys.argv[1], sys.argv[1:])'] + get_editor(self.opts) + [confpath] + cmd = [kitty_exe(), '+runpy', 'import os, sys, time; time.sleep(0.05); os.execvp(sys.argv[1], sys.argv[1:])'] + get_editor(get_options()) + [confpath] self.new_os_window(*cmd) def get_output(self, source_window: Window, num_lines: Optional[int] = 1) -> str: @@ -941,7 +941,7 @@ class Boss: raise ValueError('Unknown type_of_input: {}'.format(type_of_input)) else: data = input_data if isinstance(input_data, bytes) else input_data.encode('utf-8') - copts = common_opts_as_dict(self.opts) + copts = common_opts_as_dict(get_options()) final_args: List[str] = [] for x in args: if x == '@selection': @@ -1081,7 +1081,7 @@ class Boss: if actions: self.drain_actions(actions) if not found_action: - open_url(url, program or self.opts.open_url_with, cwd=cwd) + open_url(url, program or get_options().open_url_with, cwd=cwd) def drain_actions(self, actions: List) -> None: @@ -1128,8 +1128,8 @@ class Boss: text = w.text_for_selection() if text: set_primary_selection(text) - if self.opts.copy_on_select: - self.copy_to_buffer(self.opts.copy_on_select) + if get_options().copy_on_select: + self.copy_to_buffer(get_options().copy_on_select) def copy_to_buffer(self, buffer_name: str) -> None: w = self.active_window @@ -1401,14 +1401,15 @@ class Boss: window.refresh() def patch_colors(self, spec: Dict[str, int], cursor_text_color: Union[bool, int, Color], configured: bool = False) -> None: + opts = get_options() if configured: for k, v in spec.items(): - if hasattr(self.opts, k): - setattr(self.opts, k, color_from_int(v)) + if hasattr(opts, k): + setattr(opts, k, color_from_int(v)) if cursor_text_color is not False: if isinstance(cursor_text_color, int): cursor_text_color = color_from_int(cursor_text_color) - self.opts.cursor_text_color = cursor_text_color + opts.cursor_text_color = cursor_text_color for tm in self.all_tab_managers: tm.tab_bar.patch_colors(spec) patch_global_colors(spec, configured) diff --git a/kitty/child.py b/kitty/child.py index a02d779a9..785d7c7c5 100644 --- a/kitty/child.py +++ b/kitty/child.py @@ -14,7 +14,6 @@ from typing import ( import kitty.fast_data_types as fast_data_types from .constants import is_macos, shell_path, terminfo_dir -from .options_stub import Options try: from typing import TypedDict @@ -187,7 +186,6 @@ class Child: self, argv: Sequence[str], cwd: str, - opts: Options, stdin: Optional[bytes] = None, env: Optional[Dict[str, str]] = None, cwd_from: Optional[int] = None, @@ -204,7 +202,6 @@ class Child: else: cwd = os.path.expandvars(os.path.expanduser(cwd or os.getcwd())) self.cwd = os.path.abspath(cwd) - self.opts = opts self.stdin = stdin self.env = env or {} @@ -217,7 +214,7 @@ class Child: 'lc_ctype_before_python') and not getattr(default_env, 'lc_ctype_set_by_user', False): del env['LC_CTYPE'] env.update(self.env) - env['TERM'] = self.opts.term + env['TERM'] = fast_data_types.get_options().term env['COLORTERM'] = 'truecolor' if self.cwd: # needed in case cwd is a symlink, in which case shells diff --git a/kitty/launch.py b/kitty/launch.py index a8860833b..1b695af50 100644 --- a/kitty/launch.py +++ b/kitty/launch.py @@ -10,7 +10,9 @@ from .child import Child from .cli import WATCHER_DEFINITION, parse_args from .cli_stub import LaunchCLIOptions from .constants import resolve_custom_file -from .fast_data_types import patch_color_profiles, set_clipboard_string +from .fast_data_types import ( + get_options, patch_color_profiles, set_clipboard_string +) from .tabs import Tab from .types import run_once from .utils import find_exe, read_shell_environment, set_primary_selection @@ -330,7 +332,7 @@ def launch( final_cmd.append(x) exe = find_exe(final_cmd[0]) if not exe: - env = read_shell_environment(boss.opts) + env = read_shell_environment(get_options()) if 'PATH' in env: import shutil exe = shutil.which(final_cmd[0], path=env['PATH']) diff --git a/kitty/rc/get_colors.py b/kitty/rc/get_colors.py index 8f4c7e133..cd7c913f3 100644 --- a/kitty/rc/get_colors.py +++ b/kitty/rc/get_colors.py @@ -40,7 +40,9 @@ configured colors. return {'configured': opts.configured, 'match': opts.match} 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)} + from kitty.fast_data_types import get_options + opts = get_options() + 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) ans.update({k: color_from_int(v) for k, v in windows[0].current_colors.items()}) diff --git a/kitty/rc/set_background_opacity.py b/kitty/rc/set_background_opacity.py index 9db59b3a2..26aac864d 100644 --- a/kitty/rc/set_background_opacity.py +++ b/kitty/rc/set_background_opacity.py @@ -48,7 +48,8 @@ cause colors to be changed in all windows. } def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: - if not boss.opts.dynamic_background_opacity: + from kitty.fast_data_types import get_options + 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}: diff --git a/kitty/rc/set_spacing.py b/kitty/rc/set_spacing.py index 14097d410..93d4bc013 100644 --- a/kitty/rc/set_spacing.py +++ b/kitty/rc/set_spacing.py @@ -108,8 +108,9 @@ windows). windows = self.windows_for_payload(boss, window, payload_get) settings: Dict[str, Optional[float]] = payload_get('settings') dirtied_tabs = {} + from kitty.fast_data_types import get_options if payload_get('configured'): - patch_configured_edges(boss.opts, settings) + patch_configured_edges(get_options(), settings) for w in windows: patch_window_edges(w, settings) diff --git a/kitty/tab_bar.py b/kitty/tab_bar.py index 2f37d302e..53116faac 100644 --- a/kitty/tab_bar.py +++ b/kitty/tab_bar.py @@ -7,11 +7,10 @@ from typing import Any, Dict, NamedTuple, Optional, Sequence, Tuple from .config import build_ansi_color_table from .fast_data_types import ( - DECAWM, Screen, cell_size_for_window, pt_to_px, set_tab_bar_render_data, - viewport_for_window + DECAWM, Screen, cell_size_for_window, get_options, pt_to_px, + set_tab_bar_render_data, viewport_for_window ) from .layout.base import Rect -from .options_stub import Options from .rgb import Color, alpha_blend, color_as_sgr, color_from_int, to_color from .types import WindowGeometry from .typing import PowerlineStyle @@ -245,11 +244,11 @@ def draw_tab_with_powerline(draw_data: DrawData, screen: Screen, tab: TabBarData class TabBar: - def __init__(self, os_window_id: int, opts: Options): + def __init__(self, os_window_id: int): self.os_window_id = os_window_id - self.opts = opts self.num_tabs = 1 - self.margin_width = pt_to_px(self.opts.tab_bar_margin_width, self.os_window_id) + opts = get_options() + self.margin_width = pt_to_px(opts.tab_bar_margin_width, self.os_window_id) self.cell_width, cell_height = cell_size_for_window(self.os_window_id) self.data_buffer_size = 0 self.laid_out_once = False @@ -277,17 +276,17 @@ class TabBar: self.active_fg = as_rgb(color_as_int(opts.active_tab_foreground)) self.bell_fg = as_rgb(0xff0000) self.draw_data = DrawData( - self.leading_spaces, self.sep, self.trailing_spaces, self.opts.bell_on_tab, self.bell_fg, - self.opts.tab_fade, self.opts.active_tab_foreground, self.opts.active_tab_background, - self.opts.inactive_tab_foreground, self.opts.inactive_tab_background, - self.opts.tab_bar_background or self.opts.background, self.opts.tab_title_template, - self.opts.active_tab_title_template, - self.opts.tab_activity_symbol, - self.opts.tab_powerline_style + self.leading_spaces, self.sep, self.trailing_spaces, opts.bell_on_tab, self.bell_fg, + opts.tab_fade, opts.active_tab_foreground, opts.active_tab_background, + opts.inactive_tab_foreground, opts.inactive_tab_background, + opts.tab_bar_background or opts.background, opts.tab_title_template, + opts.active_tab_title_template, + opts.tab_activity_symbol, + opts.tab_powerline_style ) - if self.opts.tab_bar_style == 'separator': + if opts.tab_bar_style == 'separator': self.draw_func = draw_tab_with_separator - elif self.opts.tab_bar_style == 'powerline': + elif opts.tab_bar_style == 'powerline': self.draw_func = draw_tab_with_powerline else: self.draw_func = draw_tab_with_fade @@ -303,12 +302,13 @@ class TabBar: self.draw_data = self.draw_data._replace(inactive_bg=color_from_int(spec['inactive_tab_background'])) if 'tab_bar_background' in spec: self.draw_data = self.draw_data._replace(default_bg=color_from_int(spec['tab_bar_background'])) - fg = spec.get('inactive_tab_foreground', color_as_int(self.opts.inactive_tab_foreground)) + opts = get_options() + fg = spec.get('inactive_tab_foreground', color_as_int(opts.inactive_tab_foreground)) bg = spec.get('tab_bar_background', False) if bg is None: - bg = color_as_int(self.opts.background) + bg = color_as_int(opts.background) elif bg is False: - bg = color_as_int(self.opts.tab_bar_background or self.opts.background) + bg = color_as_int(opts.tab_bar_background or opts.background) self.screen.color_profile.set_configured_colors(fg, bg) def layout(self) -> None: diff --git a/kitty/tabs.py b/kitty/tabs.py index 97501d523..f27d2823e 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -19,13 +19,12 @@ from .child import Child from .cli_stub import CLIOptions from .constants import appname, kitty_exe from .fast_data_types import ( - add_tab, attach_window, detach_window, get_boss, mark_tab_bar_dirty, - next_window_id, remove_tab, remove_window, ring_bell, set_active_tab, - set_active_window, swap_tabs, sync_os_window_title + add_tab, attach_window, detach_window, get_boss, get_options, + mark_tab_bar_dirty, next_window_id, remove_tab, remove_window, ring_bell, + set_active_tab, set_active_window, swap_tabs, sync_os_window_title ) from .layout.base import Layout, Rect from .layout.interface import create_layout_object_for, evict_cached_layouts -from .options_stub import Options from .tab_bar import TabBar, TabBarData from .typing import EdgeLiteral, SessionTab, SessionType, TypedDict from .utils import log_error, platform_window_id, resolved_shell @@ -90,10 +89,10 @@ class Tab: # {{{ self.id: int = add_tab(self.os_window_id) if not self.id: raise Exception('No OS window with id {} found, or tab counter has wrapped'.format(self.os_window_id)) - self.opts, self.args = tab_manager.opts, tab_manager.args + self.args = tab_manager.args self.name = getattr(session_tab, 'name', '') - self.enabled_layouts = [x.lower() for x in getattr(session_tab, 'enabled_layouts', None) or self.opts.enabled_layouts] - self.borders = Borders(self.os_window_id, self.id, self.opts) + self.enabled_layouts = [x.lower() for x in getattr(session_tab, 'enabled_layouts', None) or get_options().enabled_layouts] + self.borders = Borders(self.os_window_id, self.id) self.windows = WindowList(self) for i, which in enumerate('first second third fourth fifth sixth seventh eighth ninth tenth'.split()): setattr(self, which + '_window', partial(self.nth_window, num=i)) @@ -283,15 +282,15 @@ class Tab: # {{{ check_for_suitability = True if cmd is None: if use_shell: - cmd = resolved_shell(self.opts) + cmd = resolved_shell(get_options()) check_for_suitability = False else: if self.args.args: cmd = list(self.args.args) else: - cmd = resolved_shell(self.opts) + cmd = resolved_shell(get_options()) check_for_suitability = False - cmd = self.args.args or resolved_shell(self.opts) + cmd = self.args.args or resolved_shell(get_options()) if check_for_suitability: old_exe = cmd[0] if not os.path.isabs(old_exe): @@ -310,7 +309,7 @@ class Tab: # {{{ else: if stat.S_ISDIR(st.st_mode): cwd = old_exe - cmd = resolved_shell(self.opts) + cmd = resolved_shell(get_options()) elif not is_executable: import shlex with suppress(OSError): @@ -320,7 +319,7 @@ class Tab: # {{{ line = f.read(4096).splitlines()[0] cmd += shlex.split(line) + [old_exe] else: - cmd += [resolved_shell(self.opts)[0], cmd[0]] + cmd += [resolved_shell(get_options())[0], cmd[0]] fenv: Dict[str, str] = {} if env: fenv.update(env) @@ -328,7 +327,7 @@ class Tab: # {{{ pwid = platform_window_id(self.os_window_id) if pwid is not None: fenv['WINDOWID'] = str(pwid) - ans = Child(cmd, cwd or self.cwd, self.opts, stdin, fenv, cwd_from, allow_remote_control=allow_remote_control) + ans = Child(cmd, cwd or self.cwd, stdin, fenv, cwd_from, allow_remote_control=allow_remote_control) ans.fork() return ans @@ -356,7 +355,7 @@ class Tab: # {{{ child = self.launch_child( use_shell=use_shell, cmd=cmd, stdin=stdin, cwd_from=cwd_from, cwd=cwd, env=env, allow_remote_control=allow_remote_control) window = Window( - self, child, self.opts, self.args, override_title=override_title, + self, child, self.args, override_title=override_title, copy_colors_from=copy_colors_from, watchers=watchers ) # Must add child before laying out so that resize_pty succeeds @@ -530,16 +529,16 @@ class Tab: # {{{ class TabManager: # {{{ - def __init__(self, os_window_id: int, opts: Options, args: CLIOptions, wm_class: str, wm_name: str, startup_session: Optional[SessionType] = None): + def __init__(self, os_window_id: int, args: CLIOptions, wm_class: str, wm_name: str, startup_session: Optional[SessionType] = None): self.os_window_id = os_window_id self.wm_class = wm_class self.wm_name = wm_name self.last_active_tab_id = None - self.opts, self.args = opts, args - self.tab_bar_hidden = self.opts.tab_bar_style == 'hidden' + self.args = args + self.tab_bar_hidden = get_options().tab_bar_style == 'hidden' self.tabs: List[Tab] = [] self.active_tab_history: Deque[int] = deque() - self.tab_bar = TabBar(self.os_window_id, opts) + self.tab_bar = TabBar(self.os_window_id) self._active_tab_idx = 0 if startup_session is not None: @@ -581,7 +580,7 @@ class TabManager: # {{{ @property def tab_bar_should_be_visible(self) -> bool: - return len(self.tabs) >= self.opts.tab_bar_min_tabs + return len(self.tabs) >= get_options().tab_bar_min_tabs def _add_tab(self, tab: Tab) -> None: visible_before = self.tab_bar_should_be_visible @@ -765,16 +764,16 @@ class TabManager: # {{{ if active_tab_needs_to_change: next_active_tab = -1 - if self.opts.tab_switch_strategy == 'previous': + if get_options().tab_switch_strategy == 'previous': while self.active_tab_history and next_active_tab < 0: tab_id = self.active_tab_history.pop() for idx, qtab in enumerate(self.tabs): if qtab.id == tab_id: next_active_tab = idx break - elif self.opts.tab_switch_strategy == 'left': + elif get_options().tab_switch_strategy == 'left': next_active_tab = max(0, self.active_tab_idx - 1) - elif self.opts.tab_switch_strategy == 'right': + elif get_options().tab_switch_strategy == 'right': next_active_tab = min(self.active_tab_idx, len(self.tabs) - 1) if next_active_tab < 0: diff --git a/kitty/window.py b/kitty/window.py index 82019ccc3..d0e434407 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -28,10 +28,10 @@ from .fast_data_types import ( MARK, MARK_MASK, NO_CURSOR_SHAPE, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, TINT_PROGRAM, KeyEvent, Screen, add_timer, add_window, cell_size_for_window, click_mouse_url, compile_program, - encode_key_for_tty, get_boss, get_clipboard_string, init_cell_program, - mouse_selection, pt_to_px, set_clipboard_string, set_titlebar_color, - set_window_padding, set_window_render_data, update_window_title, - update_window_visibility, viewport_for_window + encode_key_for_tty, get_boss, get_clipboard_string, get_options, + init_cell_program, mouse_selection, pt_to_px, set_clipboard_string, + set_titlebar_color, set_window_padding, set_window_render_data, + update_window_title, update_window_visibility, viewport_for_window ) from .keys import keyboard_mode_name from .notify import NotificationCommand, handle_notification_cmd @@ -311,7 +311,6 @@ class Window: self, tab: TabType, child: ChildType, - opts: Options, args: CLIOptions, override_title: Optional[str] = None, copy_colors_from: Optional['Window'] = None, @@ -344,8 +343,9 @@ class Window: self.geometry: WindowGeometry = WindowGeometry(0, 0, 0, 0, 0, 0) self.needs_layout = True self.is_visible_in_layout: bool = True - self.child, self.opts = child, opts + self.child = child cell_width, cell_height = cell_size_for_window(self.os_window_id) + opts = get_options() self.screen: Screen = Screen(self, 24, 80, opts.scrollback_lines, cell_width, cell_height, self.id) if copy_colors_from is not None: self.screen.copy_colors_from(copy_colors_from.screen) @@ -364,18 +364,19 @@ class Window: q = getattr(self.margin, edge) if q is not None: return pt_to_px(q, self.os_window_id) + opts = get_options() if is_single_window: - q = getattr(self.opts.single_window_margin_width, edge) + q = getattr(opts.single_window_margin_width, edge) if q > -0.1: return pt_to_px(q, self.os_window_id) - q = getattr(self.opts.window_margin_width, edge) + q = getattr(opts.window_margin_width, edge) return pt_to_px(q, self.os_window_id) def effective_padding(self, edge: EdgeLiteral) -> int: q = getattr(self.padding, edge) if q is not None: return pt_to_px(q, self.os_window_id) - q = getattr(self.opts.window_padding_width, edge) + q = getattr(get_options().window_padding_width, edge) return pt_to_px(q, self.os_window_id) def update_effective_padding(self) -> None: @@ -391,7 +392,7 @@ class Window: self.update_effective_padding() def effective_border(self) -> int: - val, unit = self.opts.window_border_width + val, unit = get_options().window_border_width if unit == 'pt': val = max(1 if val > 0 else 0, pt_to_px(val, self.os_window_id)) else: @@ -556,14 +557,15 @@ class Window: def on_mouse_event(self, event: Dict[str, Any]) -> bool: ev = MouseEvent(**event) self.current_mouse_event_button = ev.button - action = self.opts.mousemap.get(ev) + action = get_options().mousemap.get(ev) if action is None: return False return get_boss().dispatch_action(action, window_for_dispatch=self, dispatch_type='MouseEvent') def open_url(self, url: str, hyperlink_id: int, cwd: Optional[str] = None) -> None: + opts = get_options() if hyperlink_id: - if not self.opts.allow_hyperlinks: + if not opts.allow_hyperlinks: return from urllib.parse import unquote, urlparse, urlunparse try: @@ -582,7 +584,7 @@ class Window: self.handle_remote_file(purl.netloc, unquote(purl.path)) return url = urlunparse(purl._replace(netloc='')) - if self.opts.allow_hyperlinks & 0b10: + if opts.allow_hyperlinks & 0b10: from kittens.tui.operations import styled get_boss()._run_kitten('ask', ['--type=choices', '--message', _( 'What would you like to do with this URL:\n') + @@ -644,16 +646,17 @@ class Window: return self.screen.has_activity_since_last_focus() def on_activity_since_last_focus(self) -> None: - if self.opts.tab_activity_symbol: + if get_options().tab_activity_symbol: get_boss().on_activity_since_last_focus(self) def on_bell(self) -> None: - if self.opts.command_on_bell and self.opts.command_on_bell != ['none']: + cb = get_options().command_on_bell + if cb and cb != ['none']: import shlex import subprocess env = self.child.final_env env['KITTY_CHILD_CMDLINE'] = ' '.join(map(shlex.quote, self.child.cmdline)) - subprocess.Popen(self.opts.command_on_bell, env=env, cwd=self.child.foreground_cwd) + subprocess.Popen(cb, env=env, cwd=self.child.foreground_cwd) if not self.is_active: changed = not self.needs_attention self.needs_attention = True @@ -664,7 +667,8 @@ class Window: tab.on_bell(self) def change_titlebar_color(self) -> None: - val = self.opts.macos_titlebar_color if is_macos else self.opts.wayland_titlebar_color + opts = get_options() + val = opts.macos_titlebar_color if is_macos else opts.wayland_titlebar_color if val: if (val & 0xff) == 1: val = self.screen.color_profile.default_bg @@ -748,7 +752,7 @@ class Window: self.refresh() def request_capabilities(self, q: str) -> None: - for result in get_capabilities(q, self.opts): + for result in get_capabilities(q, get_options()): self.screen.send_escape_code_to_child(DCS, result) def handle_remote_cmd(self, cmd: str) -> None: @@ -767,13 +771,14 @@ class Window: where, text = data.partition(';')[::2] if not where: where = 's0' + cc = get_options().clipboard_control if text == '?': response = None if 's' in where or 'c' in where: - response = get_clipboard_string() if 'read-clipboard' in self.opts.clipboard_control else '' + response = get_clipboard_string() if 'read-clipboard' in cc else '' loc = 'c' elif 'p' in where: - response = get_primary_selection() if 'read-primary' in self.opts.clipboard_control else '' + response = get_primary_selection() if 'read-primary' in cc else '' loc = 'p' response = response or '' from base64 import standard_b64encode @@ -789,7 +794,7 @@ class Window: def write(key: str, func: Callable[[str], None]) -> None: if text: - if ('no-append' in self.opts.clipboard_control or + if ('no-append' in cc or len(self.clipboard_control_buffers[key]) > 1024*1024): self.clipboard_control_buffers[key] = '' self.clipboard_control_buffers[key] += text @@ -798,13 +803,13 @@ class Window: func(self.clipboard_control_buffers[key]) if 's' in where or 'c' in where: - if 'write-clipboard' in self.opts.clipboard_control: + if 'write-clipboard' in cc: write('c', set_clipboard_string) if 'p' in where: - if self.opts.copy_on_select == 'clipboard': - if 'write-clipboard' in self.opts.clipboard_control: + if cc == 'clipboard': + if 'write-clipboard' in cc: write('c', set_clipboard_string) - if 'write-primary' in self.opts.clipboard_control: + if 'write-primary' in cc: write('p', set_primary_selection) def manipulate_title_stack(self, pop: bool, title: str, icon: Any) -> None: @@ -842,8 +847,9 @@ class Window: def text_for_selection(self) -> str: lines = self.screen.text_for_selection() - if self.opts.strip_trailing_spaces == 'always' or ( - self.opts.strip_trailing_spaces == 'smart' and not self.screen.is_rectangle_select()): + sts = get_options().strip_trailing_spaces + if sts == 'always' or ( + sts == 'smart' and not self.screen.is_rectangle_select()): return ''.join((ln.rstrip() or '\n') for ln in lines) return ''.join(lines) @@ -906,12 +912,12 @@ class Window: x = x.replace('CURSOR_COLUMN', str(data['cursor_x'])) return x - cmd = list(map(prepare_arg, self.opts.scrollback_pager)) + cmd = list(map(prepare_arg, get_options().scrollback_pager)) if not os.path.isabs(cmd[0]): import shutil exe = shutil.which(cmd[0]) if not exe: - env = read_shell_environment(self.opts) + env = read_shell_environment(get_options()) if env and 'PATH' in env: exe = shutil.which(cmd[0], path=env['PATH']) if exe: