tui-rs revival project

Overview

ratatui

An actively maintained tui-rs fork.

Build Status Crate Status Docs Status

Demo cast under Linux Termite with Inconsolata font 12pt

Install

[dependencies]
tui = { package = "ratatui" }

What is this fork?

This fork was created to continue maintenance on the original TUI project. The original maintainer had created an issue explaining how he couldn't find time to continue development, which led to us creating this fork.

With that in mind, we the community look forward to continuing the work started by Florian Dehau. πŸš€

In order to organize ourselves, we currently use a discord server, feel free to join and come chat ! There are also plans to implement a matrix bridge in the near future. Discord is not a MUST to contribute, we follow a pretty standard github centered open source workflow keeping the most important conversations on github, open an issue or PR and it will be addressed. πŸ˜„

Please make sure you read the updated contributing guidelines, especially if you are interested in working on a PR or issue opened in the previous repository.

Introduction

ratatui-rs is a Rust library to build rich terminal user interfaces and dashboards. It is heavily inspired by the Javascript library blessed-contrib and the Go library termui.

The library supports multiple backends:

The library is based on the principle of immediate rendering with intermediate buffers. This means that at each new frame you should build all widgets that are supposed to be part of the UI. While providing a great flexibility for rich and interactive UI, this may introduce overhead for highly dynamic content. So, the implementation try to minimize the number of ansi escapes sequences generated to draw the updated UI. In practice, given the speed of Rust the overhead rather comes from the terminal emulator than the library itself.

Moreover, the library does not provide any input handling nor any event system and you may rely on the previously cited libraries to achieve such features.

Rust version requirements

Since version 0.17.0, ratatui requires rustc version 1.59.0 or greater.

Documentation

The documentation can be found on docs.rs.

Demo

The demo shown in the gif can be run with all available backends.

# crossterm
cargo run --example demo --release -- --tick-rate 200
# termion
cargo run --example demo --no-default-features --features=termion --release -- --tick-rate 200

where tick-rate is the UI refresh rate in ms.

The UI code is in examples/demo/ui.rs while the application state is in examples/demo/app.rs.

If the user interface contains glyphs that are not displayed correctly by your terminal, you may want to run the demo without those symbols:

cargo run --example demo --release -- --tick-rate 200 --enhanced-graphics false

Widgets

Built in

The library comes with the following list of widgets:

Click on each item to see the source of the example. Run the examples with with cargo (e.g. to run the gauge example cargo run --example gauge), and quit by pressing q.

You can run all examples by running cargo make run-examples (require cargo-make that can be installed with cargo install cargo-make).

Third-party libraries, bootstrapping templates and widgets

  • ansi-to-tui β€” Convert ansi colored text to tui::text::Text
  • color-to-tui β€” Parse hex colors to tui::style::Color
  • rust-tui-template β€” A template for bootstrapping a Rust TUI application with Tui-rs & crossterm
  • simple-tui-rs β€” A simple example tui-rs app
  • tui-builder β€” Batteries-included MVC framework for Tui-rs + Crossterm apps
  • tui-clap β€” Use clap-rs together with Tui-rs
  • tui-log β€” Example of how to use logging with Tui-rs
  • tui-logger β€” Logger and Widget for Tui-rs
  • tui-realm β€” Tui-rs framework to build stateful applications with a React/Elm inspired approach
  • tui-realm-treeview β€” Treeview component for Tui-realm
  • tui tree widget β€” Tree Widget for Tui-rs
  • tui-windows β€” Tui-rs abstraction to handle multiple windows and their rendering
  • tui-textarea: Simple yet powerful multi-line text editor widget supporting several key shortcuts, undo/redo, text search, etc.
  • tui-rs-tree-widgets: Widget for tree data structures.
  • tui-input: TUI input library supporting multiple backends and tui-rs.

Apps

Check out the list of close to 40 apps using ratatui!

Alternatives

You might want to checkout Cursive for an alternative solution to build text user interfaces in Rust.

License

MIT

