tastty-core 0.1.0

Sans-IO core of the tastty terminal session library: VT parser, screen buffer, and byte encoders.
docs.rs failed to build tastty-core-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

tastty

A batteries-included toolkit for terminal parsing, session management, and automation for the Rust language.

  • Parsing: VT parsing into a live screen buffer, with input encoders and host replies.
  • Sessions: run a program in a managed PTY, answering host queries, with input handling. Embeddable in a ratatui app as a widget.
  • Automation: spawn, send input, wait on conditions, snapshot, assert on screen state.

tastty-core tastty tastty-driver ratatui support Matrix MIT licensed

Example

Embed a live terminal in a ratatui app by spawning a program and rendering it as a widget:

cargo add tastty
use std::time::Duration;
use crossterm::event::{self, Event, KeyCode, KeyModifiers};
use tastty::widget::PseudoTerminal;
use tastty::{Builder, Terminal, TerminalSize};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut tui = ratatui::init();
    let size = tui.size()?;

    let term = Terminal::spawn(
        Builder::command("bash").size(TerminalSize { rows: size.height, cols: size.width }),
    )?;

    while !term.is_finished() {
        if term.take_redraw() {
            tui.draw(|f| term.with_screen(|s| f.render_widget(PseudoTerminal::new(s), f.area())))?;
        }
        // Forward keystrokes to the child; Ctrl+Q quits.
        if event::poll(Duration::from_millis(16))? {
            if let Event::Key(key) = event::read()? {
                if key.code == KeyCode::Char('q') && key.modifiers.contains(KeyModifiers::CONTROL) {
                    break;
                }
                let _ = term.send_key(key);
            }
        }
    }

    ratatui::restore();
    Ok(())
}

Drive an interactive program headless and assert on its screen:

cargo add tastty-driver
use std::time::Duration;
use tastty_driver::{Builder, InputSegment, Session, WaitCondition};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let session = Session::spawn(Builder::command("bash"))?;
    session.send_input(&[InputSegment::Text("echo hello\n".into())])?;
    let outcome = session.wait(
        WaitCondition::regex("hello"),
        Duration::from_secs(5),
    )?;
    println!("{}", outcome.snapshot.text());
    Ok(())
}

Check out the per-crate examples/ directories, for more information, or run an example:

cargo run -p tastty --example bordered

Crates

Contributing

We welcome contributions from the community! Check out the Contributing Guidelines on how to get started.

Status

[!NOTE] This project is still in active development and should be considered a work in progress. We value feedback on the API and usability greatly.

License

tastty is available under the MIT license. See LICENSE for more information.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in tastty by you shall be licensed as MIT, without any additional terms or conditions.