GPUI Box GitHub

Components / content

Terminal builder

A terminal grid.

A builder is RenderOnce. Construct and mount it in one expression.

use gpui_kit::content::Terminal;

Reviewed in terminal.

Construct
new(ident: impl Into<Ident>) -> Self
Options

Chain onto the value.

state(state: TerminalState) -> Self
grid(grid: impl Fn(GridGeometry, &mut App) -> Option<GridSnapshot> + 'static) -> Self
focused(focused: bool) -> Self
scrollback(scrollback: bool) -> Self
on_event(handler: impl Fn(TerminalEvent, &mut Window, &mut App) + 'static) -> Self
Reports

The variants of the event it emits. It never applies the change itself.

  • SelectionStarted
  • SelectionUpdated
  • SelectionCleared
  • Scrolled
Example · terminal
fn terminal(_window: &mut Window, cx: &mut App) -> AnyElement {
    /// A session's worth of output, chosen so every branch of the painter has
    /// something to paint.
    const SESSION: &[u8] = concat!(
        "\x1b[32m>\x1b[0m cargo run -p xtask -- gate\r\n",
        "\x1b[1mCompiling\x1b[0m gpui-box-kit v0.1.2\r\n",
        "\x1b[2m    dim text stays legible and stays dim\x1b[0m\r\n",
        "\x1b[4munderlined\x1b[0m \x1b[7minverse\x1b[0m \x1b[44;97m on a background \x1b[0m\r\n",
        "\x1b[30m0\x1b[31m1\x1b[32m2\x1b[33m3\x1b[34m4\x1b[35m5\x1b[36m6\x1b[37m7",
        "\x1b[90m8\x1b[91m9\x1b[92ma\x1b[93mb\x1b[94mc\x1b[95md\x1b[96me\x1b[97mf\x1b[0m\r\n",
        "\x1b[38;5;208m256-colour cube\x1b[0m and \x1b[38;2;120;200;255mtruecolour\x1b[0m\r\n",
        "\x1b[32m>\x1b[0m ",
    )
    .as_bytes();

    let theme = cx.theme().clone();
    let panel = |ident: &'static str, state: TerminalState| {
        div()
            .w(px(400.0))
            .h(px(180.0))
            .child(Terminal::new(ident).state(state))
    };

    stack(&theme)
        .child(
            div().w(px(400.0)).h(px(180.0)).child(
                Terminal::new("scene.terminal.ready")
                    .focused(true)
                    .grid(|geometry, _| {
                        let mut emulator = Emulator::new(geometry.cols, geometry.rows);
                        emulator.feed(SESSION);
                        // A selection over the middle of a coloured row, so the
                        // achromatic wash is reviewable against sixteen hues at
                        // once rather than against one.
                        emulator.start_selection(
                            SelectionKind::Drag,
                            emulator.grid_point(4, 0),
                            CellSide::Left,
                        );
                        emulator.update_selection(emulator.grid_point(4, 15), CellSide::Right);
                        Some(GridSnapshot {
                            lines: emulator.lines(),
                            cursor: emulator.cursor(),
                        })
                    })
                    .on_event(|_, _, _| {}),
            ),
        )
        .child(
            row(&theme)
                .items_start()
                .child(panel("scene.terminal.starting", TerminalState::Loading))
                .child(panel(
                    "scene.terminal.unavailable",
                    TerminalState::Unavailable("No shell is configured for this workspace.".into()),
                )),
        )
        .child(
            div().w(px(400.0)).h(px(180.0)).child(
                Terminal::new("scene.terminal.ended")
                    .state(TerminalState::Error("The process exited with status 130.".into()))
                    .grid(|geometry, _| {
                        let mut emulator = Emulator::new(geometry.cols, geometry.rows);
                        emulator.feed(b"\x1b[32m>\x1b[0m tail -f build.log\r\n\x1b[31merror\x1b[0m: interrupted\r\n");
                        Some(GridSnapshot {
                            lines: emulator.lines(),
                            // Nothing is reading this grid any more, so there
                            // is no insertion point in it: a caret drawn under
                            // an exited process invites a keystroke that has
                            // nowhere to go.
                            cursor: None,
                        })
                    }),
            ),
        )
        .into_any_element()
}

Source: crates/gpui-kit/src/content/terminal/view.rs