An easy-to-use TUI crate for Rust, based off of the Elm architecture.

Related tags

Command-line rustea
Overview

Rustea

An easy-to-use TUI crate for Rust, based off of the Elm architecture. This is a re-implementation of Go's Tea, created by TJ Holowaychuk.

Features

  • Minimal and easy to use API.
  • Growing collection of view helpers.
  • Automatically multithreaded command processing.
  • Cross-platform, thanks to crossterm.
  • The praised Elm architecture.
Screen.Recording.2022-04-18.at.11.52.33.AM.mov

Installation and Docs

Install by putting rustea = "0.1.5" in your Cargo.toml dependencies.

Docs can be found on docs.rs.

Quickstart

An example demonstrating a website length checker, with batched asynchronous commands.

use rustea::{
    command,
    crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
    view_helper::input::Input,
    App, Command, Message,
};

struct Model {
    url_input: Input,
    website_lengths: Vec<usize>,
}

impl App for Model {
    fn update(&mut self, msg: Message) -> Option<Command> {
        if let Some(key_event) = msg.downcast_ref::<KeyEvent>() {
            if let KeyModifiers::CONTROL = key_event.modifiers {
                if let KeyCode::Char('c') = key_event.code {
                    return Some(Box::new(command::quit));
                }
            }

            match key_event.code {
                KeyCode::Enter => {
                    let url = self.url_input.buffer();
                    self.url_input.clear();

                    // make 3 requests to demonstrate command batching
                    let commands = vec![
                        make_request_command(url.clone()),
                        make_request_command(url.clone()),
                        make_request_command(url),
                    ];
                    return Some(command::batch(commands));
                }
                _ => self.url_input.on_key_event(*key_event),
            }
        } else if let Some(len) = msg.downcast_ref::<WebsiteLengthMessage>() {
            self.website_lengths.push(len.0);
        }

        None
    }

    fn view(&self) -> String {
        let mut out = format!(
            "Website URL (press enter when done): {}",
            self.url_input.buffer()
        );
        for (i, len) in self.website_lengths.iter().enumerate() {
            out.push_str(&format!("\nHit {} length: {}", i, len));
        }

        out
    }
}

struct WebsiteLengthMessage(usize);

fn make_request_command(url: String) -> Command {
    Box::new(move || {
        // It's okay to block since commands are multi threaded
        let website_len = reqwest::blocking::get(url).unwrap().bytes().unwrap().len();
        Some(Box::new(WebsiteLengthMessage(website_len)))
    })
}

fn main() {
    rustea::run(Model {
        url_input: Input::new(),
        website_lengths: Vec::new(),
    })
    .unwrap();
}

More Examples

For more examples, see the examples directory.

You might also like...
Demo Rust Cursive crate for terminal user interface (TUI)

Demo Rust Cursive Demonstration of the Rust programming language and Cursvie crate for terminal user interface (TUI). Setup Create: cargo new demo Add

A simple, fast, and easy to use Solidity test generator based on the Branching Tree Technique.

bulloak A simple, fast, and easy to use Solidity test generator based on the Branching Tree Technique. Installing cargo install bulloak Usage Basic Us

TUI for crate management like lazydocker and lazynpm
TUI for crate management like lazydocker and lazynpm

TUI for crate management like lazydocker and lazynpm. Shouldve named it as lazycargo but lazycrates sounded good at that time.

A Rust-based shell script to create a folder structure to use for a single class every semester. Mostly an excuse to use Rust.

