Use the new get_options() function

Nicer than carrying around opts objects everywhere
This commit is contained in:
Kovid Goyal 2021-05-24 12:29:11 +05:30
parent 253b219d67
commit c827a29a7b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
11 changed files with 129 additions and 119 deletions

View File

@ -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)

View File

@ -7,10 +7,9 @@
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 @@ def __call__(
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 @@ def __call__(
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 @@ def __call__(
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)

View File

@ -32,7 +32,7 @@
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 @@ def __init__(
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 @@ def __init__(
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 @@ def add_os_window(
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 @@ def add_os_window(
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 @@ def _new_os_window(self, args: Union[SpecialWindowInstance, Iterable[str]], cwd_
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 @@ def _handle_remote_command(self, cmd: str, window: Optional[Window] = None, from
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 @@ def peer_message_received(self, msg_bytes: bytes) -> Optional[bytes]:
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 @@ def close_tab(self, tab: Optional[Tab] = None) -> None:
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 @@ def start(self, first_os_window_id: int) -> None:
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 @@ def clear_terminal(self, action: str, only_active: bool) -> None:
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 @@ def change_font_size(self, all_windows: bool, increment_operation: Optional[str]
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 @@ def set_background_opacity(self, opacity: str) -> None:
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 @@ def set_background_opacity(self, opacity: str) -> None:
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 @@ def dispatch_possible_special_key(self, ev: KeyEvent) -> bool:
# 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 @@ def start_resizing_window(self) -> None:
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 @@ def close_os_window(self) -> None:
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 @@ def quit(self, *args: Any) -> None:
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 @@ def edit_config_file(self, *a: Any) -> None:
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 @@ def _run_kitten(
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 @@ def open_url(self, url: str, program: Optional[Union[str, List[str]]] = None, cw
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 @@ def set_primary_selection(self) -> None:
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 @@ def disable_ligatures_in(self, where: Union[str, Iterable[Window]], strategy: in
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)

View File

@ -14,7 +14,6 @@
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 @@ def __init__(
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 @@ def __init__(
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 @@ def final_env(self) -> Dict[str, str]:
'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

View File

@ -10,7 +10,9 @@
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'])

View File

@ -40,7 +40,9 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg
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()})

View File

@ -48,7 +48,8 @@ def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: Arg
}
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}:

View File

@ -108,8 +108,9 @@ def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get:
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)

View File

@ -7,11 +7,10 @@
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 @@ def __init__(self, os_window_id: int, opts: Options):
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 @@ def patch_colors(self, spec: Dict[str, Any]) -> None:
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:

View File

@ -19,13 +19,12 @@
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 @@ def __init__(
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 @@ def launch_child(
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 @@ def launch_child(
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 @@ def launch_child(
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 @@ def launch_child(
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 @@ def new_window(
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 @@ def make_active(self) -> None:
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 @@ def refresh_sprite_positions(self) -> None:
@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 @@ def remove(self, tab: Tab) -> None:
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:

View File

@ -28,10 +28,10 @@
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 @@ def __init__(
self,
tab: TabType,
child: ChildType,
opts: Options,
args: CLIOptions,
override_title: Optional[str] = None,
copy_colors_from: Optional['Window'] = None,
@ -344,8 +343,9 @@ def __init__(
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 @@ def effective_margin(self, edge: EdgeLiteral, is_single_window: bool = False) ->
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 @@ def patch_edge_width(self, which: str, edge: EdgeLiteral, val: Optional[float])
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 @@ def use_utf8(self, on: bool) -> None:
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 @@ def open_url(self, url: str, hyperlink_id: int, cwd: Optional[str] = None) -> No
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 @@ def has_activity_since_last_focus(self) -> bool:
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 @@ def on_bell(self) -> None:
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 @@ def set_color_table_color(self, code: int, value: str) -> None:
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 @@ def clipboard_control(self, data: str) -> None:
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 @@ def clipboard_control(self, data: str) -> None:
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 @@ def write(key: str, func: Callable[[str], None]) -> None:
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 @@ def paste_selection_or_clipboard(self) -> None:
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 @@ def prepare_arg(x: str) -> str:
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: