diff --git a/crates/repl/src/outputs.rs b/crates/repl/src/outputs.rs index 5865afb10ef9013eaa9bc5d964b16ee944a78c3f..3796d30ec19e838a27a33d2050d586921a0a2b20 100644 --- a/crates/repl/src/outputs.rs +++ b/crates/repl/src/outputs.rs @@ -1,3 +1,39 @@ +//! # REPL Output Module +//! +//! This module provides the core functionality for handling and displaying +//! various types of output from Jupyter kernels. +//! +//! ## Key Components +//! +//! - `Output`: Represents a single output item, which can be of various types. +//! - `OutputContent`: An enum that encapsulates different types of output content. +//! - `ExecutionView`: Manages the display of outputs for a single execution. +//! - `ExecutionStatus`: Represents the current status of an execution. +//! +//! ## Output Types +//! +//! The module supports several output types, including: +//! - Plain text +//! - Markdown +//! - Images (PNG and JPEG) +//! - Tables +//! - Error messages +//! +//! ## Clipboard Support +//! +//! Most output types implement the `SupportsClipboard` trait, allowing +//! users to easily copy output content to the system clipboard. +//! +//! ## Rendering +//! +//! The module provides rendering capabilities for each output type, +//! ensuring proper display within the REPL interface. +//! +//! ## Jupyter Integration +//! +//! This module is designed to work with Jupyter message protocols, +//! interpreting and displaying various types of Jupyter output. + use std::time::Duration; use gpui::{ diff --git a/crates/repl/src/outputs/plain.rs b/crates/repl/src/outputs/plain.rs index ebedda6757b9a9833bca058d93c6bfdc5f2f1ed3..713eca8a603df16d7434865fcd2478239d39fb6d 100644 --- a/crates/repl/src/outputs/plain.rs +++ b/crates/repl/src/outputs/plain.rs @@ -1,3 +1,20 @@ +//! # Plain Text Output +//! +//! This module provides functionality for rendering plain text output in a terminal-like format. +//! It uses the Alacritty terminal emulator backend to process and display text, supporting +//! ANSI escape sequences for formatting, colors, and other terminal features. +//! +//! The main component of this module is the `TerminalOutput` struct, which handles the parsing +//! and rendering of text input, simulating a basic terminal environment within REPL output. +//! +//! This module is used for displaying: +//! +//! - Standard output (stdout) +//! - Standard error (stderr) +//! - Plain text content +//! - Error tracebacks +//! + use alacritty_terminal::{grid::Dimensions as _, term::Config, vte::ansi::Processor}; use gpui::{canvas, size, AnyElement, ClipboardItem, FontStyle, TextStyle, WhiteSpace}; use settings::Settings as _; @@ -9,22 +26,30 @@ use ui::{prelude::*, IntoElement}; use crate::outputs::SupportsClipboard; -/// Implements the most basic of terminal output for use by Jupyter outputs -/// whether: +/// The `TerminalOutput` struct handles the parsing and rendering of text input, +/// simulating a basic terminal environment within REPL output. +/// +/// `TerminalOutput` is designed to handle various types of text-based output, including: +/// +/// * stdout (standard output) +/// * stderr (standard error) +/// * text/plain content +/// * error tracebacks /// -/// * stdout -/// * stderr -/// * text/plain -/// * traceback from an error output +/// It uses the Alacritty terminal emulator backend to process and render text, +/// supporting ANSI escape sequences for text formatting and colors. /// pub struct TerminalOutput { + /// ANSI escape sequence processor for parsing input text. parser: Processor, + /// Alacritty terminal instance that manages the terminal state and content. handler: alacritty_terminal::Term, } const DEFAULT_NUM_LINES: usize = 32; const DEFAULT_NUM_COLUMNS: usize = 128; +/// Returns the default text style for the terminal output. pub fn text_style(cx: &mut WindowContext) -> TextStyle { let settings = ThemeSettings::get_global(cx).clone(); @@ -56,6 +81,7 @@ pub fn text_style(cx: &mut WindowContext) -> TextStyle { text_style } +/// Returns the default terminal size for the terminal output. pub fn terminal_size(cx: &mut WindowContext) -> terminal::TerminalSize { let text_style = text_style(cx); let text_system = cx.text_system(); @@ -85,6 +111,11 @@ pub fn terminal_size(cx: &mut WindowContext) -> terminal::TerminalSize { } impl TerminalOutput { + /// Creates a new `TerminalOutput` instance. + /// + /// This method initializes a new terminal emulator with default configuration + /// and sets up the necessary components for handling terminal events and rendering. + /// pub fn new(cx: &mut WindowContext) -> Self { let (events_tx, events_rx) = futures::channel::mpsc::unbounded(); let term = alacritty_terminal::Term::new( @@ -100,12 +131,50 @@ impl TerminalOutput { } } + /// Creates a new `TerminalOutput` instance with initial content. + /// + /// Initializes a new terminal output and populates it with the provided text. + /// + /// # Arguments + /// + /// * `text` - A string slice containing the initial text for the terminal output. + /// * `cx` - A mutable reference to the `WindowContext` for initialization. + /// + /// # Returns + /// + /// A new instance of `TerminalOutput` containing the provided text. pub fn from(text: &str, cx: &mut WindowContext) -> Self { let mut output = Self::new(cx); output.append_text(text); output } + /// Appends text to the terminal output. + /// + /// Processes each byte of the input text, handling newline characters specially + /// to ensure proper cursor movement. Uses the ANSI parser to process the input + /// and update the terminal state. + /// + /// As an example, if the user runs the following Python code in this REPL: + /// + /// ```python + /// import time + /// print("Hello,", end="") + /// time.sleep(1) + /// print(" world!") + /// ``` + /// + /// Then append_text will be called twice, with the following arguments: + /// + /// ```rust + /// terminal_output.append_text("Hello,") + /// terminal_output.append_text(" world!") + /// ``` + /// Resulting in a single output of "Hello, world!". + /// + /// # Arguments + /// + /// * `text` - A string slice containing the text to be appended. pub fn append_text(&mut self, text: &str) { for byte in text.as_bytes() { if *byte == b'\n' { @@ -120,6 +189,11 @@ impl TerminalOutput { } } + /// Renders the terminal output as a GPUI element. + /// + /// Converts the current terminal state into a renderable GPUI element. It handles + /// the layout of the terminal grid, calculates the dimensions of the output, and + /// creates a canvas element that paints the terminal cells and background rectangles. pub fn render(&self, cx: &mut WindowContext) -> AnyElement { let text_style = text_style(cx); let text_system = cx.text_system();