tastty-core 0.1.0

Sans-IO core of the tastty terminal session library: VT parser, screen buffer, and byte encoders.
# 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][core-badge]][core-crates]
[![tastty][tastty-badge]][tastty-crates]
[![tastty-driver][driver-badge]][driver-crates]
[![ratatui support][ratatui-badge]][ratatui-rs]
[![Matrix][matrix-badge]][matrix-url]
[![MIT licensed][mit-badge]][mit-url]

## Example

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

```sh
cargo add tastty
```

```rust,no_run
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:

```sh
cargo add tastty-driver
```

```rust,no_run
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:

```sh
cargo run -p tastty --example bordered
```

## Crates

- [`tastty-core`][core-docs]: VT parser, screen buffer, and input
  encoders.
- [`tastty`][tastty-docs]: managed PTY sessions, with optional [ratatui]
  widget support via [tui-term].
- [`tastty-driver`][driver-docs]: the automation layer for driving and
  testing terminal programs.

## Contributing

We welcome contributions from the community!
Check out the [Contributing Guidelines](./docs/CONTRIBUTING.md) 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](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.

[core-badge]: https://img.shields.io/crates/v/tastty-core?style=flat-square&label=tastty-core
[core-crates]: https://crates.io/crates/tastty-core
[core-docs]: https://docs.rs/tastty-core
[tastty-badge]: https://img.shields.io/crates/v/tastty?style=flat-square&label=tastty
[tastty-crates]: https://crates.io/crates/tastty
[tastty-docs]: https://docs.rs/tastty
[driver-badge]: https://img.shields.io/crates/v/tastty-driver?style=flat-square&label=tastty-driver
[driver-crates]: https://crates.io/crates/tastty-driver
[driver-docs]: https://docs.rs/tastty-driver
[ratatui-badge]: https://img.shields.io/badge/ratatui-widget-000?style=flat-square&logo=ratatui
[ratatui-rs]: https://ratatui.rs
[matrix-badge]: https://img.shields.io/badge/matrix-%23tastty-0dbd8b?style=flat-square&logo=matrix&logoColor=white
[matrix-url]: https://matrix.to/#/%23tastty:matrix.org
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
[mit-url]: LICENSE
[ratatui]: https://crates.io/crates/ratatui
[tui-term]: https://crates.io/crates/tui-term