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:
Kovid Goyal
2018-04-11 13:03:40 +05:30
parent 5755ba72b1
commit 2cf8c6aea7
6 changed files with 98 additions and 76 deletions

59
kittens/runner.py Normal file
View 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...')

View File

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

View File

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