mirror of
https://github.com/ratatui/ratatui.git
synced 2025-10-02 15:25:54 +00:00
docs: update README.md and add hello_world example (#204)
- Reformat summary info - Add badges for dependencies, discord, license - point existing badges to shields.io - add Table of Contents - tweaked installation instructions to show instructions for new and existing crates - moved fork status lower - chop lines generally to 100 limit - add a quickstart based on a simplified hello_world example - added / updated some internal links to point locally - removed some details to simplify the readme (e.g. tick-rate) - reordered widgets and pointed these at the widget docs - adds a hello_world example that has just the absolute basic code necessary to run a ratatui app. This includes some comments that help guide the user towards other approaches and considerations for a real world app.
This commit is contained in:
parent
a68d621f2d
commit
b40ca44e1a
@ -40,6 +40,7 @@ serde = { version = "1", optional = true, features = ["derive"]}
|
|||||||
time = { version = "0.3.11", optional = true, features = ["local-offset"]}
|
time = { version = "0.3.11", optional = true, features = ["local-offset"]}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
anyhow = "1.0.71"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
argh = "0.1"
|
argh = "0.1"
|
||||||
indoc = "2.0"
|
indoc = "2.0"
|
||||||
@ -84,6 +85,11 @@ name = "gauge"
|
|||||||
required-features = ["crossterm"]
|
required-features = ["crossterm"]
|
||||||
doc-scrape-examples = true
|
doc-scrape-examples = true
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "hello_world"
|
||||||
|
required-features = ["crossterm"]
|
||||||
|
doc-scrape-examples = true
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "layout"
|
name = "layout"
|
||||||
required-features = ["crossterm"]
|
required-features = ["crossterm"]
|
||||||
|
271
README.md
271
README.md
@ -1,142 +1,237 @@
|
|||||||
# ratatui
|
# Ratatui
|
||||||
|
|
||||||
An actively maintained `tui-rs` fork.
|
<img align="left" src="https://avatars.githubusercontent.com/u/125200832?s=128&v=4">
|
||||||
|
|
||||||
[](https://github.com/tui-rs-revival/ratatui/actions?query=workflow%3ACI+)
|
`ratatui` is a [Rust](https://www.rust-lang.org) library to build rich terminal user interfaces and
|
||||||
[](https://crates.io/crates/ratatui)
|
dashboards. It is a community fork of the original [tui-rs](https://github.com/fdehau/tui-rs)
|
||||||
[](https://docs.rs/crate/ratatui/)
|
project.
|
||||||
|
|
||||||
<img src="./assets/demo.gif" alt="Demo cast under Linux Termite with Inconsolata font 12pt">
|
[](https://crates.io/crates/ratatui)
|
||||||
|
[](./LICENSE)
|
||||||
|
[](https://github.com/tui-rs-revival/ratatui/actions?query=workflow%3ACI+)
|
||||||
|
[](https://docs.rs/crate/ratatui/)
|
||||||
|
[](https://deps.rs/repo/github/tui-rs-revival/ratatui)
|
||||||
|
[](https://app.codecov.io/gh/tui-rs-revival/ratatui)
|
||||||
|
[](https://discord.gg/pMCEU9hNEj)
|
||||||
|
|
||||||
# Install
|

|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Table of Contents</summary>
|
||||||
|
|
||||||
|
* [Ratatui](#ratatui)
|
||||||
|
* [Installation](#installation)
|
||||||
|
* [Introduction](#introduction)
|
||||||
|
* [Quickstart](#quickstart)
|
||||||
|
* [Status of this fork](#status-of-this-fork)
|
||||||
|
* [Rust version requirements](#rust-version-requirements)
|
||||||
|
* [Documentation](#documentation)
|
||||||
|
* [Examples](#examples)
|
||||||
|
* [Widgets](#widgets)
|
||||||
|
* [Built in](#built-in)
|
||||||
|
* [Third\-party libraries, bootstrapping templates and widgets](#third-party-libraries-bootstrapping-templates-and-widgets)
|
||||||
|
* [Apps](#apps)
|
||||||
|
* [Alternatives](#alternatives)
|
||||||
|
* [Acknowledgements](#acknowledgements)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cargo add ratatui --features all-widgets
|
||||||
|
```
|
||||||
|
|
||||||
|
Or modify your `Cargo.toml`
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tui = { package = "ratatui" }
|
ratatui = { version = "0.21.0", features = ["all-widgets"]}
|
||||||
```
|
```
|
||||||
|
|
||||||
# What is this fork?
|
Ratatui is mostly backwards compatible with `tui-rs`. To migrate an existing project, it may be
|
||||||
|
easier to rename the ratatui dependency to `tui` rather than updating every usage of the crate.
|
||||||
|
E.g.:
|
||||||
|
|
||||||
This fork was created to continue maintenance on the original TUI project. The original maintainer had created an [issue](https://github.com/fdehau/tui-rs/issues/654) explaining how he couldn't find time to continue development, which led to us creating this fork.
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
tui = { package = "ratatui", version = "0.21.0", features = ["all-widgets"]}
|
||||||
|
```
|
||||||
|
|
||||||
With that in mind, **we the community** look forward to continuing the work started by [**Florian Dehau.**](https://github.com/fdehau) :rocket:
|
## Introduction
|
||||||
|
|
||||||
In order to organize ourselves, we currently use a [discord server](https://discord.gg/pMCEU9hNEj), feel free to join and come chat ! There are also plans to implement a [matrix](https://matrix.org/) bridge in the near future.
|
`ratatui` is a terminal UI library that supports multiple backends:
|
||||||
**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. :smile:
|
|
||||||
|
|
||||||
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.
|
* [crossterm](https://github.com/crossterm-rs/crossterm) [default]
|
||||||
|
* [termion](https://github.com/ticki/termion)
|
||||||
|
* [termwiz](https://github.com/wez/wezterm/tree/master/termwiz)
|
||||||
|
|
||||||
# Introduction
|
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
|
||||||
`ratatui` is a [Rust](https://www.rust-lang.org) library to build rich terminal
|
providing a great flexibility for rich and interactive UI, this may introduce overhead for highly
|
||||||
user interfaces and dashboards. It is heavily inspired by the `Javascript`
|
dynamic content. So, the implementation try to minimize the number of ansi escapes sequences
|
||||||
library [blessed-contrib](https://github.com/yaronn/blessed-contrib) and the
|
generated to draw the updated UI. In practice, given the speed of `Rust` the overhead rather comes
|
||||||
`Go` library [termui](https://github.com/gizak/termui).
|
from the terminal emulator than the library itself.
|
||||||
|
|
||||||
The library supports multiple backends:
|
|
||||||
|
|
||||||
- [crossterm](https://github.com/crossterm-rs/crossterm) [default]
|
|
||||||
- [termion](https://github.com/ticki/termion)
|
|
||||||
- [termwiz](https://github.com/wez/wezterm/tree/master/termwiz)
|
|
||||||
|
|
||||||
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
|
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.
|
you may rely on the previously cited libraries to achieve such features.
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
The following example demonstrates the minimal amount of code necessary to setup a terminal and
|
||||||
|
render "Hello World!". The full code for this example which contains a little more detail is in
|
||||||
|
[hello_world.rs](./examples/hello_world.rs). For more guidance on how to create Ratatui apps, see
|
||||||
|
the [Docs](https://docs.rs/ratatui) and [Examples](#examples). There is also a starter template
|
||||||
|
available at [rust-tui-template](https://github.com/tui-rs-revival/rust-tui-template).
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut terminal = setup_terminal()?;
|
||||||
|
run(&mut terminal)?;
|
||||||
|
restore_terminal(&mut terminal)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_terminal() -> Result<Terminal<CrosstermBackend<Stdout>>, Box<dyn Error>> {
|
||||||
|
let mut stdout = io::stdout();
|
||||||
|
enable_raw_mode()?;
|
||||||
|
execute!(stdout, EnterAlternateScreen)?;
|
||||||
|
Ok(Terminal::new(CrosstermBackend::new(stdout))?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_terminal(
|
||||||
|
terminal: &mut Terminal<CrosstermBackend<Stdout>>,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
disable_raw_mode()?;
|
||||||
|
execute!(terminal.backend_mut(), LeaveAlternateScreen,)?;
|
||||||
|
Ok(terminal.show_cursor()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>) -> Result<(), Box<dyn Error>> {
|
||||||
|
Ok(loop {
|
||||||
|
terminal.draw(|frame| {
|
||||||
|
let greeting = Paragraph::new("Hello World!");
|
||||||
|
frame.render_widget(greeting, frame.size());
|
||||||
|
})?;
|
||||||
|
if event::poll(Duration::from_millis(250))? {
|
||||||
|
if let Event::Key(key) = event::read()? {
|
||||||
|
if KeyCode::Char('q') == key.code {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Status of this fork
|
||||||
|
|
||||||
|
In response to the original maintainer [**Florian Dehau**](https://github.com/fdehau)'s issue
|
||||||
|
regarding the [future of `tui-rs`](https://github.com/fdehau/tui-rs/issues/654), several members of
|
||||||
|
the community forked the project and created this crate. We look forward to continuing the work
|
||||||
|
started by Florian 🚀
|
||||||
|
|
||||||
|
In order to organize ourselves, we currently use a [Discord server](https://discord.gg/pMCEU9hNEj),
|
||||||
|
feel free to join and come chat! There are also plans to implement a [Matrix](https://matrix.org/)
|
||||||
|
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](./CONTRIBUTING.md) guidelines, especially if
|
||||||
|
you are interested in working on a PR or issue opened in the previous repository.
|
||||||
|
|
||||||
## Rust version requirements
|
## Rust version requirements
|
||||||
|
|
||||||
Since version 0.21.0, `ratatui` requires **rustc version 1.65.0 or greater**.
|
Since version 0.21.0, The Minimum Supported Rust Version (MSRV) of `ratatui` is 1.65.0.
|
||||||
|
|
||||||
# Documentation
|
## Documentation
|
||||||
|
|
||||||
The documentation can be found on [docs.rs.](https://docs.rs/ratatui)
|
The documentation can be found on [docs.rs.](https://docs.rs/ratatui)
|
||||||
|
|
||||||
# Demo
|
## Examples
|
||||||
|
|
||||||
The demo shown in the gif can be run with all available backends.
|
The demo shown in the gif above is available on all available backends.
|
||||||
|
|
||||||
```
|
```shell
|
||||||
# crossterm
|
# crossterm
|
||||||
cargo run --example demo --release -- --tick-rate 200
|
cargo run --example demo
|
||||||
# termion
|
# termion
|
||||||
cargo run --example demo --no-default-features --features=termion --release -- --tick-rate 200
|
cargo run --example demo --no-default-features --features=termion
|
||||||
# termwiz
|
# termwiz
|
||||||
cargo run --example demo --no-default-features --features=termwiz --release -- --tick-rate 200
|
cargo run --example demo --no-default-features --features=termwiz
|
||||||
```
|
```
|
||||||
|
|
||||||
where `tick-rate` is the UI refresh rate in ms.
|
The UI code for the is in [examples/demo/ui.rs](./examples/demo/ui.rs) while the application state is in
|
||||||
|
[examples/demo/app.rs](./examples/demo/app.rs).
|
||||||
|
|
||||||
The UI code is in [examples/demo/ui.rs](https://github.com/tui-rs-revival/ratatui/blob/main/examples/demo/ui.rs) while the
|
If the user interface contains glyphs that are not displayed correctly by your terminal, you may
|
||||||
application state is in [examples/demo/app.rs](https://github.com/tui-rs-revival/ratatui/blob/main/examples/demo/app.rs).
|
want to run the demo without those symbols:
|
||||||
|
|
||||||
If the user interface contains glyphs that are not displayed correctly by your terminal, you may want to run
|
```shell
|
||||||
the demo without those symbols:
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo run --example demo --release -- --tick-rate 200 --enhanced-graphics false
|
cargo run --example demo --release -- --tick-rate 200 --enhanced-graphics false
|
||||||
```
|
```
|
||||||
|
|
||||||
# Widgets
|
More examples are available in the [examples](./examples/) folder.
|
||||||
|
|
||||||
## Built in
|
## Widgets
|
||||||
|
|
||||||
The library comes with the following list of widgets:
|
### Built in
|
||||||
|
|
||||||
- [Block](https://github.com/tui-rs-revival/ratatui/blob/main/examples/block.rs)
|
The library comes with the following
|
||||||
- [Gauge](https://github.com/tui-rs-revival/ratatui/blob/main/examples/gauge.rs)
|
[widgets](https://docs.rs/ratatui/latest/ratatui/widgets/index.html):
|
||||||
- [Sparkline](https://github.com/tui-rs-revival/ratatui/blob/main/examples/sparkline.rs)
|
|
||||||
- [Chart](https://github.com/tui-rs-revival/ratatui/blob/main/examples/chart.rs)
|
|
||||||
- [BarChart](https://github.com/tui-rs-revival/ratatui/blob/main/examples/barchart.rs)
|
|
||||||
- [List](https://github.com/tui-rs-revival/ratatui/blob/main/examples/list.rs)
|
|
||||||
- [Table](https://github.com/tui-rs-revival/ratatui/blob/main/examples/table.rs)
|
|
||||||
- [Paragraph](https://github.com/tui-rs-revival/ratatui/blob/main/examples/paragraph.rs)
|
|
||||||
- [Canvas (with line, point cloud, map)](https://github.com/tui-rs-revival/ratatui/blob/main/examples/canvas.rs)
|
|
||||||
- [Tabs](https://github.com/tui-rs-revival/ratatui/blob/main/examples/tabs.rs)
|
|
||||||
|
|
||||||
Click on each item to see the source of the example. Run the examples with
|
* [Canvas](https://docs.rs/ratatui/latest/ratatui/widgets/canvas/struct.Canvas.html) which allows
|
||||||
cargo (e.g. to run the gauge example `cargo run --example gauge`), and quit by pressing `q`.
|
rendering [points, lines, shapes and a world map](https://docs.rs/ratatui/latest/ratatui/widgets/canvas/index.html)
|
||||||
|
* [BarChart](https://docs.rs/ratatui/latest/ratatui/widgets/struct.BarChart.html)
|
||||||
|
* [Block](https://docs.rs/ratatui/latest/ratatui/widgets/struct.Block.html)
|
||||||
|
* [Calendar](https://docs.rs/ratatui/latest/ratatui/widgets/calendar/index.html)
|
||||||
|
* [Chart](https://docs.rs/ratatui/latest/ratatui/widgets/struct.Chart.html)
|
||||||
|
* [Gauge](https://docs.rs/ratatui/latest/ratatui/widgets/struct.Gauge.html)
|
||||||
|
* [List](https://docs.rs/ratatui/latest/ratatui/widgets/struct.List.html)
|
||||||
|
* [Paragraph](https://docs.rs/ratatui/latest/ratatui/widgets/struct.Paragraph.html)
|
||||||
|
* [Sparkline](https://docs.rs/ratatui/latest/ratatui/widgets/struct.Sparkline.html)
|
||||||
|
* [Table](https://docs.rs/ratatui/latest/ratatui/widgets/struct.Table.html)
|
||||||
|
* [Tabs](https://docs.rs/ratatui/latest/ratatui/widgets/struct.Tabs.html)
|
||||||
|
|
||||||
You can run all examples by running `cargo make run-examples` (require
|
Each wiget has an associated example which can be found in the [examples](./examples/) folder. Run
|
||||||
`cargo-make` that can be installed with `cargo install cargo-make`).
|
each examples with cargo (e.g. to run the gauge example `cargo run --example gauge`), and quit by
|
||||||
|
pressing `q`.
|
||||||
|
|
||||||
|
You can also run all examples by running `cargo make run-examples` (requires `cargo-make` that can
|
||||||
|
be installed with `cargo install cargo-make`).
|
||||||
|
|
||||||
### Third-party libraries, bootstrapping templates and widgets
|
### Third-party libraries, bootstrapping templates and widgets
|
||||||
|
|
||||||
- [ansi-to-tui](https://github.com/uttarayan21/ansi-to-tui) — Convert ansi colored text to `tui::text::Text`
|
* [ansi-to-tui](https://github.com/uttarayan21/ansi-to-tui) — Convert ansi colored text to `tui::text::Text`
|
||||||
- [color-to-tui](https://github.com/uttarayan21/color-to-tui) — Parse hex colors to `tui::style::Color`
|
* [color-to-tui](https://github.com/uttarayan21/color-to-tui) — Parse hex colors to `tui::style::Color`
|
||||||
- [rust-tui-template](https://github.com/orhun/rust-tui-template) — A template for bootstrapping a Rust TUI application with Tui-rs & crossterm
|
* [rust-tui-template](https://github.com/orhun/rust-tui-template) — A template for bootstrapping a Rust TUI application with Tui-rs & crossterm
|
||||||
- [simple-tui-rs](https://github.com/pmsanford/simple-tui-rs) — A simple example tui-rs app
|
* [simple-tui-rs](https://github.com/pmsanford/simple-tui-rs) — A simple example tui-rs app
|
||||||
- [tui-builder](https://github.com/jkelleyrtp/tui-builder) — Batteries-included MVC framework for Tui-rs + Crossterm apps
|
* [tui-builder](https://github.com/jkelleyrtp/tui-builder) — Batteries-included MVC framework for Tui-rs + Crossterm apps
|
||||||
- [tui-clap](https://github.com/kegesch/tui-clap-rs) — Use clap-rs together with Tui-rs
|
* [tui-clap](https://github.com/kegesch/tui-clap-rs) — Use clap-rs together with Tui-rs
|
||||||
- [tui-log](https://github.com/kegesch/tui-log-rs) — Example of how to use logging with Tui-rs
|
* [tui-log](https://github.com/kegesch/tui-log-rs) — Example of how to use logging with Tui-rs
|
||||||
- [tui-logger](https://github.com/gin66/tui-logger) — Logger and Widget for Tui-rs
|
* [tui-logger](https://github.com/gin66/tui-logger) — Logger and Widget for Tui-rs
|
||||||
- [tui-realm](https://github.com/veeso/tui-realm) — Tui-rs framework to build stateful applications with a React/Elm inspired approach
|
* [tui-realm](https://github.com/veeso/tui-realm) — Tui-rs framework to build stateful applications with a React/Elm inspired approach
|
||||||
- [tui-realm-treeview](https://github.com/veeso/tui-realm-treeview) — Treeview component for Tui-realm
|
* [tui-realm-treeview](https://github.com/veeso/tui-realm-treeview) — Treeview component for Tui-realm
|
||||||
- [tui tree widget](https://github.com/EdJoPaTo/tui-rs-tree-widget) — Tree Widget for Tui-rs
|
* [tui tree widget](https://github.com/EdJoPaTo/tui-rs-tree-widget) — Tree Widget for Tui-rs
|
||||||
- [tui-windows](https://github.com/markatk/tui-windows-rs) — Tui-rs abstraction to handle multiple windows and their rendering
|
* [tui-windows](https://github.com/markatk/tui-windows-rs) — Tui-rs abstraction to handle multiple windows and their rendering
|
||||||
- [tui-textarea](https://github.com/rhysd/tui-textarea): Simple yet powerful multi-line text editor widget supporting several key shortcuts, undo/redo, text search, etc.
|
* [tui-textarea](https://github.com/rhysd/tui-textarea): Simple yet powerful multi-line text editor widget supporting several key shortcuts, undo/redo, text search, etc.
|
||||||
- [tui-rs-tree-widgets](https://github.com/EdJoPaTo/tui-rs-tree-widget): Widget for tree data structures.
|
* [tui-rs-tree-widgets](https://github.com/EdJoPaTo/tui-rs-tree-widget): Widget for tree data structures.
|
||||||
- [tui-input](https://github.com/sayanarijit/tui-input): TUI input library supporting multiple backends and tui-rs.
|
* [tui-input](https://github.com/sayanarijit/tui-input): TUI input library supporting multiple backends and tui-rs.
|
||||||
|
|
||||||
# Apps
|
## Apps
|
||||||
|
|
||||||
Check out the list of [close to 40 apps](./APPS.md) using `ratatui`!
|
Check out the list of [close to 40 apps](./APPS.md) using `ratatui`!
|
||||||
|
|
||||||
# Alternatives
|
## Alternatives
|
||||||
|
|
||||||
You might want to checkout [Cursive](https://github.com/gyscos/Cursive) for an
|
You might want to checkout [Cursive](https://github.com/gyscos/Cursive) for an alternative solution
|
||||||
alternative solution to build text user interfaces in Rust.
|
to build text user interfaces in Rust.
|
||||||
|
|
||||||
# Acknowledgements
|
## Acknowledgements
|
||||||
|
|
||||||
Special thanks to [**Pavel Fomchenkov**](https://github.com/nawok) for his work in designing **an awesome logo** for the ratatui project and tui-rs-revival organization.
|
Special thanks to [**Pavel Fomchenkov**](https://github.com/nawok) for his work in designing **an awesome logo** for the ratatui project and tui-rs-revival organization.
|
||||||
|
|
||||||
# License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](./LICENSE)
|
||||||
|
79
examples/hello_world.rs
Normal file
79
examples/hello_world.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
use anyhow::{Context, Result};
|
||||||
|
use crossterm::{
|
||||||
|
event::{self, Event, KeyCode},
|
||||||
|
execute,
|
||||||
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
|
};
|
||||||
|
use ratatui::{backend::CrosstermBackend, widgets::Paragraph, Terminal};
|
||||||
|
use std::{
|
||||||
|
io::{self, Stdout},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This is a bare minimum example. There are many approaches to running an application loop, so
|
||||||
|
/// this is not meant to be prescriptive. It is only meant to demonstrate the basic setup and
|
||||||
|
/// teardown of a terminal application.
|
||||||
|
///
|
||||||
|
/// A more robust application would probably want to handle errors and ensure that the terminal is
|
||||||
|
/// restored to a sane state before exiting. This example does not do that. It also does not handle
|
||||||
|
/// events or update the application state. It just draws a greeting and exits when the user
|
||||||
|
/// presses 'q'.
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let mut terminal = setup_terminal().context("setup failed")?;
|
||||||
|
run(&mut terminal).context("app loop failed")?;
|
||||||
|
restore_terminal(&mut terminal).context("restore terminal failed")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Setup the terminal. This is where you would enable raw mode, enter the alternate screen, and
|
||||||
|
/// hide the cursor. This example does not handle errors. A more robust application would probably
|
||||||
|
/// want to handle errors and ensure that the terminal is restored to a sane state before exiting.
|
||||||
|
fn setup_terminal() -> Result<Terminal<CrosstermBackend<Stdout>>> {
|
||||||
|
let mut stdout = io::stdout();
|
||||||
|
enable_raw_mode().context("failed to enable raw mode")?;
|
||||||
|
execute!(stdout, EnterAlternateScreen).context("unable to enter alternate screen")?;
|
||||||
|
Terminal::new(CrosstermBackend::new(stdout)).context("creating terminal failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restore the terminal. This is where you disable raw mode, leave the alternate screen, and show
|
||||||
|
/// the cursor.
|
||||||
|
fn restore_terminal(terminal: &mut Terminal<CrosstermBackend<Stdout>>) -> Result<()> {
|
||||||
|
disable_raw_mode().context("failed to disable raw mode")?;
|
||||||
|
execute!(terminal.backend_mut(), LeaveAlternateScreen)
|
||||||
|
.context("unable to switch to main screen")?;
|
||||||
|
terminal.show_cursor().context("unable to show cursor")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the application loop. This is where you would handle events and update the application
|
||||||
|
/// state. This example exits when the user presses 'q'. Other styles of application loops are
|
||||||
|
/// possible, for example, you could have multiple application states and switch between them based
|
||||||
|
/// on events, or you could have a single application state and update it based on events.
|
||||||
|
fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>) -> Result<()> {
|
||||||
|
loop {
|
||||||
|
terminal.draw(crate::render_app)?;
|
||||||
|
if should_quit()? {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the application. This is where you would draw the application UI. This example just
|
||||||
|
/// draws a greeting.
|
||||||
|
fn render_app(frame: &mut ratatui::Frame<CrosstermBackend<Stdout>>) {
|
||||||
|
let greeting = Paragraph::new("Hello World! (press 'q' to quit)");
|
||||||
|
frame.render_widget(greeting, frame.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the user has pressed 'q'. This is where you would handle events. This example just
|
||||||
|
/// checks if the user has pressed 'q' and returns true if they have. It does not handle any other
|
||||||
|
/// events. There is a 250ms timeout on the event poll so that the application can exit in a timely
|
||||||
|
/// manner, and to ensure that the terminal is rendered at least once every 250ms.
|
||||||
|
fn should_quit() -> Result<bool> {
|
||||||
|
if event::poll(Duration::from_millis(250)).context("event poll failed")? {
|
||||||
|
if let Event::Key(key) = event::read().context("event read failed")? {
|
||||||
|
return Ok(KeyCode::Char('q') == key.code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user