diff --git a/kittens/show_error/main.py b/kittens/show_error/main.py index 409369292..b22ebf954 100644 --- a/kittens/show_error/main.py +++ b/kittens/show_error/main.py @@ -1,13 +1,17 @@ #!/usr/bin/env python3 # License: GPL v3 Copyright: 2018, Kovid Goyal +import json import os import sys +import termios from contextlib import suppress from typing import List from kitty.cli import parse_args from kitty.cli_stub import ErrorCLIOptions +from kitty.fast_data_types import open_tty +from kitty.utils import hold_till_enter, no_echo, write_all from ..tui.operations import styled @@ -21,14 +25,35 @@ The title for the error message. def real_main(args: List[str]) -> None: msg = 'Show an error message' cli_opts, items = parse_args(args[1:], OPTIONS, '', msg, 'hints', result_class=ErrorCLIOptions) - error_message = sys.stdin.buffer.read().decode('utf-8') - sys.stdin = open(os.ctermid()) + data = json.loads(sys.stdin.buffer.read()) + error_message = data['msg'] if cli_opts.title: print(styled(cli_opts.title, fg_intense=True, fg='red', bold=True)) print() - print(error_message) - print() - input('\x1b[1;32mPress Enter to close\x1b[m') + print(error_message, flush=True) + if data.get('tb'): + import select + from kittens.tui.operations import init_state, set_cursor_visible + fd, original_termios = open_tty() + msg = '\n\r\x1b[1;32mPress e to see detailed traceback or any other key to exit\x1b[m' + write_all(fd, msg) + write_all(fd, init_state(alternate_screen=False, kitty_keyboard_mode=False) + set_cursor_visible(False)) + with no_echo(fd): + termios.tcdrain(fd) + while True: + rd = select.select([fd], [], [])[0] + if not rd: + break + q = os.read(fd, 1) + if q in b'eE': + break + return + if data.get('tb'): + tb = data['tb'] + for ln in tb.splitlines(): + print('\r\n', ln, sep='', end='') + print(flush=True) + hold_till_enter() def main(args: List[str]) -> None: diff --git a/kitty/boss.py b/kitty/boss.py index f42027f9f..662792cd5 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1452,7 +1452,12 @@ class Boss: break def show_error(self, title: str, msg: str) -> None: - self._run_kitten('show_error', args=['--title', title], input_data=msg) + ec = sys.exc_info() + tb = '' + if ec != (None, None, None): + import traceback + tb = traceback.format_exc() + self._run_kitten('show_error', args=['--title', title], input_data=json.dumps({'msg': msg, 'tb': tb})) @ac('mk', 'Create a new marker') def create_marker(self) -> None: