Add basic editing support for the broadcast kitten

This commit is contained in:
Kovid Goyal 2020-12-01 17:35:15 +05:30
parent 34db18ea0a
commit 00aba7c646
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 54 additions and 16 deletions

View File

@ -12,11 +12,12 @@
from kitty.key_encoding import RELEASE, encode_key_event, key_defs as K
from kitty.rc.base import MATCH_TAB_OPTION, MATCH_WINDOW_OPTION
from kitty.remote_control import create_basic_command, encode_send
from kitty.typing import KeyEventType
from kitty.typing import KeyEventType, ScreenSize
from ..tui.handler import Handler
from ..tui.line_edit import LineEdit
from ..tui.loop import Loop
from ..tui.operations import styled
from ..tui.operations import RESTORE_CURSOR, SAVE_CURSOR, styled
class Broadcast(Handler):
@ -25,6 +26,7 @@ def __init__(self, opts: BroadcastCLIOptions, initial_strings: List[str]) -> Non
self.opts = opts
self.initial_strings = initial_strings
self.payload = {'exclude_active': True, 'data': '', 'match': opts.match_tab, 'match_tab': opts.match_tab}
self.line_edit = LineEdit()
if not opts.match and not opts.match_tab:
self.payload['all'] = True
@ -32,10 +34,21 @@ def initialize(self) -> None:
self.print('Type the text to broadcast below, press', styled('Ctrl+c', fg='yellow'), 'to quit:')
for x in self.initial_strings:
self.write_broadcast_text(x)
self.write(SAVE_CURSOR)
def commit_line(self) -> None:
self.write(RESTORE_CURSOR + SAVE_CURSOR)
self.cmd.clear_to_end_of_screen()
self.line_edit.write(self.write, screen_cols=self.screen_size.cols)
def on_resize(self, screen_size: ScreenSize) -> None:
super().on_resize(screen_size)
self.commit_line()
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
self.write_broadcast_text(text)
self.write(text)
self.line_edit.on_text(text, in_bracketed_paste)
self.commit_line()
def on_interrupt(self) -> None:
self.quit_loop(0)
@ -44,19 +57,16 @@ def on_eot(self) -> None:
self.write_broadcast_text('\x04')
def on_key(self, key_event: KeyEventType) -> None:
if self.line_edit.on_key(key_event):
self.commit_line()
if key_event.type is not RELEASE and not key_event.mods:
if key_event.key is K['TAB']:
self.write_broadcast_text('\t')
self.write('\t')
return
elif key_event.key is K['BACKSPACE']:
self.write_broadcast_text('\177')
self.write('\x08\x1b[X')
return
elif key_event.key is K['ENTER']:
if key_event.key is K['ENTER']:
self.write_broadcast_text('\r')
self.print('')
self.line_edit.clear()
self.write(SAVE_CURSOR)
return
ek = encode_key_event(key_event)
self.write_broadcast_data('kitty-key:' + ek)

View File

@ -7,6 +7,8 @@
from kitty.fast_data_types import truncate_point_for_length, wcswidth
from kitty.key_encoding import RELEASE, KeyEvent, key_defs as K
from .operations import RESTORE_CURSOR, SAVE_CURSOR, move_cursor_by
HOME = K['HOME']
END = K['END']
BACKSPACE = K['BACKSPACE']
@ -31,13 +33,28 @@ def split_at_cursor(self, delta: int = 0) -> Tuple[str, str]:
before, after = self.current_input[:x], self.current_input[x:]
return before, after
def write(self, write: Callable[[str], None], prompt: str = '') -> None:
def write(self, write: Callable[[str], None], prompt: str = '', screen_cols: int = 0) -> None:
if self.pending_bell:
write('\a')
self.pending_bell = False
write(prompt)
write(self.current_input)
write('\r\x1b[{}C'.format(self.cursor_pos + wcswidth(prompt)))
text = prompt + self.current_input
cursor_pos = self.cursor_pos + wcswidth(prompt)
if screen_cols:
write(SAVE_CURSOR + text + RESTORE_CURSOR)
used_lines, last_line_cursor_pos = divmod(cursor_pos, screen_cols)
if used_lines == 0:
if last_line_cursor_pos:
write(move_cursor_by(last_line_cursor_pos, 'right'))
else:
if used_lines:
write(move_cursor_by(used_lines, 'down'))
if last_line_cursor_pos:
write(move_cursor_by(last_line_cursor_pos, 'right'))
else:
write(text)
write('\r')
if cursor_pos:
write(move_cursor_by(cursor_pos, 'right'))
def add_text(self, text: str) -> None:
if self.current_input:

View File

@ -68,6 +68,11 @@ def clear_screen() -> str:
return '\033[H\033[2J'
@cmd
def clear_to_end_of_screen() -> str:
return '\033[J'
@cmd
def clear_to_eol() -> str:
return '\033[K'
@ -108,6 +113,12 @@ def set_cursor_position(x: int, y: int) -> str: # (0, 0) is top left
return '\033[{};{}H'.format(y + 1, x + 1)
@cmd
def move_cursor_by(amt: int, direction: str) -> str:
suffix = {'up': 'A', 'down': 'B', 'right': 'C', 'left': 'D'}[direction]
return f'\033[{amt}{suffix}'
@cmd
def set_cursor_shape(shape: str = 'block', blink: bool = True) -> str:
val = {'block': 1, 'underline': 3, 'bar': 5}.get(shape, 1)