1#!/usr/local/bin/python3.8 2# vim:fileencoding=utf-8 3# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net> 4 5import os 6import sys 7from typing import List 8 9 10def icat(args: List[str]) -> None: 11 from kittens.runner import run_kitten as rk 12 sys.argv = args 13 rk('icat') 14 15 16def list_fonts(args: List[str]) -> None: 17 from kitty.fonts.list import main as list_main 18 list_main(args) 19 20 21def remote_control(args: List[str]) -> None: 22 from kitty.remote_control import main as rc_main 23 rc_main(args) 24 25 26def runpy(args: List[str]) -> None: 27 if len(args) < 2: 28 raise SystemExit('Usage: kitty +runpy "some python code"') 29 sys.argv = ['kitty'] + args[2:] 30 exec(args[1]) 31 32 33def hold(args: List[str]) -> None: 34 import subprocess 35 import tty 36 from contextlib import suppress 37 ret = subprocess.Popen(args[1:]).wait() 38 with suppress(BaseException): 39 print('\n\x1b[1;32mPress any key to exit', end='', flush=True) 40 with suppress(BaseException): 41 tty.setraw(sys.stdin.fileno()) 42 sys.stdin.buffer.read(1) 43 raise SystemExit(ret) 44 45 46def complete(args: List[str]) -> None: 47 from kitty.complete import main as complete_main 48 complete_main(args[1:], entry_points, namespaced_entry_points) 49 50 51def launch(args: List[str]) -> None: 52 import runpy 53 sys.argv = args[1:] 54 try: 55 exe = args[1] 56 except IndexError: 57 raise SystemExit( 58 'usage: kitty +launch script.py [arguments to be passed to script.py ...]\n\n' 59 'script.py will be run with full access to kitty code. If script.py is ' 60 'prefixed with a : it will be searched for in PATH' 61 ) 62 if exe.startswith(':'): 63 import shutil 64 q = shutil.which(exe[1:]) 65 if not q: 66 raise SystemExit(f'{exe[1:]} not found in PATH') 67 exe = q 68 if not os.path.exists(exe): 69 raise SystemExit(f'{exe} does not exist') 70 runpy.run_path(exe, run_name='__main__') 71 72 73def run_kitten(args: List[str]) -> None: 74 try: 75 kitten = args[1] 76 except IndexError: 77 from kittens.runner import list_kittens 78 list_kittens() 79 raise SystemExit(1) 80 sys.argv = args[1:] 81 from kittens.runner import run_kitten as rk 82 rk(kitten) 83 84 85def edit_config_file(args: List[str]) -> None: 86 from kitty.cli import create_default_opts 87 from kitty.fast_data_types import set_options 88 from kitty.utils import edit_config_file as f 89 set_options(create_default_opts()) 90 f() 91 92 93def namespaced(args: List[str]) -> None: 94 try: 95 func = namespaced_entry_points[args[1]] 96 except KeyError: 97 pass 98 else: 99 func(args[1:]) 100 return 101 raise SystemExit(f'{args[1]} is not a known entry point. Choices are: ' + ', '.join(namespaced_entry_points)) 102 103 104entry_points = { 105 # These two are here for backwards compat 106 'icat': icat, 107 'list-fonts': list_fonts, 108 'runpy': runpy, 109 'launch': launch, 110 'kitten': run_kitten, 111 'edit-config': edit_config_file, 112 113 '@': remote_control, 114 '+': namespaced, 115} 116namespaced_entry_points = {k: v for k, v in entry_points.items() if k[0] not in '+@'} 117namespaced_entry_points['hold'] = hold 118namespaced_entry_points['complete'] = complete 119 120 121def setup_openssl_environment() -> None: 122 # Use our bundled CA certificates instead of the system ones, since 123 # many systems come with no certificates in a useable form or have various 124 # locations for the certificates. 125 d = os.path.dirname 126 ext_dir: str = getattr(sys, 'kitty_extensions_dir') 127 if 'darwin' in sys.platform.lower(): 128 cert_file = os.path.join(d(d(d(ext_dir))), 'cacert.pem') 129 else: 130 cert_file = os.path.join(d(ext_dir), 'cacert.pem') 131 os.environ['SSL_CERT_FILE'] = cert_file 132 setattr(sys, 'kitty_ssl_env_var', 'SSL_CERT_FILE') 133 134 135def main() -> None: 136 if getattr(sys, 'frozen', False) and getattr(sys, 'kitty_extensions_dir', ''): 137 setup_openssl_environment() 138 first_arg = '' if len(sys.argv) < 2 else sys.argv[1] 139 func = entry_points.get(first_arg) 140 if func is None: 141 if first_arg.startswith('@'): 142 remote_control(['@', first_arg[1:]] + sys.argv[2:]) 143 elif first_arg.startswith('+'): 144 namespaced(['+', first_arg[1:]] + sys.argv[2:]) 145 else: 146 from kitty.main import main as kitty_main 147 kitty_main() 148 else: 149 func(sys.argv[1:]) 150 151 152if __name__ == '__main__': 153 main() 154