A Rust Course Folder Shell Script PROJECT IN PROGRESS (Spring 2022) When completed, script will create a folder structure of the following schema: [ro

Write Cross-platform application with React-like decralative UI framework and scalable ECS architecture all in Rust.

bevy_dioxus Dioxus Plugin for Bevy Write Cross-platform application with React-like decralative UI framework and scalable ECS architecture all in Rust

The first web framework in Rust to adopt the Model-View-Controller (MVC) architecture

Integra Web Framework Integra is a sleek, performant web framework for Rust, harnessing the power of the hyper library. Will become the first highly p

Another TUI based system monitor, this time in Rust!
Another TUI based system monitor, this time in Rust!

Another TUI based system monitor, this time in Rust!

Multi-Architecture Code Emission Library

macel Multi-Architecture Code Emission Library (macel) is a library which implements a low-level intermediate representation meant to expose on machin

Determine which CPU architecture is used in a binary file.

cpu_rec_rs Determine which CPU architecture is used in a binary file. Example: $ cpu_rec_rs /bin/bash /usr/lib/firmware/rtlwifi/rtl8821aefw* Loading c

Comments
  • Use a Result type instead of so many unwraps + contributor wishlist/todolist?

    Use a Result type instead of so many unwraps + contributor wishlist/todolist?

    I know this is a pretty new library, but you may want to consider implementing a library-wide Result/Error type for unexpected circumstances instead of using so many unwrap calls. Even the demo from the readme closes with a panic when Ctrl+C is pressed instead of quitting gracefully.

    Also, I'd be happy to help with this or anything that is within the realm of my meager rust skill set. Maybe you could put together a "todo-list" or "wish-list" of sorts, for anything that you would be open to contribution on?

    opened by tonyb983 5
  • Clearing the screen on exit

    Clearing the screen on exit

    Is there any way to clear the terminal on exit?

    Larger TUI apps usually clear the terminal both when starting up and shutting down. I was able to do the former, but can't figure out the latter.

    I've tried a couple of things, but it seems this isn't really possible (at least in a straight forward way) because under the hood two threads are involved and the clearing code needs to be executed last. Here are my attempts:

    fn make_on_exit1() -> Command {
        Box::new(|| {
            queue!(io::stdout(), Clear(All), MoveTo(0, 0)).unwrap();
            // A hacky way to get QuitMessage
            command::quit()
        })
    }
    
    fn make_on_exit2() -> Command {
        command::batch(vec![
            Box::new(|| {
                queue!(io::stdout(), Clear(All), MoveTo(0, 0)).unwrap();
                None
            }),
            Box::new(command::quit),
        ])
    }
    

    And here is a gist with the full example: https://gist.github.com/NoneTheWisr/e0f409aa4d53d102a10ff76d66e34ae2

    opened by NoneTheWisr 1
  • Extend `view_helpers`

    Extend `view_helpers`

    Right now, view_helpers only contains a single helper. There are a lot more useful helpers that can be included and should be, as well as some potential examples.

    opened by lazops 0
Owner
Laz
Full stack @1Password.
Laz
TimeKnight is a neat little TUI-based timer app I use in conjunction with a task tracker

TimeKnight is a neat little TUI-based timer app I use in conjunction with a task tracker. It's kind of a secret sauce for productivity (particularly if you have ADHD or have a ridiculously overactive brain).

Monomadic 1 Feb 8, 2022
Shell scripting that will knock your socks off

atom Shell scripting that will knock your socks off. NOTE: Click the image above for a video demonstration.

adam mcdaniel 256 Dec 14, 2022
CLI program for sending one-off requests to the VTube Studio API

vtubestudio-cli (vts) CLI program for sending one-off requests to the VTube Studio API. It connects to the websocket, authenticates, performs one or t

null 2 Nov 24, 2021
Minimal server (with maximal security) for turning off an X10-controlled fan over HTTP

"Fan Remote" A self-contained Rust binary to expose a single X10 command (turn off that fan) as an HTML form button. In its current form, it's highly

Stephan Sokolow 2 Oct 23, 2022
Following "ZK HACK III - Building On-chain Apps Off-chain Using RISC Zero"

RISC Zero Rust Starter Template Welcome to the RISC Zero Rust Starter Template! This template is intended to give you a starting point for building a

drCathieSo.eth 3 Dec 22, 2022
🎨✨ Show off your soothing color palette

?? Show off your soothing color palette ✨ Palettes · install · contribute · Gratitute ?? Palettes Rust C Lua Ruby Go sh js ?? install Installing this

BinaryBrainiacs 4 Jan 28, 2023
oneoff is a library for one-off types

OneOff OneOff is a library for one-off types use oneoff::OneOff; let left = OneOff::Left(1); let right = OneOff::Right(2); assert_eq!(left, OneOff:

null 3 Nov 15, 2024
Rustato: A powerful, thread-safe global state management library for Rust applications, offering type-safe, reactive state handling with an easy-to-use macro-based API.

Rustato State Manager A generical thread-safe global state manager for Rust Introduction • Features • Installation • Usage • Advanced Usage • Api Refe

BiteCraft 8 Sep 16, 2024
Api testing tool made with rust to use for api developement (Kind of Tui)

Api testing tool made with rust to use for api developement (Kind of Tui) This Rust project provides a simple yet powerful tool for making HTTP reques

Kythonlk 3 Feb 14, 2024
A tui to test regexes on the rust regex crate

regex-tui Structure src/ ├── app.rs -> holds the states and renders the widgets ├── event.rs -> handles the terminal events (key press, mouse cl

null 1 Oct 21, 2021