diff --git a/README.asciidoc b/README.asciidoc index 192b7373f..e73f117ec 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -30,6 +30,7 @@ :sc_previous_tab: pass:quotes[`ctrl+shift+left`] :sc_previous_window: pass:quotes[`ctrl+shift+[`] :sc_restore_font_size: pass:quotes[`ctrl+shift+backspace`] +:sc_run_simple_kitten_text_url_hints: pass:quotes[`ctrl+shift+e`] :sc_scroll_end: pass:quotes[`ctrl+shift+end`] :sc_scroll_home: pass:quotes[`ctrl+shift+home`] :sc_scroll_line_down: pass:quotes[`ctrl+shift+down` or `ctrl+shift+j`] @@ -228,6 +229,7 @@ windows are: |Restore font size | {sc_restore_font_size} |Toggle fullscreen | {sc_toggle_fullscreen} |Input unicode character | {sc_input_unicode_character} +|Click URL using the keyboard | {sc_run_simple_kitten_text_url_hints} |Pass current selection to program | {sc_pass_selection_to_program} |=== diff --git a/kittens/url_hints/main.py b/kittens/url_hints/main.py index e5f36ac0f..edce53510 100644 --- a/kittens/url_hints/main.py +++ b/kittens/url_hints/main.py @@ -4,6 +4,7 @@ import re import string +import subprocess import sys from collections import namedtuple from functools import lru_cache, partial @@ -11,7 +12,7 @@ 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 open_url, read_with_timeout +from kitty.utils import command_for_open, read_with_timeout from ..tui.handler import Handler from ..tui.loop import Loop @@ -187,7 +188,8 @@ def mark(finditer, line, index_map): def run(args, source_file=None): if source_file is None: - text = read_from_stdin() + text = sys.stdin.buffer.read().decode('utf-8') + sys.stdin = open('/dev/tty') else: with open(source_file, 'r') as f: text = f.read() @@ -209,12 +211,18 @@ def run(args, source_file=None): handler = URLHints(lines, index_map) loop.loop(handler) if handler.chosen and loop.return_code == 0: - open_url(handler.chosen, program=args.program or 'default') + 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 raise SystemExit(loop.return_code) OPTIONS = partial('''\ --program +default=default What program to use to open matched URLs. Defaults to the default URL open program for the operating system. diff --git a/kitty/boss.py b/kitty/boss.py index 27f353849..baa1bcfba 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -397,6 +397,29 @@ class Boss: else: w.paste(text) + def run_simple_kitten(self, type_of_input, kitten, *args): + import shlex + w = self.active_window + tab = self.active_tab + if w is not None and tab is not None and w.overlay_for is None: + cmdline = args[0] if args else '' + args = shlex.split(cmdline) if cmdline else [] + if '--program' not in cmdline: + args.extend(('--program', self.opts.open_url_with)) + if type_of_input in ('text', 'history'): + data = (w.buffer_as_text(add_history=type_of_input == 'history') + '\x1c').encode('utf-8') + elif type_of_input in ('ansi', 'ansi-history'): + data = (w.buffer_as_ansi(add_history=type_of_input == 'ansi-history') + '\x1c').encode('utf-8') + elif type_of_input == 'none': + data = None + else: + raise ValueError('Unknown type_of_input: {}'.format(type_of_input)) + tab.new_special_window( + SpecialWindow( + ['kitty', '+runpy', 'from kittens.{}.main import main; main()'.format(kitten)] + args, + stdin=data, + overlay_for=w.id)) + def switch_focus_to(self, window_idx): tab = self.active_tab tab.set_active_window_idx(window_idx) diff --git a/kitty/config.py b/kitty/config.py index 1d0a683fa..5d4ac4f49 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -111,6 +111,8 @@ def parse_key_action(action): args = tuple(map(parse_key_action, filter(None, parts))) elif func == 'send_text': args = rest.split(' ', 1) + elif func == 'run_simple_kitten': + args = rest.split(' ', 2) elif func == 'goto_tab': args = (max(0, int(rest)), ) elif func in shlex_actions: diff --git a/kitty/kitty.conf b/kitty/kitty.conf index 673fd879f..de561a133 100644 --- a/kitty/kitty.conf +++ b/kitty/kitty.conf @@ -329,6 +329,11 @@ map ctrl+shift+minus decrease_font_size map ctrl+shift+backspace restore_font_size map ctrl+shift+f11 toggle_fullscreen map ctrl+shift+u input_unicode_character +# Open a currently visible URL using the keyboard. The program used ot open the URL is specified in open_url_with. +# You can customize how the URLs are detected and opened by specifying command line options to +# url_hints. For example: +# map ctrl+shift+e run_simple_kitten text url_hints --program firefox --regex "http://[^ ]+" +map ctrl+shift+e run_simple_kitten text url_hints # Sending arbitrary text on shortcut key presses # You can tell kitty to send arbitrary (UTF-8) encoded text to diff --git a/kitty/utils.py b/kitty/utils.py index 131b3f9fc..932e7584e 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -111,6 +111,14 @@ def base64_encode( return ans +def command_for_open(program='default'): + if program == 'default': + cmd = ['open'] if is_macos else ['xdg-open'] + else: + cmd = shlex.split(program) + return cmd + + def open_cmd(cmd, arg=None): if arg is not None: cmd = list(cmd) @@ -119,11 +127,7 @@ def open_cmd(cmd, arg=None): def open_url(url, program='default'): - if program == 'default': - cmd = ['open'] if is_macos else ['xdg-open'] - else: - cmd = shlex.split(program) - return open_cmd(cmd, url) + return open_cmd(command_for_open(program), url) def detach(fork=True, setsid=True, redirect=True): diff --git a/preprocess-readme.py b/preprocess-readme.py index a26612810..abc409a02 100755 --- a/preprocess-readme.py +++ b/preprocess-readme.py @@ -15,7 +15,8 @@ defns = defaultdict(list) for line in open('kitty/kitty.conf'): if line.startswith('map '): - _, sc, name = line.split(maxsplit=3) + _, sc, name = line.split(maxsplit=2) + name = name.rstrip().replace(' ', '_') defns[name].append('`' + sc + '`') defns = [