8 releases (5 breaking)

0.6.1 Jan 14, 2024
0.6.0 Jan 14, 2024
0.5.0 Oct 4, 2023
0.4.0 May 30, 2023
0.1.0 Aug 2, 2022

#141 in Command-line interface

34 downloads per month
Used in flashed

LGPL-3.0-or-later

160KB
4K SLoC

Tuviv

Tuviv is a library for building terminal user interfaces (TUIs) with rust with a heavy focus on layout. Tuviv does not come with as many widgets as, say, tui-rs, but rather contains many more widgets based on layout: specifically a Flexbox, and a Grid, along with others.

The purpose of this library is to significantly ease creating layouts, which is mildly clunky with tui-rs: such as the fact that you cannot center text vertically (#396) - but also wider-scale things - such as the lack of a flexbox or a grid.

Features

  • crossterm, termion - different backends. crossterm is enabled by default and is strongly recommended.
  • textwrap - allows for the Paragraph widget. Is enabled by default. (please note if you don't include this you will have to reimplement something to render text)

Examples

Create a Buffer And Render a Widget

// Imports
use std::io;
use std::time::Duration;

use tuviv::{
    le::Orientation,
    prelude::*,
    widgets::{Filler, Flexbox},
};

fn main() -> io::Result<()> {
    // Create a flexbox
    // With coloured squares
    let flexbox = Flexbox::new(Orientation::Horizontal, false)
        .child(
            Filler::new(" ".styled().bg_red())
                .fixed_size(16, 8)
                .centered()
                .to_flex_child()
                .expand(1),
        )
        .child(
            Flexbox::new(Orientation::Vertical, false)
                .child(
                    Filler::new(" ".styled().bg_yellow())
                        .fixed_size(16, 8)
                        .centered()
                        .to_flex_child()
                        .expand(1),
                )
                .child(
                    Filler::new(" ".styled().bg_green())
                        .fixed_size(16, 8)
                        .centered()
                        .to_flex_child()
                        .expand(1),
                )
                .to_flex_child()
                .expand(1),
        );
    
    // Render a single frame.
    //
    // Look at `tuviv::run_app` for a better way of doing this
    // for real applications
    tuviv::render_frame(&*flexbox, Duration::from_secs(2))?;

    Ok(())
}

Create More Complicated Widget Trees

Tuviv uses a builder pattern so complicated widgets can be created easily:

use tuviv::prelude::*;

// Create a grid with progressbars:
//
// ╭───────────────╮
// │CPU  █▌────────│
// │MEM  ███▌──────│
// │GPU  ─────CO o │
// ╰───────────────╯
let grid = Grid::new()
    .template_rows(vec![Sizing::Auto; 3])
    .template_columns(vec![Sizing::Auto, Sizing::AutoFixed(10)])
    .column_gap(2)
    .auto_child(Paragraph::new("CPU".styled()))
    .auto_child(
        ProgressBar::new()
            .total(100.0)
            .value(10.0)
            .align_y(Alignment::Center),
    )
    .auto_child(Paragraph::new("MEM".styled()))
    .auto_child(
        ProgressBar::new()
            .total(8.0)
            .value(2.4)
            .align_y(Alignment::Center),
    )
    .auto_child(Paragraph::new("GPU".styled()))
    .auto_child(
        ProgressBar::new()
            .total(15.0)
            .value(8.0)
            .fg(vec!["".styled().bold()])
            .edge("C".styled().yellow().bold())
            .bg(vec!["O o ".styled()])
            .align_y(Alignment::Center),
    )
    .to_box_sizing()
    .border(Border::ROUNDED)
    .centered();

Dependencies

~1–11MB
~47K SLoC