Comments
  • 'bleeding' of style between paragraph and block

    'bleeding' of style between paragraph and block

    TL;DR; Is it correct that:

    • the style of the contained paragraph should set the style of its surrounding block.
    • the style set in the block (via block.style) sets the style for the blank space in the para even if the para has its own style set.

    If I have a paragraph with a block around it then there are 4 combinations of setting styles for the text and box

      para         block
      -------      ------- 
      default     default
      explicit     default  
      default     explicit
      explicit     explicit      
    

    by default I mean Style::default by explicit i mean say Style::default().bg(Color::Red).fg(Color::Yellow)

    I used

    • Style::default().bg(Color::Red).fg(Color::Yellow) for the block in my tests (setting block.border_style)
    • Style::default().bg(Color::Blue).fg(Color::Green) for the paragraph

    In a modified version of the paragraph sample app. (source below)

    My expectation was a follows (for each combo listed above)

    • white text on black everywhere
    • green on blue text in a white on black box
    • white on black text in a yellow on red box
    • green on blue text in a yellow on red box

    What I get is

    image

    I also ran the same code with block.style instead of block.border_style. Nothing in the docs explains the difference between them. So I wanted to see what happened

    image

    This seems to be suggesting that block.style is intended to set the overall style of the para/block combo (para inherits from block), whereas block.border_style only sets the stye of the block. Fine.

    But note that in the second case of both screen shots the para style has overriden the default of the block. This is a surprise

    Also note the odd fact that although the para is explicity set to blue on green in the last case (of the last screen shot) the style set in the block style 'wins' in the 'blank' space

    are these 2 intended behaviors?

    I also tried with styled text rather that styling the paragraph (para always set to Style::default)

    image

    (There are only 2 combos now since the para style is always set to default but the text is set to white on blue)

    Note the big difference for the second one. The style of the text is not propagated to the containing block.

    and for completeness sake , style text with the block style set via block.border_style

    image

    here is the modified code of the paragraph sample

        let size = f.size();
    
        // Words made "loooong" to demonstrate line breaking.
        let s = "Veeeeeeeeeeeeeeeery    loooooooooooooooooong   striiiiiiiiiiiiiiiiiiiiiiiiiing.   ";
        let mut long_line = s.repeat(usize::from(size.width) / s.len() + 4);
        long_line.push('\n');
    
        //   let block = Block::default().style(Style::default()); //.bg(Color::White).fg(Color::Black));
        // f.render_widget(block, size);
    
        let chunks = Layout::default()
            .direction(Direction::Vertical)
            .margin(5)
            .constraints(
                [
                    Constraint::Percentage(25),
                    Constraint::Percentage(25),
                    Constraint::Percentage(25),
                    Constraint::Percentage(25),
                ]
                .as_ref(),
            )
            .split(size);
    
        let text = vec![Spans::from("This is a line ")];
    
        let create_block = |title, dflt| {
            Block::default()
                .borders(Borders::ALL)
                .title(Span::styled(
                    title,
                    Style::default().add_modifier(Modifier::BOLD),
                ))
                .border_style(if dflt {
                    Style::default()
                } else {
                    Style::default().bg(Color::Red).fg(Color::Yellow)
                })
        };
    
        let paragraph = Paragraph::new(text.clone())
            .style(Style::default())
            .block(create_block("dflt dflt", true))
            .alignment(Alignment::Left);
        f.render_widget(paragraph, chunks[0]);
    
        let paragraph = Paragraph::new(text.clone())
            .style(Style::default().bg(Color::Blue).fg(Color::Green))
            .block(create_block("para = Gr/Bl bl = dflt", true))
            .alignment(Alignment::Left);
        f.render_widget(paragraph, chunks[1]);
        let paragraph = Paragraph::new(text.clone())
            .style(Style::default())
            .block(create_block("para = dflt, block = Y/red", false))
            .alignment(Alignment::Left);
        f.render_widget(paragraph, chunks[2]);
        let paragraph = Paragraph::new(text.clone())
            .style(Style::default().bg(Color::Blue).fg(Color::Green))
            .block(create_block("Para = b/g block = y/red ", false))
            .alignment(Alignment::Left);
        f.render_widget(paragraph, chunks[3]);
    }
    

    Environment

    Add a description of the systems where you are observing the issue. For example:

    • OS: Windows
    • Terminal Emulator: windows terminal
    • Font: ?
    • Crate version: 0.20.1 (cloned current head)
    • Backend: crossterm

    Why do I care about ths. Because I am writing a widget that greys out a paragraphs text temporarily. If I do that when the surrounding block is set to Style::default then it gets greyed out too. And there is no way for me to inspect the block to look at its style (there is no get_style method)

    opened by pm100 10
  • feat(terminal)!: add inline viewport

    feat(terminal)!: add inline viewport

    originally taken from https://github.com/fdehau/tui-rs/pull/552.

    Updates Viewport type, making it an enum with Fullscreen, Inline and Fixed views. Inline(_) includes the height of the inline screen.

    Adds an insert_before method that can write permanent lines above the inline tui. Intended usecase is like yarn install, where there would be multiple updating elements at the bottom of the screen, and then 'xxx installed' would be permanent logs above the updating elements.

    I've tried to minimise the breaking changes from the original PR, but there's still a breaking change in the Backend trait. In theory I can add some default methods to make it not a breaking change

    (CC @pdecat, https://github.com/ellie/atuin/pull/648)

    opened by conradludgate 6
  • fix(widget)!: List should not ignore empty string items

    fix(widget)!: List should not ignore empty string items

    Upstream: #688

    Description

    Fixes issue #680. Handles the case where a list item is created with an empty string, which is not split by the lines iterator.

    Testing guidelines

    New test can be ran with cargo test

    Checklist

    • [x] I have read the contributing guidelines.
    • [x] I have added relevant tests.
    • [x] I have documented all new additions.
    bug 
    opened by orhun 6
  • feat(block): support placing the title on bottom

    feat(block): support placing the title on bottom

    Upstream: #669

    Description

    Before you could only put the title on the top row of a block. Now you can put it on the bottom row! Revolutionary.

    In the future, implementing an option for both a bottom and top title is possible, but seems unnecessary considering you could just manually have a Layout and do the work yourself at that point, and having support for title wizardry seems pointless. The farthest you could go is having an option to actually move the title everywhere; it's an easy extension and seems like something that would normally be built-in. Hence here it is; you can do top and bottom, left right and center.

    Testing guidelines

    When creating a Block with, say, Block::default().title(), slap on a .title_on_bottom(). Check tests/widget_block.rs for the tests, which are just a copy of the alignment tests.

    Checklist

    • [x] I have read the contributing guidelines.
    • [x] I have added relevant tests.
    • [x] I have documented all new additions.
    enhancement 
    opened by orhun 6
  • The table widget example is misguiding

    The table widget example is misguiding

    Description

    The table widget example is potentially misguiding users on the crossterm Events API. The table widget example uses the KeyCode enum in crossterm without filtering for the KeyEventKind::Press, which leads in events being doubled when pressing keys. It isn't a bug per se, I just don't think that was the behavior that was intended from the snippet.

    line 108-115 in this file for the exact part

    bug 
    opened by philippelejeune01 5
  • docs: add some lines of documentation to clear doubts

    docs: add some lines of documentation to clear doubts

    Upstream: #677

    Description

    It is a PR just to resolve issue #352

    Add a few lines to explain how to define the coordinates

    Testing guidelines

    Just test it using VS Code

    Checklist

    • [X] I have read the contributing guidelines.
    • [X] I have added relevant tests.
    • [X] I have documented all new additions.
    documentation 
    opened by orhun 5
  • Open the discussions tab

    Open the discussions tab

    First of all, thank you for making this project revive. I'm suggesting to enable the discussions on this repository. Indeed, people may want to ask questions, share news of this project, and perhaps announce that the original owner came back. Well, it will be a great opportunity to exchange about this project.

    enhancement 
    opened by antoninhrlt 4
  • Bump crossterm to 0.26 with CI fix

    Bump crossterm to 0.26 with CI fix

    Upstream: #689

    Description

    Testing guidelines

    I checked all examples by cargo run --example {example-name} and confirmed they work on iTerm2 on my Mac machine.

    Checklist

    • [x] I have read the contributing guidelines.
    • [x] I have added relevant tests. (Since this PR just upgrading existing dependency, no tests need to be added)
    • [x] I have documented all new additions.

    Description

    crossterm v0.26.0 was released recently. And some people are starting to use the latest version. Since this crate requires crossterm 0.25, both 0.25 and 0.26 are mixed in user's project when the user depends on crossterm directly. I actually saw an issue around this in my tui-textarea project: https://github.com/rhysd/tui-textarea/issues/9

    The best way to solve the issue is to follow the latest crossterm version by tui crate. I checked the release note and tui crate. Breaking changes seem not relevant to tui crate.

    This is a breaking change due to MSRV bump from 1.56 to 1.58. crossterm 0.26 is using inline format arguments feature and it requires 1.58.

    Build 
    opened by orhun 4
  • Significantly improve `Layout` performance

    Significantly improve `Layout` performance

    Upstream: #585

    Main changes

    I found that the current implementation of Layout was very heavy on allocations and clones, especially considering you're expected to use it plus the split() function every frame. So, I made some changes to allow Layout to work more on the stack.

    This is what I changed Layout to

    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
    pub struct Layout<'a> {
        direction: Direction,
        margin: Margin,
        constraints: &'a [Constraint],
        /// Whether the last chunk of the computed layout should be expanded to fill the available
        /// space.
        expand_to_fill: bool,
    }
    

    This replaces the constraints field with a reference to a slice, instead of a Vec<Constraint>. Considering that most implementations using Layout use static arrays anyway, this seemed like a no brainer, until I tried to use the LAYOUT_CAHCE. It is impossible to store this new Layout inside of the LAYOUT_CACHE because that would require that you borrow the given Layout for 'static. My solution to the problem was only storing the hash of the Layout into the cache as opposed to moving the entire Layout.

    macro_rules! hash_layout {
        ($self:expr, $area:expr) => {{
            let mut to_hash = ahash::AHasher::default();
            $area.hash(&mut to_hash);
            $self.margin.hash(&mut to_hash);
            $self.expand_to_fill.hash(&mut to_hash);
            $self.direction.hash(&mut to_hash);
            $self.constraints.iter().copied().for_each(|f| match f {
                Constraint::Max(max) => to_hash.write_u16(max),
                Constraint::Min(min) => to_hash.write_u16(min),
                Constraint::Ratio(left, right) => {
                    to_hash.write_u32(left);
                    to_hash.write_u32(right);
                }
                Constraint::Length(length) => to_hash.write_u16(length),
                Constraint::Percentage(percentage) => to_hash.write_u16(percentage),
            });
            to_hash.finish()
        }};
    }
    
    #[derive(Clone, Copy)]
    #[repr(transparent)]
    struct CustomHash(u64);
    
    impl Default for CustomHash {
        #[inline]
        fn default() -> Self {
            Self(0)
        }
    }
    
    impl std::hash::Hasher for CustomHash {
        #[inline]
        fn finish(&self) -> u64 {
            self.0
        }
    
        #[inline]
        fn write(&mut self, _: &[u8]) {
            panic!("unsupported operation");
        }
    
        #[inline]
        fn write_u64(&mut self, i: u64) {
            self.0 = i;
        }
    }
    
    thread_local! {
        static LAYOUT_CACHE: RefCell<HashMap<u64, Vec<Rect>, BuildHasherDefault<CustomHash>>> = RefCell::new(HashMap::default());
    }
    
    pub fn split(&self, area: Rect) -> Vec<Rect> {
        // TODO: Maybe use a fixed size cache ?
        LAYOUT_CACHE.with(|c| {
            c.borrow_mut()
                .entry(hash_layout!(self, area))
                .or_insert_with(|| split(area, self))
                .clone()
        })
    }
    

    This is the code I used for storing the layout. Here is a breakdown

    • First I create a hasher using ahash, It's not critical that ahash be the hashing algorithm (the default hasher works as well). However, considering how often the split() function will be run, I think it's worth the sacrifice of one extra dependency.
    • After creating the hasher, I feed it the area parameter, and then each field of the Layout one by one. cargo +nightly bench insisted that this was faster than simply running self.hash(&mut to_hash);
    • After computing the hash of area + self, I use the final value as the final key into the LAYOUT_CAHCE.
    • Because LAYOUT_CACHE uses CustomHash as it's RandomState, the hash computed by ahash is simply passed through and no further hashing is done. There's no point in hashing a hash.
    • Finally, the resulting Vec<Rect> is either grabbed from the LAYOUT_CACHE or computed, and then cloned to bypass the reference created by the HashMap

    Benchmarks

    I did some benchmarks to see just how much my changes effected performance. This was my benchmark

    #[bench]
    fn bench_vertical_split_by_height(b: &mut test::Bencher) {
        let target = Rect {
            x: 2,
            y: 2,
            width: 10,
            height: 10,
        };
    
        let layout = Layout::default()
            .direction(Direction::Vertical)
            .constraints(
                [
                    Constraint::Percentage(10),
                    Constraint::Max(5),
                    Constraint::Min(1),
                ]
                .as_ref(),
            );
    
        b.iter(|| layout.split(target));
    }
    

    When I benchmarked the original implementation and mine, these were my results. (top one is my implementation).

    test layout::tests::bench_vertical_split_by_height ... bench:          89 ns/iter (+/- 5)
    test layout::tests::bench_vertical_split_by_height ... bench:         243 ns/iter (+/- 2)
    

    My implementation seems to be ~3x faster than the original implementation.

    Swapping out ahash with the default hasher (std::collections::hash_map::DefaultHasher::default()) gave me this result

    test layout::tests::bench_vertical_split_by_height ... bench:         148 ns/iter (+/- 10)
    

    Smaller changes

    I noticed that most of the methods inside of this module (layout) were very simple and small, so I made them const and #[inline]ed them.

    Pre-requisites

    All of my changes passed the unit tests and ran the examples.

    Thanks for considering my PR, - StratusFearMe21

    enhancement 
    opened by orhun 4
  • fix(canvas)!: use full block for Marker::Block

    fix(canvas)!: use full block for Marker::Block

    Fixes https://github.com/tui-rs-revival/ratatui/issues/82

    When drawing a vertical line on a canvas, using Marker::Block would draw a gap in between each line. This is because the default block character was a half bar. This changes the default block character to a full block, and adds a new marker type Marker::Bar to replace the current Marker::Block.

    BREAKING CHANGE: Marker::Block now uses a full block character, and Marker::Bar is the new half block character.

    • Adds tests for each Marker in the canvas widget.
    • Adds marker to the canvas example to show the difference between the marker types.
    opened by joshka 3
  • fix(examples): update input in examples to only use press events

    fix(examples): update input in examples to only use press events

    Hi I saw the user_input example was already updated to work on windows but I just did the rest of them that use input other than quit.

    Also added a hack in panic.rs because on windows/powershell a release event is sent from when you originally press enter to cargo run. No more double presses now either.

    Fix https://github.com/tui-rs-revival/ratatui/issues/120

    Edit: I just looked at the conventional commit thing and it's just a fix, you can merge this now

    bug 
    opened by lesleyrs 3
  • Nightly releases

    Nightly releases

    Problem

    There might be some time gaps between new releases so the users cannot test/use the latest functionality without using ratatui as a git dependency in Cargo.toml which makes the crate unpublishable on crates.io. (crates.io doesn't accept git dependencies)

    See what atuin did recently as a workaround: https://github.com/ellie/atuin/commit/a515b06bcb556c1be2d0fc3095cd778d413fe40d

    Solution

    Create automated nightly releases every week or so. ratatui can be used as e.g. version = "nightly-2023-04-21" afterwards.

    Alternatives

    Just plan things out and release more frequently.

    Additional context

    None.


    We need comments/thoughts on this.

    enhancement 
    opened by orhun 6
  • Support conversion from `String` to `Color`

    Support conversion from `String` to `Color`

    Problem

    In my projects I sometimes need a conversion like this:

    "black" => TuiColor::Black,
    "red" => TuiColor::Red,
    "green" => TuiColor::Green,
    

    Solution

    Implement FromStr for ratatui::style::Color.

    An example can be found here.

    In the example, I used rgb crate for converting HEX values to Color as well. Since it introduces a new dependency, I'm not sure if we should do that as well.

    Alternatives

    None.

    Additional context

    I also did something like this in the past: https://github.com/orhun/kmon/blob/66f27006fed614c048469b2511b600d07c8912d6/src/style.rs#L110-L152

    enhancement good first issue 
    opened by orhun 12
  • ratatui prints random bytes on exit

    ratatui prints random bytes on exit

    Description

    When I execute one of the example code from your documentation, it prints random bytes on exit.

    To Reproduce

    use std::{io, thread, time::Duration};
    use ratatui::{
        backend::CrosstermBackend,
        widgets::{Widget, Block, Borders},
        layout::{Layout, Constraint, Direction},
        Terminal
    };
    use crossterm::{
        event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
        execute,
        terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
    };
    
    fn main() -> Result<(), io::Error> {
        // setup terminal
        enable_raw_mode()?;
        let mut stdout = io::stdout();
        execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
        let backend = CrosstermBackend::new(stdout);
        let mut terminal = Terminal::new(backend)?;
    
        terminal.draw(|f| {
            let size = f.size();
            let block = Block::default()
                .title("Block")
                .borders(Borders::ALL);
            f.render_widget(block, size);
        })?;
    
        thread::sleep(Duration::from_millis(5000));
    
        // restore terminal
        disable_raw_mode()?;
        execute!(
            terminal.backend_mut(),
            LeaveAlternateScreen,
            DisableMouseCapture
        )?;
        terminal.show_cursor()?;
    
        Ok(())
    }
    

    Expected behavior

    To not print any byte to command line

    Screenshots

    Bildschirmfoto vom 2023-04-20 20-42-03

    Environment

    • OS: Fedora 36
    • Terminal Emulator: GNOME Terminal
    • Font: Monospace
    • Crate version: 0.20.1
    • Backend: crossterm

    Additional context

    None

    bug 
    opened by alimkoca 6
  • Add the scroll bar to the Paragraph widget

    Add the scroll bar to the Paragraph widget

    Problem

    The Paragraph widget does not have a scroll bar.

    Solution

    Show the scroll bar for the Paragraph widget when the scroll is defined.

    Alternatives

    Additional context

    enhancement 
    opened by pythops 0
  • Add calendar widget

    Add calendar widget

    A calendar widget that with some display options and styling for individual dates.

    This widget displays the month provided to it in the constructor. (see docs and the example for more info).

    One thing to note: This pulls in a new dependency, the time crate. Since this adds a dependency, it might be worth putting the widget behind a feature flag - I'm happy to do so if that's desired.

    opened by sophacles 12
  • Add benchmarking for widgets

    Add benchmarking for widgets

    Problem

    There might be performance issues/concerns about tui widgets and adding benchmarks is important to uncover them.

    Solution

    Add benches for widgets. See #22 for an example.

    Alternatives

    None.

    Additional context

    #22

    enhancement good first issue help wanted 
    opened by orhun 0
Releases(v0.20.1)
  • v0.20.1(Mar 22, 2023)

    This is a bug fix release for the bold text style which wasn't displaying correctly.

    Bug Fixes

    • (style) Bold needs a bit (#104)

    Documentation

    • (apps) Add "logss" to apps (#105)
    • (uncategorized) Fixup remaining tui references (#106)

    Contributors

    Thank you so much to everyone that contributed to this release!

    • @joshka
    • @todoesverso
    • @UncleScientist
    Source code(tar.gz)
    Source code(zip)
  • v0.20.0(Mar 19, 2023)

    This marks the first release of ratatui, a community-maintained fork of tui.

    The purpose of this release is to include bug fixes and small changes into the repository thus no new big features are added. We have transferred all the pull requests from the original repository and worked on the low hanging ones to incorporate them in this "maintenance" release.

    Here is a list of changes:

    Features

    • (cd) Add continuous deployment workflow (#93)
    • (ci) Add MacOS to CI (#60)
    • (widget) Add offset() to TableState (#10)
    • (widget) Add width() to ListItem (#17)

    Bug Fixes

    • (ci) Test MSRV compatibility on CI (#85)
    • (ci) Bump Rust version to 1.63.0 (#80)
    • (ci) Use env for the cargo-make version (#76)
    • (ci) Fix deprecation warnings on CI (#58)
    • (doc) Add 3rd party libraries accidentally removed at #21 (#61)
    • (widget) List should not ignore empty string items (#42) [breaking]
    • (uncategorized) Cassowary/layouts: add extra constraints for fixing Min(v)/Max(v) combination. (#31)
    • (uncategorized) Fix user_input example double key press registered on windows
    • (uncategorized) Ignore zero-width symbol on rendering Paragraph
    • (uncategorized) Fix typos (#45)
    • (uncategorized) Fix typos (#47)

    Refactor

    • (style) Make bitflags smaller (#13)

    Documentation

    • (apps) Move 'apps using ratatui' to dedicated file (#98) (#99)
    • (canvas) Add documentation for x_bounds, y_bounds (#35)
    • (contributing) Specify the use of unsafe for optimization (#67)
    • (github) Remove pull request template (#68)
    • (readme) Update crate status badge (#102)
    • (readme) Small edits before first release (#101)
    • (readme) Add install instruction and update title (#100)
    • (readme) Add systeroid to application list (#92)
    • (readme) Add glicol-cli to showcase list (#95)
    • (readme) Add oxker to application list (#74)
    • (readme) Add app kubectl-watch which uses tui (#73)
    • (readme) Add poketex to 'apps using tui' in README (#64)
    • (readme) Update README.md (#39)
    • (readme) Update README.md (#40)
    • (readme) Clarify README.md fork status update
    • (uncategorized) Fix: fix typos (#90)
    • (uncategorized) Update to build more backends (#81)
    • (uncategorized) Expand "Apps" and "Third-party" sections (#21)
    • (uncategorized) Add tui-input and update xplr in README.md
    • (uncategorized) Add hncli to list of applications made with tui-rs (#41)
    • (uncategorized) Updated readme and contributing guide with updates about the fork (#46)

    Performance

    • (layout) Better safe shared layout cache (#62)

    Miscellaneous Tasks

    • (cargo) Update project metadata (#94)
    • (ci) Integrate typos for checking typos (#91)
    • (ci) Change the target branch to main (#79)
    • (ci) Re-enable clippy on CI (#59)
    • (uncategorized) Integrate committed for checking conventional commits (#77)
    • (uncategorized) Update rust-version to 1.59 in Cargo.toml (#57)
    • (uncategorized) Update deps (#51)
    • (uncategorized) Fix typo in layout.rs (#619)
    • (uncategorized) Add apps using tui

    Contributors

    Thank you so much to everyone that contributed to this release!

    • @orhun
    • @mindoodoo
    • @sayanarijit
    • @Owletti
    • @UncleScientist
    • @rhysd
    • @ckaznable
    • @imuxin
    • @mrjackwills
    • @conradludgate
    • @kianmeng
    • @chaosprint

    And most importantly, special thanks to Florian Dehau for creating this awesome library πŸ’– We look forward to building on the strong foundations that the original crate laid out.

    Source code(tar.gz)
    Source code(zip)
Owner
Ratatui
tui-rs revival project
Ratatui
Firefox used to have this feature a while back (from Firefox 11 to 46) and it is so good, that I feel it needs revival.

3D WebPage Inspector By: Seanpm2001, Et; Al. Top README.md Read this article in a different language Sorted by: A-Z Sorting options unavailable ( af A

Sean P. Myrick V19.1.7.2 3 Nov 10, 2022
A template for bootstrapping a Rust TUI application with tui-rs & crossterm

rust-tui-template A template for bootstrapping a Rust TUI application with tui-rs & crossterm. tui-rs The library is based on the principle of immedia

Orhun ParmaksΔ±z 72 Dec 31, 2022
SKYULL is a command-line interface (CLI) in development that creates REST API project structure templates with the aim of making it easy and fast to start a new project.

SKYULL is a command-line interface (CLI) in development that creates REST API project structure templates with the aim of making it easy and fast to start a new project. With just a few primary configurations, such as project name, you can get started quickly.

Gabriel Michaliszen 4 May 9, 2023
A hackable, minimal, fast TUI file explorer, stealing ideas from nnn and fzf.

xplr A hackable, minimal, fast TUI file explorer, stealing ideas from nnn and fzf. [Quickstart] [Features] [Plugins] [Documentation] [Upgrade Guide] [

Arijit Basu 2.6k Jan 1, 2023
Rust TUI client for steamcmd

Steam TUI About Just a simple TUI client for steamcmd. Allows for the graphical launching, updating, and downloading of steam games through a simple t

Dylan Madisetti 599 Jan 9, 2023
Another TUI based system monitor, this time in Rust!

Another TUI based system monitor, this time in Rust!

Caleb Bassi 2.1k Jan 3, 2023
A user-friendly TUI client for Matrix written in Rust!

Konoha A user-friendly TUI client for Matrix written in Rust! Notice: The client is currently not usable and is only hosted on GitHub for version cont

L3af 9 Jan 5, 2022
TUI image viewer

Picterm TUI image viewer install $ cargo install picterm or $ git clone https://github.com/ksk001100/picterm $ cd picterm $ cargo install --path . usa

Keisuke Toyota 41 Dec 31, 2022
A cli prepared with TUI that facilitates your operations.

⚠️ For linux only ⚠️ Helper CLI A cli prepared with TUI that facilitates your operations. Click me to learn more about the theme system. If you just w

Yiğit 4 Feb 1, 2022
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
Parse hex colors to tui::style::Color

Color -> Tui Parse hex colors to tui rgb colors #c3f111 -> Color::Rgb(195,241,17) Note that the indexed colors are NOT HEX #142 -> Color::Indexed(142)

Uttarayan Mondal 1 Nov 8, 2021
TUI input library supporting multiple backends

tui-input WARNING: Most of the functionality is only human tested. A TUI input library supporting multiple backends. This crate can be used with tui-r

Arijit Basu 36 Dec 19, 2022
2048 in `tui`, just for fun

TUI 2048 - Have a relax at anytime - ?? ^_^ How to run repo clone this repo, git clone https://github.com/WanderHuang/game-2048-tui.git cd game-2048-t

wander 43 Dec 16, 2022
Tiny color conversion library for TUI application builders

Definition of ANSI, RGB and HSL color types and all the conversions between them. There are many other color conversion crates. This one may be useful

Canop 8 Dec 15, 2022
FastSSH is a TUI that allows you to quickly connect to your services by navigating through your SSH config.

Connect quickly to your services ?? FastSSH is a TUI that allows you to quickly connect to your services by navigating through your SSH config. Instal

Julien 85 Dec 14, 2022
Lemurs - A lightweight TUI display/login manager written in Rust πŸ’

Lemurs ?? A TUI Display/Login Manager written in Rust WIP: Whilst the project is working and installable, there are still a lot of bugs and limitation

Gijs Burghoorn 136 Jan 1, 2023
Playground for 2D EKF-SLAM as TUI in Rust

SLAMme.RS Playground for 2D EKF-SLAM as TUI in Rust Installation $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # install RUST $ su

Thore Goll 1 Jan 14, 2022
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
Rust TUI library - Clipping region is a set of min/max x/y values applied to the existing region

TinyBit Clipping region is a set of min/max x/y values applied to the existing region A TUI lib This is not yet production ready T O D O TODO: bugs: T

Togglebit 13 May 3, 2022