mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-26 18:22:09 +02:00
Refactor the kittens framework
Make it possible to perform arbitrary actions with the kittens output and also allow running kittens from standalone python files.
This commit is contained in:
59
kittens/runner.py
Normal file
59
kittens/runner.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
from functools import partial
|
||||
|
||||
|
||||
def import_kitten_main_module(config_dir, kitten):
|
||||
if kitten.endswith('.py'):
|
||||
path = os.path.expanduser(kitten)
|
||||
if not os.path.isabs(path):
|
||||
path = os.path.join(config_dir, path)
|
||||
path = os.path.abspath(path)
|
||||
if os.path.dirname(path):
|
||||
sys.path.insert(0, os.path.dirname(path))
|
||||
with open(path) as f:
|
||||
src = f.read()
|
||||
code = compile(src, path, 'exec')
|
||||
g = {'__name__': 'kitten'}
|
||||
exec(code, g)
|
||||
return {'start': g['main'], 'end': g['handle_result']}
|
||||
else:
|
||||
m = importlib.import_module('kittens.{}.main'.format(kitten))
|
||||
return {'start': m.main, 'end': m.handle_result}
|
||||
|
||||
|
||||
def create_kitten_handler(kitten, orig_args):
|
||||
from kitty.constants import config_dir
|
||||
m = import_kitten_main_module(config_dir, kitten)
|
||||
return partial(m['end'], [kitten] + orig_args)
|
||||
|
||||
|
||||
def launch(args):
|
||||
config_dir, kitten = args[:2]
|
||||
del args[:2]
|
||||
args = [kitten] + args
|
||||
os.environ['KITTY_CONFIG_DIRECTORY'] = config_dir
|
||||
from kittens.tui.operations import clear_screen, reset_mode
|
||||
m = import_kitten_main_module(config_dir, kitten)
|
||||
result = m['start'](args)
|
||||
print(reset_mode('ALTERNATE_SCREEN') + clear_screen(), end='')
|
||||
if result is not None:
|
||||
import json
|
||||
print('OK:', json.dumps(result))
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
args = sys.argv[1:]
|
||||
launch(args)
|
||||
except Exception:
|
||||
print('Unhandled exception running kitten:')
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
input('Press Enter to quit...')
|
||||
@@ -5,7 +5,6 @@
|
||||
import os
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
from gettext import gettext as _
|
||||
|
||||
@@ -454,26 +453,24 @@ class UnicodeInput(Handler):
|
||||
self.refresh()
|
||||
|
||||
|
||||
def run_loop(args):
|
||||
def main(args):
|
||||
loop = Loop()
|
||||
with cached_values_for('unicode-input') as cached_values:
|
||||
handler = UnicodeInput(cached_values)
|
||||
loop.loop(handler)
|
||||
if handler.current_char and loop.return_code == 0:
|
||||
print('OK:', hex(ord(handler.current_char))[2:])
|
||||
try:
|
||||
handler.recent.remove(ord(handler.current_char))
|
||||
except Exception:
|
||||
pass
|
||||
recent = [ord(handler.current_char)] + handler.recent
|
||||
cached_values['recent'] = recent[:len(DEFAULT_SET)]
|
||||
return loop.return_code
|
||||
return handler.current_char
|
||||
if loop.return_code != 0:
|
||||
raise SystemExit(loop.return_code)
|
||||
|
||||
|
||||
def main(args=sys.argv):
|
||||
try:
|
||||
raise SystemExit(run_loop(args))
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
input(_('Press Enter to quit.'))
|
||||
def handle_result(args, current_char, target_window_id, boss):
|
||||
w = boss.window_id_map.get(target_window_id)
|
||||
if w is not None:
|
||||
w.paste(current_char)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
import re
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from functools import lru_cache, partial
|
||||
@@ -12,7 +11,6 @@ from gettext import gettext as _
|
||||
|
||||
from kitty.cli import parse_args
|
||||
from kitty.key_encoding import ESCAPE, backspace_key, enter_key
|
||||
from kitty.utils import command_for_open
|
||||
|
||||
from ..tui.handler import Handler
|
||||
from ..tui.loop import Loop
|
||||
@@ -178,16 +176,7 @@ def run_loop(args, lines, index_map):
|
||||
handler = URLHints(lines, index_map)
|
||||
loop.loop(handler)
|
||||
if handler.chosen and loop.return_code == 0:
|
||||
if args.in_kitty:
|
||||
import json
|
||||
print('OK:', json.dumps({'url': handler.chosen, 'program': args.program, 'action': 'open_with'}))
|
||||
else:
|
||||
cmd = command_for_open(args.program)
|
||||
ret = subprocess.Popen(cmd + [handler.chosen]).wait()
|
||||
if ret != 0:
|
||||
print('URL handler "{}" failed with return code: {}'.format(' '.join(cmd), ret), file=sys.stderr)
|
||||
input('Press Enter to quit')
|
||||
loop.return_code = ret
|
||||
return {'url': handler.chosen, 'program': args.program}
|
||||
raise SystemExit(loop.return_code)
|
||||
|
||||
|
||||
@@ -215,7 +204,7 @@ def run(args, source_file=None):
|
||||
input(_('No URLs found, press Enter to abort.'))
|
||||
return
|
||||
|
||||
run_loop(args, lines, index_map)
|
||||
return run_loop(args, lines, index_map)
|
||||
|
||||
|
||||
OPTIONS = partial('''\
|
||||
@@ -234,16 +223,10 @@ expression instead.
|
||||
default={0}
|
||||
Comma separated list of recognized URL prefixes. Defaults to:
|
||||
{0}
|
||||
|
||||
|
||||
--in-kitty
|
||||
type=bool-set
|
||||
Output the URL instead of opening it. Intended for use from within
|
||||
kitty.
|
||||
'''.format, ','.join(sorted(URL_PREFIXES)))
|
||||
|
||||
|
||||
def main(args=sys.argv):
|
||||
def main(args):
|
||||
msg = 'Highlight URLs inside the specified text'
|
||||
try:
|
||||
args, items = parse_args(args[1:], OPTIONS, '[path to file or omit to use stdin]', msg, 'url_hints')
|
||||
@@ -251,9 +234,9 @@ def main(args=sys.argv):
|
||||
print(e.args[0], file=sys.stderr)
|
||||
input(_('Press Enter to quit'))
|
||||
return 1
|
||||
try:
|
||||
run(args, (items or [None])[0])
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
input(_('Press Enter to quit'))
|
||||
return run(args, (items or [None])[0])
|
||||
|
||||
|
||||
def handle_result(args, data, target_window_id, boss):
|
||||
program = data['program']
|
||||
boss.open_url(data['url'], None if program == 'default' else program)
|
||||
|
||||
Reference in New Issue
Block a user