def final_env(self) -> Dict[str, str]: from kitty.options.utils import DELETE_ENV_VAR env = default_env().copy() if is_macos and env.get( 'LC_CTYPE') == 'UTF-8' and not sys._xoptions.get( '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'] = fast_data_types.get_options().term env['COLORTERM'] = 'truecolor' env['KITTY_PID'] = getpid() if self.cwd: # needed in case cwd is a symlink, in which case shells # can use it to display the current directory name rather # than the resolved path env['PWD'] = self.cwd tdir = checked_terminfo_dir() if tdir: env['TERMINFO'] = tdir env['KITTY_INSTALLATION_DIR'] = kitty_base_dir opts = fast_data_types.get_options() self.unmodified_argv = list(self.argv) if 'disabled' not in opts.shell_integration: from .shell_integration import modify_shell_environ modify_shell_environ(opts, env, self.argv) env = {k: v for k, v in env.items() if v is not DELETE_ENV_VAR} if self.is_clone_launch: env['KITTY_IS_CLONE_LAUNCH'] = self.is_clone_launch self.is_clone_launch = '1' # free memory else: env.pop('KITTY_IS_CLONE_LAUNCH', None) return env
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: 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}: boss._set_os_window_background_opacity(os_window_id, payload_get('opacity'))
def reload_kitty_config(self, opts: Optional[Options] = None) -> None: if opts is None: opts = get_options() data = json.dumps({ 'paths': opts.config_paths, 'overrides': opts.config_overrides }) if self.write_to_process_fd > -1: self.send_to_prewarm_process(f'reload_kitty_config:{data}\n')
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: tabs = self.tabs_for_match_payload(boss, window, payload_get) layouts = parse_layout_names(payload_get('layouts')) if payload_get('configured'): get_options().enabled_layouts = list(layouts) for tab in tabs: if tab: tab.set_enabled_layouts(layouts) return None
def __init__(self, request_id: str, quiet: int, bypass: str) -> None: self.id = request_id self.bypass_ok: Optional[bool] = None if bypass: byp = get_options().file_transfer_confirmation_bypass self.bypass_ok = (encode_bypass(request_id, byp) == bypass) if byp else False self.files = {} self.last_activity_at = monotonic() self.send_acknowledgements = quiet < 1 self.send_errors = quiet < 2
def on_mouse_event(self, event): ev = MouseEvent(**event) opts = get_options() action_def = opts.mousemap.get(ev) if not action_def: return False self.current_mouse_button = ev.button for action in opts.alias_map.resolve_aliases(action_def, 'mouse_map'): getattr(self, action.func)(*action.args) self.current_mouse_button = 0 return True
def kitty_opts() -> 'Options': from kitty.fast_data_types import get_options, set_options try: ans = cast(Optional['Options'], get_options()) except RuntimeError: ans = None if ans is None: from kitty.cli import create_default_opts from kitty.utils import suppress_error_logging with suppress_error_logging(): ans = create_default_opts() set_options(ans) return ans
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: 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) 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)
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: 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(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 for tab in dirtied_tabs.values(): tab.relayout()
def __init__(self, request_id: str, quiet: int, bypass: str, num_of_args: int) -> None: self.id = request_id self.expected_num_of_args = num_of_args self.bypass_ok: Optional[bool] = None self.accepted = False if bypass: byp = get_options().file_transfer_confirmation_bypass self.bypass_ok = (encode_bypass(request_id, byp) == bypass) if byp else False self.last_activity_at = monotonic() self.send_acknowledgements = quiet < 1 self.send_errors = quiet < 2 self.last_activity_at = monotonic() self.file_specs: List[Tuple[str, str]] = [] self.queued_files_map: Dict[str, SourceFile] = {} self.active_file: Optional[SourceFile] = None self.pending_chunks: Deque[FileTransmissionCommand] = deque() self.metadata_sent = False
def final_env(self) -> Dict[str, str]: env: Optional[Dict[str, str]] = getattr(self, '_final_env', None) if env is None: env = self._final_env = default_env().copy() if is_macos and env.get( 'LC_CTYPE') == 'UTF-8' and not sys._xoptions.get( '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'] = fast_data_types.get_options().term env['COLORTERM'] = 'truecolor' if self.cwd: # needed in case cwd is a symlink, in which case shells # can use it to display the current directory name rather # than the resolved path env['PWD'] = self.cwd tdir = checked_terminfo_dir() if tdir: env['TERMINFO'] = tdir return env
def test_prewarming(self): from kitty.prewarm import fork_prewarm_process cwd = tempfile.gettempdir() env = {'TEST_ENV_PASS': '******'} cols = 117 stdin_data = 'from_stdin' pty = self.create_pty(cols=cols) ttyname = os.ttyname(pty.slave_fd) opts = get_options() opts.config_overrides = 'font_family prewarm', p = fork_prewarm_process(opts, use_exec=True) if p is None: return p.take_from_worker_fd(create_file=True) child = p(pty.slave_fd, [kitty_exe(), '+runpy', """\ import os, json; from kitty.utils import *; from kitty.fast_data_types import get_options; print(json.dumps({ 'cterm': os.ctermid(), 'ttyname': os.ttyname(sys.stdout.fileno()), 'cols': read_screen_size().cols, 'cwd': os.getcwd(), 'env': os.environ.get('TEST_ENV_PASS'), 'pid': os.getpid(), 'font_family': get_options().font_family, 'stdin': sys.stdin.read(), 'done': 'hello', }, indent=2))"""], cwd=cwd, env=env, stdin_data=stdin_data) self.assertFalse(pty.screen_contents().strip()) p.mark_child_as_ready(child.child_id) pty.wait_till(lambda: 'hello' in pty.screen_contents()) data = json.loads(pty.screen_contents()) self.ae(data['cols'], cols) self.assertTrue(data['cterm']) self.ae(data['ttyname'], ttyname) self.ae(os.path.realpath(data['cwd']), os.path.realpath(cwd)) self.ae(data['env'], env['TEST_ENV_PASS']) self.ae(data['font_family'], 'prewarm') self.ae(int(p.from_worker.readline()), data['pid'])
def handle_result(args: List[str], data: Result, target_window_id: int, boss: BossType) -> None: if data: from kitty.fast_data_types import get_options cmd = command_for_open(get_options().open_url_with) open_cmd(cmd, data)
def handle_result(args: List[str], session_file_path: str, target_window_id: int, boss: Boss) -> None: startup_session = next( create_sessions(get_options(), default_session=session_file_path)) boss.add_os_window(startup_session)
def get_result(name: str) -> Optional[str]: from kitty.fast_data_types import get_options q = all_queries.get(name) if q is None: return None return q.get_result(get_options())
def handle_result(args: List[str], data: Dict[str, Any], target_window_id: int, boss: BossType) -> None: if data['customize_processing']: m = load_custom_processor(data['customize_processing']) if 'handle_result' in m: m['handle_result'](args, data, target_window_id, boss, data['extra_cli_args']) return None programs = data['programs'] or ('default',) matches: List[str] = [] groupdicts = [] for m, g in zip(data['match'], data['groupdicts']): if m: matches.append(m) groupdicts.append(g) joiner = data['multiple_joiner'] try: is_int: Optional[int] = int(joiner) except Exception: is_int = None text_type = data['type'] @lru_cache() def joined_text() -> str: if is_int is not None: try: return matches[is_int] except IndexError: return matches[-1] if joiner == 'json': import json return json.dumps(matches, ensure_ascii=False, indent='\t') if joiner == 'auto': q = '\n\r' if text_type in ('line', 'url') else ' ' else: q = {'newline': '\n\r', 'space': ' '}.get(joiner, '') return q.join(matches) for program in programs: if program == '-': w = boss.window_id_map.get(target_window_id) if w is not None: w.paste(joined_text()) elif program == '@': set_clipboard_string(joined_text()) elif program == '*': set_primary_selection(joined_text()) else: cwd = data['cwd'] program = get_options().open_url_with if program == 'default' else program if text_type == 'hyperlink': w = boss.window_id_map.get(target_window_id) for m in matches: if w is not None: w.open_url(m, hyperlink_id=1, cwd=cwd) else: for m, groupdict in zip(matches, groupdicts): if groupdict: m = [] for k, v in groupdict.items(): m.append('{}={}'.format(k, v or '')) boss.open_url(m, program, cwd=cwd)