diff --git a/euporie/cell.py b/euporie/cell.py index 2b550aa2..000851da 100644 --- a/euporie/cell.py +++ b/euporie/cell.py @@ -387,7 +387,19 @@ def ran(self, msg): self.nb.kernel_status = self.state elif msg_type == "execute_input": - self.json["execution_count"] = msg.get("content", {}).get("execution_count") + self.execution_count = msg.get("content", {}).get("execution_count") + + elif msg_type == "stream": + name = msg.get("content", {}).get("name") + outputs = { + output.get("name"): output + for output in self.json["outputs"] + if output.get("name") + } + if name in outputs: + outputs[name].text += msg.get("content", {}).get("text", "") + else: + self.json["outputs"].append(nbformat.v4.output_from_msg(msg)) elif msg_type in ("stream", "error", "display_data", "execute_result"): self.json["outputs"].append(nbformat.v4.output_from_msg(msg)) diff --git a/euporie/output.py b/euporie/output.py index 16ec12f9..c3658460 100644 --- a/euporie/output.py +++ b/euporie/output.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- from pathlib import PurePath -from prompt_toolkit.layout import Container, Window +from prompt_toolkit.layout import Container, Window, to_container from prompt_toolkit.layout.controls import FormattedTextControl -from prompt_toolkit.widgets import Label, TextArea +from prompt_toolkit.widgets import Label from rich.markdown import Markdown -from euporie import mdtable # noqa F401 from euporie.config import config from euporie.control import HTMLControl, ImageControl, RichControl, SVGControl from euporie.text import ANSI @@ -85,9 +84,8 @@ def __init__(self, index, json, parent=None): break if mime_path.match("text/stderr"): - self.content = TextArea( - datum.rstrip(), wrap_lines=True, style="bg:darkred" - ) + control = FormattedTextControl(ANSI(datum.rstrip())) + self.content = Window(control, wrap_lines=True, style="fg:red") break if mime_path.match("text/*"): @@ -98,7 +96,7 @@ def __init__(self, index, json, parent=None): else: datum = sorted(self.data.items(), key=bling)[-1][1] - self.content = Label(ANSI(str(datum).rstrip())) + self.content = Label(str(datum).rstrip()) @property def data(self): @@ -115,22 +113,22 @@ def metadata(self): return self.json.get("metadata", {}) def get_key_bindings(self, *args, **kwargs): - return self.content.get_key_bindings(*args, **kwargs) + return to_container(self.content).get_key_bindings(*args, **kwargs) def get_children(self, *args, **kwargs): - return self.content.get_children(*args, **kwargs) + return to_container(self.content).get_children(*args, **kwargs) def preferred_width(self, *args, **kwargs): - return self.content.preferred_width(*args, **kwargs) + return to_container(self.content).preferred_width(*args, **kwargs) def preferred_height(self, *args, **kwargs): - return self.content.preferred_height(*args, **kwargs) + return to_container(self.content).preferred_height(*args, **kwargs) def write_to_screen(self, *args, **kwargs): - return self.content.write_to_screen(*args, **kwargs) + return to_container(self.content).write_to_screen(*args, **kwargs) def reset(self, *args, **kwargs): - return self.content.reset(*args, **kwargs) + return to_container(self.content).reset(*args, **kwargs) def __pt_container__(self) -> Container: - return self.content + return to_container(self.content) diff --git a/euporie/text.py b/euporie/text.py index 9709d35d..7c42f5d0 100644 --- a/euporie/text.py +++ b/euporie/text.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +import re from typing import Generator from prompt_toolkit.formatted_text import ANSI as PTANSI @@ -37,6 +38,13 @@ class ANSI(PTANSI): Converts ANSI text into formatted text, preserving all control sequences. """ + def __init__(self, value: str) -> None: + + # Remove anything before a carriage return + value = re.sub("^.*\\r", "", value) + + super().__init__(value) + def _parse_corot(self) -> Generator[None, str, None]: """ Coroutine that parses the ANSI escape sequences.