Ratzilla

repository·main·Indexed 23 days ago

https://github.com/ratatui/ratzilla

A framework for building terminal-themed web applications using Ratatui and WebAssembly. It provides multiple rendering backends, including CanvasBackend for HTML canvas, DomBackend for rendering cells as <span> elements, and a high-performance WebGl2Backend. Ratzilla includes tools for handling mouse and key events in the browser, managing cursor shapes, and scaffolding new projects via cargo-generate templates.

Tokens
5.8K
Snippets
12
Records
41
Agent score
80%

What's inside ratzilla

  1. Create a new Ratzilla project using cargo-generate

    main

    You can bootstrap a new Ratzilla project using the cargo-generate tool. The templates directory provides project skeletons that can be used as sources for cargo-generate.

    The available template is:

    • Simple: A minimal Ratzilla project template designed for getting started quickly.
  2. Use the ratzilla public API modules

    main

    The ratzilla crate provides a set of modules for building terminal-like interfaces in web environments. The primary modules available for use are:

    • error: Custom error types for the library.
    • event: Event and input handling logic.
    • utils: Web utility functions.
    • widgets: UI components (widgets).
    • backend: Backend implementations for rendering.
    • ratatui: Re-exports the ratatui crate for direct access to its types and traits.
    • web_sys: Re-exports web_sys for web-specific API access.
  3. Configure FontAtlasConfig for WebGl2Backend

    main

    The FontAtlasConfig enum determines how glyphs are rendered in the WebGL2 backend. It supports two modes:

    1. Static(FontAtlasData): Uses pre-generated font atlas data. This is highly performant but limited to the characters included in the atlas. Static atlases are typically generated using the beamterm-atlas CLI tool.
    2. Dynamic(Vec<String>, f32): Rasterizes glyphs on demand. This provides full Unicode and emoji support by using browser fonts. The Vec<String> contains font family names (matching CSS font-family values) and the f32 specifies the font size.

    You can create a dynamic configuration using the FontAtlasConfig::dynamic(font_families, font_size) helper method.

  4. Measure WebGL2 Rendering Performance

    main

    You can profile the performance of the WebGL2 backend using the browser's native Performance API.

    1. Enable profiling in your options: .measure_performance(true).
    2. Open Browser Developer Tools (F12) and go to the Performance tab.
    3. Record a session and look for the User Timing section.

    The backend emits two specific marks:

    • sync-terminal-buffer: The time taken to synchronize Ratatui's cell data with the renderer.
    • webgl-render: The time taken to flush GPU buffers and execute the WebGL draw call.

    You can also query these measurements directly from the browser console using performance.getEntriesByName('webgl-render').

  5. Handle Hyperlinks in WebGl2Backend

    main

    The WebGl2Backend supports interactive hyperlinks within the terminal grid.

    To enable them, use .enable_hyperlinks() on your WebGl2BackendOptions. This sets up a default handler that opens the URL in a new browser tab using window.open(url, '_blank').

    If you need custom behavior (e.g., logging the URL or handling it within your application logic), use .on_hyperlink_click(callback) instead. The callback receives the URL as a &str.

  6. Configure DomBackendOptions

    main

    Use DomBackendOptions to customize how the DomBackend interacts with the DOM.

    • grid_id: An Option<String> representing the ID of the element where the grid will be rendered.
      • If None, it defaults to "grid".
      • If provided (e.g., "my-id"), the actual rendered element ID will be suffixed with "_ratzilla_grid" (e.g., "my-id_ratzilla_grid").
    • cursor_shape: A CursorShape defining how the cursor is rendered in the DOM.
  7. Configure CanvasBackendOptions

    main

    Use CanvasBackendOptions to customize how the canvas is created and rendered.

    • grid_id(id: &str): Sets the ID of the HTML element that will act as the parent of the canvas. If not set, the <body> is used.
    • size((u32, u32)): Overrides the automatically detected size of the canvas in pixels.
    • always_clip_cells: A boolean flag (default false). When true, it forces foreground drawing to be clipped to the cell rectangle. This is useful for preventing out-of-bounds rendering caused by problematic fonts, but may impact performance when many cells change simultaneously.
  8. Example: Setting up a web-based terminal with mouse events

    main

    This example demonstrates how to initialize a Terminal with a CanvasBackend and attach a mouse event listener that uses grid coordinates.

    # fn main() -> Result<(), Box<dyn std::error::Error>> {
    use ratzilla::{CanvasBackend, WebRenderer};
    use ratatui::Terminal;
    
    let mut terminal = Terminal::new(CanvasBackend::new()?)?;
    
    // Set up mouse events with grid coordinate translation
    terminal.on_mouse_event(|event| {
        // event.col and event.row are terminal grid coordinates
        println!("Mouse at ({}, {})", event.col, event.row);
    })?;
    # Ok(())
    // }
  9. Configure the WebGl2Backend with WebGl2BackendOptions

    main

    The WebGl2Backend is a high-performance terminal renderer for web environments using WebGL2. You can customize its behavior using WebGl2BackendOptions via a builder pattern.

    Key configuration capabilities include:

    • Canvas Sizing: Set a specific pixel size with .size((u32, u32)) or use .disable_auto_css_resize() to let external CSS control the dimensions.
    • Font Atlas: Choose between a Static atlas (pre-generated .atlas files) or a Dynamic atlas (runtime font selection) using .font_atlas_config().
    • Interactivity: Enable mouse text selection with .enable_mouse_selection_with_mode(mode) or configure hyperlink behavior with .on_hyperlink_click(callback).
    • Debugging: Enable the console debug API with .enable_console_debug_api() to access window.__beamterm_debug in the browser.
    use ratzilla::backend::webgl2::{WebGl2BackendOptions, FontAtlasConfig};
    use ratzilla::backend::webgl2::FontAtlasData;
    
    // Static atlas
    let options = WebGl2BackendOptions::new()
        .font_atlas_config(FontAtlasConfig::Static(FontAtlasData::default()));
    
    // Dynamic atlas
    let options = WebGl2BackendOptions::new()
        .font_atlas_config(FontAtlasConfig::dynamic(
            // monospace is an implicit fallback font in browsers
            &["JetBrains Mono"],
            16.0
        ));
  10. Use CursorShape to manage cursor visibility and styling

    main

    The CursorShape enum defines the supported cursor shapes for the backend and provides methods to manipulate ratatui::style::Style to show or hide the cursor based on the selected shape. It also provides CSS attributes for web-based backends.

    Supported Shapes

    • SteadyBlock: A non-blinking block cursor (█).
    • SteadyUnderScore: A non-blinking underscore cursor (_).
    • None: Used to clear the cursor.

    Styling Methods

    • hide(&self, style: Style) -> Style: Returns a modified style that effectively hides the cursor shape (e.g., by removing reversal or underlining).
    • show(&self, style: Style) -> Style: Returns a modified style that shows the cursor shape (e.g., by applying reversal or underlining).
    • get_css_attribute(&self) -> CssAttribute: Returns the corresponding CSS field and value (e.g., text-decoration: underline for SteadyUnderScore).
  11. Configure mouse coordinate transformation with MouseConfig

    main

    To translate raw pixel coordinates from web mouse events into terminal grid coordinates (columns and rows), use the MouseConfig struct. This is necessary when your terminal UI is rendered on a web canvas or element where pixel positions do not map 1:1 to character cells.

    MouseConfig uses a builder pattern to configure:

    • grid_width and grid_height: The dimensions of your terminal grid in characters.
    • offset: An optional pixel offset from the element edge (e.g., to account for padding).
    • cell_dimensions: Optional (width, height) in pixels for each character cell, enabling pixel-perfect calculation.
    let config = MouseConfig::new(80, 24)
        .with_offset(5.0)
        .with_cell_dimensions(10.0, 19.0);