diff --git a/kittens/tui/handler.py b/kittens/tui/handler.py index 3e09d8ef0..083ebc3f3 100644 --- a/kittens/tui/handler.py +++ b/kittens/tui/handler.py @@ -34,3 +34,7 @@ class Handler: if isinstance(data, str): data = data.encode('utf-8') self.write_buf.append(data) + + def print(self, *args, sep=' ', end='\r\n'): + data = sep.join(map(str, args)) + end + self.write(data) diff --git a/kittens/tui/loop.py b/kittens/tui/loop.py index 2530297be..ca26b5f57 100644 --- a/kittens/tui/loop.py +++ b/kittens/tui/loop.py @@ -303,8 +303,14 @@ class Loop: signal.signal(signal.SIGTERM, self._on_sigterm) signal.signal(signal.SIGINT, self._on_sigint) handler.write_buf = [] - handler.initialize(screen_size(), self.quit, self.wakeup) keep_going = True + try: + handler.initialize(screen_size(), self.quit, self.wakeup) + except Exception: + import traceback + tb = traceback.format_exc() + self.return_code = 1 + keep_going = False while keep_going: has_data_to_write = bool(handler.write_buf) if not has_data_to_write and not self.read_allowed: diff --git a/kittens/tui/operations.py b/kittens/tui/operations.py index 1d029b5a0..f1065bd83 100644 --- a/kittens/tui/operations.py +++ b/kittens/tui/operations.py @@ -46,6 +46,28 @@ def clear_screen(): return string_capabilities['clear'].replace(r'\E', '\033').encode('ascii') +def set_window_title(value): + return ('\033]2;' + value.replace('\033', '').replace('\x9c', '') + '\033\\').encode('utf-8') + + +def set_line_wrapping(yes_or_no): + return (set_mode if yes_or_no else reset_mode)('DECAWM') + + +STANDARD_COLORS = {name: i for i, name in enumerate( + 'black red green yellow blue magenta cyan gray'.split())} + + +def colored(text, color, intense=False): + if isinstance(color, str): + e = (90 if intense else 30) + STANDARD_COLORS[color] + elif isinstance(color, int): + e = '38:5:{}'.format(max(0, min(color, 255))) + else: + e = '38:2:{}:{}:{}'.format(*color) + return '\033[{}m{}\033[39m'.format(e, text) + + def init_state(alternate_screen=True): ans = ( S7C1T + SAVE_CURSOR + SAVE_PRIVATE_MODE_VALUES + reset_mode('LNM') + diff --git a/kittens/unicode_input/main.py b/kittens/unicode_input/main.py index fcae4e688..8d1e217ef 100644 --- a/kittens/unicode_input/main.py +++ b/kittens/unicode_input/main.py @@ -4,15 +4,73 @@ import sys +from kitty.fast_data_types import wcswidth +from kitty.key_encoding import backspace_key, enter_key, ESCAPE + from ..tui.handler import Handler from ..tui.loop import Loop +from ..tui.operations import ( + clear_screen, colored, set_line_wrapping, set_window_title +) class UnicodeInput(Handler): + def __init__(self): + self.current_input = '' + self.current_char = None + self.prompt_template = '{}> ' + self.update_prompt() + + def update_current_char(self): + try: + code = int(self.current_input, 16) + if code <= 32 or code == 127 or 128 <= code <= 159: + self.current_char = None + else: + self.current_char = chr(code) + except Exception: + self.current_char = None + + def update_prompt(self): + self.update_current_char() + if self.current_char is None: + c, color = '??', 'red' + else: + c, color = self.current_char, 'green' + w = wcswidth(c) + self.prompt = self.prompt_template.format(colored(c, color)) + self.promt_len = w + len(self.prompt_template) - 2 + def initialize(self, *args): Handler.initialize(self, *args) - self.write('Testing 123...') + self.write(set_line_wrapping(False)) + self.write(set_window_title('Unicode input')) + self.draw_screen() + + def draw_screen(self): + self.write(clear_screen()) + self.print('Enter the hex code for the unicode character') + self.write(self.prompt) + self.write(self.current_input) + + def refresh(self): + self.update_prompt() + self.draw_screen() + + def on_text(self, text, in_bracketed_paste): + self.current_input += text + self.refresh() + + def on_key(self, key_event): + if key_event is backspace_key: + self.current_input = self.current_input[:-1] + self.refresh() + elif key_event is enter_key: + self.quit_loop(0) + else: + if key_event.key is ESCAPE: + self.quit_loop(1) def on_interrupt(self): self.quit_loop(1) @@ -20,8 +78,15 @@ class UnicodeInput(Handler): def on_eot(self): self.quit_loop(1) + def on_resize(self, new_size): + Handler.on_resize(self, new_size) + self.draw_screen() + def main(args=sys.argv): loop = Loop() handler = UnicodeInput() loop.loop(handler) + if handler.current_char and loop.return_code == 0: + print(hex(ord(handler.current_char))[2:]) + raise SystemExit(loop.return_code)