parent
e3f60e6fa7
commit
65fef81f29
@ -14,6 +14,9 @@ Changelog
|
|||||||
|
|
||||||
- macOS: Fix an error in remote control when using --listen-on (:iss:`679`)
|
- macOS: Fix an error in remote control when using --listen-on (:iss:`679`)
|
||||||
|
|
||||||
|
- hints kitten: Add a :option:`kitty +kitten hints --multiple` option to select
|
||||||
|
multiple items (:iss:`687`)
|
||||||
|
|
||||||
- Fix pasting large amounts of text very slow (:iss:`682`)
|
- Fix pasting large amounts of text very slow (:iss:`682`)
|
||||||
|
|
||||||
- Add a :option:`kitty --hold` command line option to stay open after the child process exits (:iss:`667`)
|
- Add a :option:`kitty --hold` command line option to stay open after the child process exits (:iss:`667`)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ HINT_ALPHABET = string.digits + string.ascii_lowercase
|
|||||||
screen_size = screen_size_function()
|
screen_size = screen_size_function()
|
||||||
|
|
||||||
|
|
||||||
class Mark(object):
|
class Mark:
|
||||||
|
|
||||||
__slots__ = ('index', 'start', 'end', 'text')
|
__slots__ = ('index', 'start', 'end', 'text')
|
||||||
|
|
||||||
@ -63,8 +63,10 @@ def highlight_mark(m, text, current_input):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def render(text, current_input, all_marks):
|
def render(text, current_input, all_marks, ignore_mark_indices):
|
||||||
for mark in reversed(all_marks):
|
for mark in reversed(all_marks):
|
||||||
|
if mark.index in ignore_mark_indices:
|
||||||
|
continue
|
||||||
mtext = highlight_mark(mark, text[mark.start:mark.end], current_input)
|
mtext = highlight_mark(mark, text[mark.start:mark.end], current_input)
|
||||||
text = text[:mark.start] + mtext + text[mark.end:]
|
text = text[:mark.start] + mtext + text[mark.end:]
|
||||||
|
|
||||||
@ -78,11 +80,16 @@ class Hints(Handler):
|
|||||||
def __init__(self, text, all_marks, index_map, args):
|
def __init__(self, text, all_marks, index_map, args):
|
||||||
self.text, self.index_map = text, index_map
|
self.text, self.index_map = text, index_map
|
||||||
self.all_marks = all_marks
|
self.all_marks = all_marks
|
||||||
self.current_input = ''
|
self.ignore_mark_indices = set()
|
||||||
self.current_text = None
|
|
||||||
self.args = args
|
self.args = args
|
||||||
self.window_title = _('Choose URL') if args.type == 'url' else _('Choose text')
|
self.window_title = _('Choose URL') if args.type == 'url' else _('Choose text')
|
||||||
self.chosen = None
|
self.multiple = args.multiple
|
||||||
|
self.chosen = []
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.current_input = ''
|
||||||
|
self.current_text = None
|
||||||
|
|
||||||
def init_terminal_state(self):
|
def init_terminal_state(self):
|
||||||
self.cmd.set_cursor_visible(False)
|
self.cmd.set_cursor_visible(False)
|
||||||
@ -101,11 +108,15 @@ class Hints(Handler):
|
|||||||
changed = True
|
changed = True
|
||||||
if changed:
|
if changed:
|
||||||
matches = [
|
matches = [
|
||||||
m.text for idx, m in self.index_map.items()
|
m for idx, m in self.index_map.items()
|
||||||
if encode_hint(idx).startswith(self.current_input)
|
if encode_hint(idx).startswith(self.current_input)
|
||||||
]
|
]
|
||||||
if len(matches) == 1:
|
if len(matches) == 1:
|
||||||
self.chosen = matches[0]
|
self.chosen.append(matches[0].text)
|
||||||
|
if self.multiple:
|
||||||
|
self.ignore_mark_indices.add(matches[0].index)
|
||||||
|
self.reset()
|
||||||
|
else:
|
||||||
self.quit_loop(0)
|
self.quit_loop(0)
|
||||||
return
|
return
|
||||||
self.current_text = None
|
self.current_text = None
|
||||||
@ -119,15 +130,20 @@ class Hints(Handler):
|
|||||||
elif key_event is enter_key and self.current_input:
|
elif key_event is enter_key and self.current_input:
|
||||||
try:
|
try:
|
||||||
idx = decode_hint(self.current_input)
|
idx = decode_hint(self.current_input)
|
||||||
self.chosen = self.index_map[idx].text
|
self.chosen.append(self.index_map[idx].text)
|
||||||
|
self.ignore_mark_indices.add(idx)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.current_input = ''
|
self.current_input = ''
|
||||||
self.current_text = None
|
self.current_text = None
|
||||||
self.draw_screen()
|
self.draw_screen()
|
||||||
|
else:
|
||||||
|
if self.multiple:
|
||||||
|
self.reset()
|
||||||
|
self.draw_screen()
|
||||||
else:
|
else:
|
||||||
self.quit_loop(0)
|
self.quit_loop(0)
|
||||||
elif key_event.key is ESCAPE:
|
elif key_event.key is ESCAPE:
|
||||||
self.quit_loop(1)
|
self.quit_loop(0 if self.multiple else 1)
|
||||||
|
|
||||||
def on_interrupt(self):
|
def on_interrupt(self):
|
||||||
self.quit_loop(1)
|
self.quit_loop(1)
|
||||||
@ -141,7 +157,7 @@ class Hints(Handler):
|
|||||||
|
|
||||||
def draw_screen(self):
|
def draw_screen(self):
|
||||||
if self.current_text is None:
|
if self.current_text is None:
|
||||||
self.current_text = render(self.text, self.current_input, self.all_marks)
|
self.current_text = render(self.text, self.current_input, self.all_marks, self.ignore_mark_indices)
|
||||||
self.cmd.clear_screen()
|
self.cmd.clear_screen()
|
||||||
self.write(self.current_text)
|
self.write(self.current_text)
|
||||||
|
|
||||||
@ -342,6 +358,12 @@ Defaults to the select_by_word_characters setting from kitty.conf.
|
|||||||
default=3
|
default=3
|
||||||
type=int
|
type=int
|
||||||
The minimum number of characters to consider a match.
|
The minimum number of characters to consider a match.
|
||||||
|
|
||||||
|
|
||||||
|
--multiple
|
||||||
|
type=bool-set
|
||||||
|
Select multiple matches and perform the action on all of them together at the end.
|
||||||
|
In this mode, press :kbd:`Esc` to finish selecting.
|
||||||
'''.format(','.join(sorted(URL_PREFIXES))).format
|
'''.format(','.join(sorted(URL_PREFIXES))).format
|
||||||
help_text = 'Select text from the screen using the keyboard. Defaults to searching for URLs.'
|
help_text = 'Select text from the screen using the keyboard. Defaults to searching for URLs.'
|
||||||
usage = ''
|
usage = ''
|
||||||
@ -377,18 +399,22 @@ def main(args):
|
|||||||
|
|
||||||
def handle_result(args, data, target_window_id, boss):
|
def handle_result(args, data, target_window_id, boss):
|
||||||
program = data['program']
|
program = data['program']
|
||||||
|
matches = tuple(filter(None, data['match']))
|
||||||
if program == '-':
|
if program == '-':
|
||||||
w = boss.window_id_map.get(target_window_id)
|
w = boss.window_id_map.get(target_window_id)
|
||||||
if w is not None:
|
if w is not None:
|
||||||
w.paste(data['match'])
|
for m in matches:
|
||||||
|
w.paste(m)
|
||||||
elif program == '@':
|
elif program == '@':
|
||||||
set_clipboard_string(data['match'])
|
set_clipboard_string(matches[-1])
|
||||||
else:
|
else:
|
||||||
cwd = None
|
cwd = None
|
||||||
w = boss.window_id_map.get(target_window_id)
|
w = boss.window_id_map.get(target_window_id)
|
||||||
if w is not None:
|
if w is not None:
|
||||||
cwd = w.cwd_of_child
|
cwd = w.cwd_of_child
|
||||||
boss.open_url(data['match'], None if program == 'default' else program, cwd=cwd)
|
program = None if program == 'default' else program
|
||||||
|
for m in matches:
|
||||||
|
boss.open_url(m, program, cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
handle_result.type_of_input = 'screen'
|
handle_result.type_of_input = 'screen'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user