Skip to content

A Rust crate for beautiful, artisanally crafted CLIs, TUIs, and text-based IO.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

ccbrown/iocraft

Repository files navigation

iocraft

✨ A Rust crate for beautiful, artisanally crafted CLIs, TUIs, and text-based IO. ✨

GitHub Actions Workflow Status docs.rs crates.io Codecov

iocraft is a library for crafting beautiful text output and interfaces for the terminal or logs. It allows you to easily build complex layouts and interactive elements using a declarative API.

Features

  • Define your UI using a clean, highly readable syntax.
  • Organize your UI using flexbox layouts powered by taffy.
  • Output colored and styled UIs to the terminal or ASCII output anywhere else.
  • Create animated or interactive elements with event handling and hooks.
  • Build fullscreen terminal applications with ease.
  • Pass props and context by reference to avoid unnecessary cloning.
  • Broad support for both Unix and Windows terminals so your UIs look great everywhere.

Getting Started

If you're familiar with React, you'll feel right at home with iocraft. It uses all the same concepts, but is text-focused and made for Rust.

Here's your first iocraft program:

use iocraft::prelude::*;

fn main() {
    element! {
        Box(
            border_style: BorderStyle::Round,
            border_color: Color::Blue,
        ) {
            Text(content: "Hello, world!")
        }
    }
    .print();
}

Your UI is composed primarily via the element! macro, which allows you to declare your UI elements in a React/SwiftUI-like syntax.

iocraft provides a few built-in components, such as Box, Text, and TextInput, but you can also create your own using the #[component] macro.

For example, here's a custom component that uses a hook to display a counter which increments every 100ms:

use iocraft::prelude::*;
use std::time::Duration;

#[component]
fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
    let mut count = hooks.use_state(|| 0);

    hooks.use_future(async move {
        loop {
            smol::Timer::after(Duration::from_millis(100)).await;
            count += 1;
        }
    });

    element! {
        Text(color: Color::Blue, content: format!("counter: {}", count))
    }
}

fn main() {
    smol::block_on(element!(Counter).render_loop()).unwrap();
}

More Examples

There are many examples on GitHub which demonstrate various concepts such as tables, progress bars, fullscreen apps, forms, and more!

Shoutouts

iocraft was inspired by Dioxus and Ink, which you should also check out, especially if you're building graphical interfaces or interested in using JavaScript/TypeScript.

You may also want to check out Ratatui, which serves a similar purpose with a less declarative API.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.