Finish up the URL hints kitten

This commit is contained in:
Kovid Goyal
2018-02-14 12:34:01 +05:30
parent 62174fdbcc
commit 57cf789c75
2 changed files with 42 additions and 17 deletions

View File

@@ -56,6 +56,10 @@ def set_line_wrapping(yes_or_no):
return (set_mode if yes_or_no else reset_mode)('DECAWM') return (set_mode if yes_or_no else reset_mode)('DECAWM')
def set_cursor_visible(yes_or_no):
return (set_mode if yes_or_no else reset_mode)('DECTCEM')
STANDARD_COLORS = {name: i for i, name in enumerate( STANDARD_COLORS = {name: i for i, name in enumerate(
'black red green yellow blue magenta cyan gray'.split())} 'black red green yellow blue magenta cyan gray'.split())}
UNDERLINE_STYLES = {name: i + 1 for i, name in enumerate( UNDERLINE_STYLES = {name: i + 1 for i, name in enumerate(

View File

@@ -9,12 +9,15 @@ from collections import namedtuple
from functools import lru_cache, partial from functools import lru_cache, partial
from gettext import gettext as _ from gettext import gettext as _
from kitty.cli import parse_args
from kitty.key_encoding import ESCAPE, backspace_key, enter_key from kitty.key_encoding import ESCAPE, backspace_key, enter_key
from kitty.utils import read_with_timeout from kitty.utils import open_url, read_with_timeout
from ..tui.handler import Handler from ..tui.handler import Handler
from ..tui.loop import Loop from ..tui.loop import Loop
from ..tui.operations import clear_screen, faint, set_window_title, styled from ..tui.operations import (
clear_screen, faint, set_cursor_visible, set_window_title, styled
)
Mark = namedtuple('Mark', 'index start end text') Mark = namedtuple('Mark', 'index start end text')
URL_PREFIXES = 'http https file ftp'.split() URL_PREFIXES = 'http https file ftp'.split()
@@ -48,9 +51,7 @@ def render(lines, current_input):
return styled( return styled(
hint, hint,
fg='black', fg='black',
fg_intense=True,
bg='green', bg='green',
bg_intense=True,
bold=True bold=True
) + styled( ) + styled(
text, fg='gray', fg_intense=True, bold=True text, fg='gray', fg_intense=True, bold=True
@@ -61,13 +62,13 @@ def render(lines, current_input):
ans.append(faint(line)) ans.append(faint(line))
continue continue
buf = [] buf = []
if marks[0].start:
buf.append(faint(line[:marks[0].start]))
for i, m in enumerate(marks): for i, m in enumerate(marks):
if i == 0 and m.start:
buf.append(faint(line[:m.start]))
buf.append(mark(m))
if m is not marks[-1]: if m is not marks[-1]:
buf.append(faint(line[m.end:marks[i + 1].start])) buf.append(faint(line[m.end:marks[i + 1].start]))
buf.append(mark(m))
rest = line[marks[-1].end:] rest = line[marks[-1].end:]
if rest: if rest:
@@ -86,6 +87,7 @@ class URLHints(Handler):
self.chosen = None self.chosen = None
def init_terminal_state(self): def init_terminal_state(self):
self.write(set_cursor_visible(False))
self.write(set_window_title(_('Choose URL'))) self.write(set_window_title(_('Choose URL')))
def initialize(self, *args): def initialize(self, *args):
@@ -137,6 +139,7 @@ class URLHints(Handler):
if self.current_text is None: if self.current_text is None:
self.current_text = render(self.lines, self.current_input) self.current_text = render(self.lines, self.current_input)
self.write(clear_screen()) self.write(clear_screen())
self.write(self.current_text)
def read_from_stdin(): def read_from_stdin():
@@ -156,17 +159,19 @@ def read_from_stdin():
def regex_finditer(pat, line): def regex_finditer(pat, line):
for m in pat.finditer(line): for m in pat.finditer(line):
yield m.start(), m.end() s, e = m.span()
if e - s > 2:
yield s, e
def find_urls(pat, line): def find_urls(pat, line):
for m in pat.finditer(line): for m in pat.finditer(line):
s, e = m.start(), m.end() s, e = m.span()
url = line[s:e]
if s > 4 and line[s - 5:s] == 'link:': # asciidoc URLs if s > 4 and line[s - 5:s] == 'link:': # asciidoc URLs
url = line[s:e]
idx = url.rfind('[') idx = url.rfind('[')
if idx > -1: if idx > -1:
e = idx e -= len(url) - idx
yield s, e yield s, e
@@ -180,20 +185,20 @@ def mark(finditer, line, index_map):
return line, marks return line, marks
def run(source_file=None, regex=None, opener=None): def run(source_file=None, regex=None, program=None):
if source_file is None: if source_file is None:
text = read_from_stdin() text = read_from_stdin()
else: else:
with open(source_file, 'r') as f: with open(source_file, 'r') as f:
text = f.read() text = f.read()
if regex is None: if regex is None:
finditer = partial(regex_finditer, re.compile(regex))
else:
from .url_regex import url_delimiters from .url_regex import url_delimiters
url_pat = '(?:{})://[^{}]{3,}'.format( url_pat = '(?:{})://[^{}]{{3,}}'.format(
'|'.join(URL_PREFIXES), url_delimiters '|'.join(URL_PREFIXES), url_delimiters
) )
finditer = partial(find_urls, url_pat) finditer = partial(find_urls, re.compile(url_pat))
else:
finditer = partial(regex_finditer, re.compile(regex))
lines = [] lines = []
index_map = {} index_map = {}
for line in text.splitlines(): for line in text.splitlines():
@@ -203,11 +208,27 @@ def run(source_file=None, regex=None, opener=None):
loop = Loop() loop = Loop()
handler = URLHints(lines, index_map) handler = URLHints(lines, index_map)
loop.loop(handler) loop.loop(handler)
if handler.chosen and loop.return_code == 0:
open_url(handler.chosen, program=program or 'default')
raise SystemExit(loop.return_code) raise SystemExit(loop.return_code)
OPTIONS = '''\
--program
What program to use to open matched URLs. Defaults
to the default URL open program for the operating system.
--regex
Instead of searching for URLs search for the specified regular
expression instead.
'''
def main(args=sys.argv): def main(args=sys.argv):
pass msg = 'Highlight URLs inside the specified text'
args, items = parse_args(args[1:], OPTIONS, '[path to file or omit to use stdin]', msg, 'url_hints')
run((items or [None])[0], args.regex, args.program)
if __name__ == '__main__': if __name__ == '__main__':