diff --git a/kittens/hints/main.py b/kittens/hints/main.py index 1c79b7809..eb47a4516 100644 --- a/kittens/hints/main.py +++ b/kittens/hints/main.py @@ -27,6 +27,7 @@ from kitty.utils import ( from ..tui.handler import Handler, result_handler from ..tui.loop import Loop from ..tui.operations import faint, styled +from ..tui.utils import report_unhandled_error @lru_cache() @@ -117,6 +118,8 @@ def render(text: str, current_input: str, all_marks: Sequence[Mark], ignore_mark class Hints(Handler): + overlay_ready_report_needed = True + def __init__(self, text: str, all_marks: Sequence[Mark], index_map: Dict[int, Mark], args: HintsCLIOptions): self.text, self.index_map = text, index_map self.alphabet = args.alphabet or DEFAULT_HINT_ALPHABET @@ -159,7 +162,6 @@ class Hints(Handler): def initialize(self) -> None: self.init_terminal_state() self.draw_screen() - self.cmd.overlay_ready() def on_text(self, text: str, in_bracketed_paste: bool = False) -> None: changed = False @@ -513,11 +515,7 @@ def run(args: HintsCLIOptions, text: str, extra_cli_args: Sequence[str] = ()) -> m.index = largest_index - m.index + offset index_map = {m.index: m for m in all_marks} except Exception: - import traceback - traceback.print_exc() - input('Press Enter to quit.') - raise SystemExit(1) - + report_unhandled_error() return run_loop(args, text, all_marks, index_map, extra_cli_args) @@ -678,9 +676,7 @@ def main(args: List[str]) -> Optional[Dict[str, Any]]: text = '' if sys.stdin.isatty(): if '--help' not in args and '-h' not in args: - print('You must pass the text to be hinted on STDIN', file=sys.stderr) - input(_('Press Enter to quit')) - return None + report_unhandled_error('You must pass the text to be hinted on STDIN') else: text = sys.stdin.buffer.read().decode('utf-8') sys.stdin = open(os.ctermid()) @@ -688,18 +684,14 @@ def main(args: List[str]) -> Optional[Dict[str, Any]]: opts, items = parse_hints_args(args[1:]) except SystemExit as e: if e.code != 0: - print(e.args[0], file=sys.stderr) - input(_('Press Enter to quit')) + report_unhandled_error(e.args[0]) return None if items and not (opts.customize_processing or opts.type == 'linenum'): - print('Extra command line arguments present: {}'.format(' '.join(items)), file=sys.stderr) - input(_('Press Enter to quit')) + report_unhandled_error('Extra command line arguments present: {}'.format(' '.join(items))) try: return run(opts, text, items) except Exception: - import traceback - traceback.print_exc() - input(_('Press Enter to quit')) + report_unhandled_error() return None @@ -753,7 +745,7 @@ def linenum_handle_result(args: List[str], data: Dict[str, Any], target_window_i }[action])(*cmd) -@result_handler(type_of_input='screen-ansi', has_ready_notification=True) +@result_handler(type_of_input='screen-ansi', has_ready_notification=Handler.overlay_ready_report_needed) def handle_result(args: List[str], data: Dict[str, Any], target_window_id: int, boss: BossType) -> None: if data['customize_processing']: m = load_custom_processor(data['customize_processing']) diff --git a/kittens/tui/handler.py b/kittens/tui/handler.py index 312a96c1a..ebf1d2569 100644 --- a/kittens/tui/handler.py +++ b/kittens/tui/handler.py @@ -44,6 +44,7 @@ class Handler: use_alternate_screen = True mouse_tracking = MouseTracking.none terminal_io_ended = False + overlay_ready_report_needed = False def _initialize( self, @@ -219,7 +220,7 @@ class HandleResult: def result_handler( type_of_input: Optional[str] = None, no_ui: bool = False, - has_ready_notification: bool = False + has_ready_notification: bool = Handler.overlay_ready_report_needed ) -> Callable[[Callable[..., Any]], HandleResult]: def wrapper(impl: Callable[..., Any]) -> HandleResult: diff --git a/kittens/tui/loop.py b/kittens/tui/loop.py index 3ea9b22f2..4d2d62aec 100644 --- a/kittens/tui/loop.py +++ b/kittens/tui/loop.py @@ -236,6 +236,7 @@ class Loop: else: self.asyncio_loop = asyncio.get_event_loop() self.return_code = 0 + self.overlay_ready_reported = False self.optional_actions = optional_actions self.read_buf = '' self.decoder = codecs.getincrementaldecoder('utf-8')('ignore') @@ -435,6 +436,8 @@ class Loop: self.asyncio_loop.set_exception_handler(handle_exception) handler._initialize(self._get_screen_size(), term_manager, schedule_write, self, debug, image_manager) with handler: + if handler.overlay_ready_report_needed: + handler.cmd.overlay_ready() self.asyncio_loop.add_reader( tty_fd, self._read_ready, handler, tty_fd) self.asyncio_loop.add_writer( @@ -467,9 +470,12 @@ class Loop: term_manager.extra_finalize = b''.join(self.write_buf).decode('utf-8') if tb is not None: + report_overlay_ready = handler.overlay_ready_report_needed and not self.overlay_ready_reported self.return_code = 1 if not handler.terminal_io_ended: - self._report_error_loop(tb, term_manager) + self._report_error_loop(tb, term_manager, report_overlay_ready) - def _report_error_loop(self, tb: str, term_manager: TermManager) -> None: - self.loop_impl(UnhandledException(tb), term_manager) + def _report_error_loop(self, tb: str, term_manager: TermManager, overlay_ready_report_needed: bool) -> None: + handler = UnhandledException(tb) + handler.overlay_ready_report_needed = overlay_ready_report_needed + self.loop_impl(handler, term_manager) diff --git a/kittens/tui/utils.py b/kittens/tui/utils.py index 15ed4efa2..c8262a310 100644 --- a/kittens/tui/utils.py +++ b/kittens/tui/utils.py @@ -48,3 +48,17 @@ def human_size( from math import log exponent = min(int(log(size, 1024)), len(unit_list) - 1) return format_number(size / 1024**exponent, max_num_of_decimals) + sep + unit_list[exponent] + + +def report_unhandled_error(msg: str = '') -> None: + ' Report an unhandled exception also sending the overlay ready message to ensure kitten is visible ' + from .operations import overlay_ready + print(end=overlay_ready()) + if msg: + print(msg, file=sys.stderr) + cls, e, tb = sys.exc_info() + if not isinstance(e, (SystemExit, KeyboardInterrupt)): + import traceback + traceback.print_exc() + input('Press Enter to quit.') + raise SystemExit(1) diff --git a/kittens/unicode_input/main.py b/kittens/unicode_input/main.py index 6738b6836..adbf60861 100644 --- a/kittens/unicode_input/main.py +++ b/kittens/unicode_input/main.py @@ -28,6 +28,7 @@ from ..tui.operations import ( clear_screen, colored, cursor, faint, set_line_wrapping, set_window_title, sgr, styled ) +from ..tui.utils import report_unhandled_error HEX, NAME, EMOTICONS, FAVORITES = 'HEX', 'NAME', 'EMOTICONS', 'FAVORITES' favorites_path = os.path.join(config_dir, 'unicode-input-favorites.conf') @@ -567,8 +568,7 @@ def main(args: List[str]) -> Optional[str]: cli_opts, items = parse_unicode_input_args(args[1:]) except SystemExit as e: if e.code != 0: - print(e.args[0], file=sys.stderr) - input(_('Press Enter to quit')) + report_unhandled_error(e.args[0]) return None loop = Loop()