mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-21 20:23:11 +00:00
docs: tweak readme (#1419)
Fixes: <https://github.com/ratatui/ratatui/issues/1417>
This commit is contained in:
parent
6db16d67fc
commit
4728f0e68b
4 changed files with 243 additions and 204 deletions
229
README.md
229
README.md
|
@ -2,14 +2,13 @@
|
||||||
<summary>Table of Contents</summary>
|
<summary>Table of Contents</summary>
|
||||||
|
|
||||||
- [Ratatui](#ratatui)
|
- [Ratatui](#ratatui)
|
||||||
- [Installation](#installation)
|
- [Quick Start](#quickstart)
|
||||||
- [Introduction](#introduction)
|
|
||||||
- [Other documentation](#other-documentation)
|
- [Other documentation](#other-documentation)
|
||||||
|
- [Introduction](#introduction)
|
||||||
- [Quickstart](#quickstart)
|
- [Quickstart](#quickstart)
|
||||||
- [Initialize and restore the terminal](#initialize-and-restore-the-terminal)
|
- [Initialize and restore the terminal](#initialize-and-restore-the-terminal)
|
||||||
- [Drawing the UI](#drawing-the-ui)
|
- [Drawing the UI](#drawing-the-ui)
|
||||||
- [Handling events](#handling-events)
|
- [Handling events](#handling-events)
|
||||||
- [Example](#example)
|
|
||||||
- [Layout](#layout)
|
- [Layout](#layout)
|
||||||
- [Text and styling](#text-and-styling)
|
- [Text and styling](#text-and-styling)
|
||||||
- [Status of this fork](#status-of-this-fork)
|
- [Status of this fork](#status-of-this-fork)
|
||||||
|
@ -45,28 +44,42 @@ Badge]][GitHub Sponsors]<br> [![Discord Badge]][Discord Server] [![Matrix Badge]
|
||||||
lightweight library that provides a set of widgets and utilities to build complex Rust TUIs.
|
lightweight library that provides a set of widgets and utilities to build complex Rust TUIs.
|
||||||
Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development.
|
Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development.
|
||||||
|
|
||||||
## Installation
|
## Quickstart
|
||||||
|
|
||||||
Add `ratatui` as a dependency to your cargo.toml:
|
Add `ratatui` and `crossterm` as dependencies to your cargo.toml:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cargo add ratatui
|
cargo add ratatui crossterm
|
||||||
```
|
```
|
||||||
|
|
||||||
Ratatui uses [Crossterm] by default as it works on most platforms. See the [Installation]
|
Then you can create a simple "Hello World" application:
|
||||||
section of the [Ratatui Website] for more details on how to use other backends ([Termion] /
|
|
||||||
[Termwiz]).
|
|
||||||
|
|
||||||
## Introduction
|
```rust
|
||||||
|
use crossterm::event::{self, Event};
|
||||||
|
use ratatui::{text::Text, Frame};
|
||||||
|
|
||||||
Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
|
fn main() {
|
||||||
that for each frame, your app must render all widgets that are supposed to be part of the UI.
|
let mut terminal = ratatui::init();
|
||||||
This is in contrast to the retained mode style of rendering where widgets are updated and then
|
loop {
|
||||||
automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
|
terminal.draw(draw).expect("failed to draw frame");
|
||||||
for more info.
|
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ratatui::restore();
|
||||||
|
}
|
||||||
|
|
||||||
You can also watch the [FOSDEM 2024 talk] about Ratatui which gives a brief introduction to
|
fn draw(frame: &mut Frame) {
|
||||||
terminal user interfaces and showcases the features of Ratatui, along with a hello world demo.
|
let text = Text::raw("Hello World!");
|
||||||
|
frame.render_widget(text, frame.area());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The full code for this example which contains a little more detail is in the [Examples]
|
||||||
|
directory. For more guidance on different ways to structure your application see the
|
||||||
|
[Application Patterns] and [Hello World tutorial] sections in the [Ratatui Website] and the
|
||||||
|
various [Examples]. There are also several starter templates available in the [templates]
|
||||||
|
repository.
|
||||||
|
|
||||||
## Other documentation
|
## Other documentation
|
||||||
|
|
||||||
|
@ -78,46 +91,82 @@ terminal user interfaces and showcases the features of Ratatui, along with a hel
|
||||||
- [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
|
- [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
|
||||||
- [Breaking Changes] - a list of breaking changes in the library.
|
- [Breaking Changes] - a list of breaking changes in the library.
|
||||||
|
|
||||||
## Quickstart
|
You can also watch the [FOSDEM 2024 talk] about Ratatui which gives a brief introduction to
|
||||||
|
terminal user interfaces and showcases the features of Ratatui, along with a hello world demo.
|
||||||
|
|
||||||
The following example demonstrates the minimal amount of code necessary to setup a terminal and
|
## Introduction
|
||||||
render "Hello World!". The full code for this example which contains a little more detail is in
|
|
||||||
the [Examples] directory. For more guidance on different ways to structure your application see
|
Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
|
||||||
the [Application Patterns] and [Hello World tutorial] sections in the [Ratatui Website] and the
|
that for each frame, your app must render all widgets that are supposed to be part of the UI.
|
||||||
various [Examples]. There are also several starter templates available in the [templates]
|
This is in contrast to the retained mode style of rendering where widgets are updated and then
|
||||||
repository.
|
automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
|
||||||
|
for more info.
|
||||||
|
|
||||||
|
Ratatui uses [Crossterm] by default as it works on most platforms. See the [Installation]
|
||||||
|
section of the [Ratatui Website] for more details on how to use other backends ([Termion] /
|
||||||
|
[Termwiz]).
|
||||||
|
|
||||||
Every application built with `ratatui` needs to implement the following steps:
|
Every application built with `ratatui` needs to implement the following steps:
|
||||||
|
|
||||||
- Initialize the terminal
|
- Initialize the terminal
|
||||||
- A main loop to:
|
- A main loop that:
|
||||||
- Handle input events
|
- Draws the UI
|
||||||
- Draw the UI
|
- Handles input events
|
||||||
- Restore the terminal state
|
- Restore the terminal state
|
||||||
|
|
||||||
The library contains a [`prelude`] module that re-exports the most commonly used traits and
|
|
||||||
types for convenience. Most examples in the documentation will use this instead of showing the
|
|
||||||
full path of each type.
|
|
||||||
|
|
||||||
### Initialize and restore the terminal
|
### Initialize and restore the terminal
|
||||||
|
|
||||||
The [`Terminal`] type is the main entry point for any Ratatui application. It is a light
|
The [`Terminal`] type is the main entry point for any Ratatui application. It is generic over a
|
||||||
abstraction over a choice of [`Backend`] implementations that provides functionality to draw
|
a choice of [`Backend`] implementations that each provide functionality to draw frames, clear
|
||||||
each frame, clear the screen, hide the cursor, etc. It is parametrized over any type that
|
the screen, hide the cursor, etc. There are backend implementations for [Crossterm], [Termion]
|
||||||
implements the [`Backend`] trait which has implementations for [Crossterm], [Termion] and
|
and [Termwiz].
|
||||||
[Termwiz].
|
|
||||||
|
|
||||||
Most applications should enter the Alternate Screen when starting and leave it when exiting and
|
The simplest way to initialize the terminal is to use the [`init`] function which returns a
|
||||||
also enable raw mode to disable line buffering and enable reading key events. See the [`backend`
|
[`DefaultTerminal`] instance with the default options, enters the Alternate Screen and Raw mode
|
||||||
module] and the [Backends] section of the [Ratatui Website] for more info.
|
and sets up a panic hook that restores the terminal in case of panic. This instance can then be
|
||||||
|
used to draw frames and interact with the terminal state. (The [`DefaultTerminal`] instance is a
|
||||||
|
type alias for a terminal with the [`crossterm`] backend.) The [`restore`] function restores the
|
||||||
|
terminal to its original state.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let mut terminal = ratatui::init();
|
||||||
|
let result = run(&mut terminal);
|
||||||
|
ratatui::restore();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [`backend` module] and the [Backends] section of the [Ratatui Website] for more info on
|
||||||
|
the alternate screen and raw mode.
|
||||||
|
|
||||||
### Drawing the UI
|
### Drawing the UI
|
||||||
|
|
||||||
The drawing logic is delegated to a closure that takes a [`Frame`] instance as argument. The
|
Drawing the UI is done by calling the [`Terminal::draw`] method on the terminal instance. This
|
||||||
[`Frame`] provides the size of the area to draw to and allows the app to render any [`Widget`]
|
method takes a closure that is called with a [`Frame`] instance. The [`Frame`] provides the size
|
||||||
using the provided [`render_widget`] method. After this closure returns, a diff is performed and
|
of the area to draw to and allows the app to render any [`Widget`] using the provided
|
||||||
only the changes are drawn to the terminal. See the [Widgets] section of the [Ratatui Website]
|
[`render_widget`] method. After this closure returns, a diff is performed and only the changes
|
||||||
for more info.
|
are drawn to the terminal. See the [Widgets] section of the [Ratatui Website] for more info.
|
||||||
|
|
||||||
|
The closure passed to the [`Terminal::draw`] method should handle the rendering of a full frame.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use ratatui::{Frame, widgets::Paragraph};
|
||||||
|
|
||||||
|
fn run(terminal: &mut ratatui::DefaultTerminal) -> std::io::Result<()> {
|
||||||
|
loop {
|
||||||
|
terminal.draw(|frame| draw(frame))?;
|
||||||
|
if handle_events()? {
|
||||||
|
break Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(frame: &mut Frame) {
|
||||||
|
let text = Paragraph::new("Hello World!");
|
||||||
|
frame.render_widget(text, frame.area());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Handling events
|
### Handling events
|
||||||
|
|
||||||
|
@ -126,63 +175,23 @@ calling backend library methods directly. See the [Handling Events] section of t
|
||||||
Website] for more info. For example, if you are using [Crossterm], you can use the
|
Website] for more info. For example, if you are using [Crossterm], you can use the
|
||||||
[`crossterm::event`] module to handle events.
|
[`crossterm::event`] module to handle events.
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::io::{self, stdout};
|
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
|
||||||
|
|
||||||
use ratatui::{
|
fn handle_events() -> std::io::Result<bool> {
|
||||||
backend::CrosstermBackend,
|
match event::read()? {
|
||||||
crossterm::{
|
Event::Key(key) if key.kind == KeyEventKind::Press => match key.code {
|
||||||
event::{self, Event, KeyCode},
|
KeyCode::Char('q') => return Ok(true),
|
||||||
terminal::{
|
// handle other key events
|
||||||
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
|
_ => {}
|
||||||
},
|
},
|
||||||
ExecutableCommand,
|
// handle other events
|
||||||
},
|
_ => {}
|
||||||
widgets::{Block, Paragraph},
|
|
||||||
Frame, Terminal,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
|
||||||
enable_raw_mode()?;
|
|
||||||
stdout().execute(EnterAlternateScreen)?;
|
|
||||||
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
|
|
||||||
|
|
||||||
let mut should_quit = false;
|
|
||||||
while !should_quit {
|
|
||||||
terminal.draw(ui)?;
|
|
||||||
should_quit = handle_events()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
disable_raw_mode()?;
|
|
||||||
stdout().execute(LeaveAlternateScreen)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_events() -> io::Result<bool> {
|
|
||||||
if event::poll(std::time::Duration::from_millis(50))? {
|
|
||||||
if let Event::Key(key) = event::read()? {
|
|
||||||
if key.kind == event::KeyEventKind::Press && key.code == KeyCode::Char('q') {
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui(frame: &mut Frame) {
|
|
||||||
frame.render_widget(
|
|
||||||
Paragraph::new("Hello World!").block(Block::bordered().title("Greeting")),
|
|
||||||
frame.area(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Running this example produces the following output:
|
|
||||||
|
|
||||||
![docsrs-hello]
|
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
The library comes with a basic yet useful layout management object called [`Layout`] which
|
The library comes with a basic yet useful layout management object called [`Layout`] which
|
||||||
|
@ -197,16 +206,13 @@ use ratatui::{
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn ui(frame: &mut Frame) {
|
fn draw(frame: &mut Frame) {
|
||||||
let [title_area, main_area, status_area] = Layout::vertical([
|
use Constraint::{Fill, Length, Min};
|
||||||
Constraint::Length(1),
|
|
||||||
Constraint::Min(0),
|
let vertical = Layout::vertical([Length(1), Min(0),Length(1)]);
|
||||||
Constraint::Length(1),
|
let [title_area, main_area, status_area] = vertical.areas(frame.area());
|
||||||
])
|
let horizontal = Layout::horizontal([Fill(1); 2]);
|
||||||
.areas(frame.area());
|
let [left_area, right_area] = horizontal.areas(main_area);
|
||||||
let [left_area, right_area] =
|
|
||||||
Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)])
|
|
||||||
.areas(main_area);
|
|
||||||
|
|
||||||
frame.render_widget(Block::bordered().title("Title Bar"), title_area);
|
frame.render_widget(Block::bordered().title("Title Bar"), title_area);
|
||||||
frame.render_widget(Block::bordered().title("Status Bar"), status_area);
|
frame.render_widget(Block::bordered().title("Status Bar"), status_area);
|
||||||
|
@ -217,7 +223,13 @@ fn ui(frame: &mut Frame) {
|
||||||
|
|
||||||
Running this example produces the following output:
|
Running this example produces the following output:
|
||||||
|
|
||||||
![docsrs-layout]
|
```text
|
||||||
|
Title Bar───────────────────────────────────
|
||||||
|
┌Left────────────────┐┌Right───────────────┐
|
||||||
|
│ ││ │
|
||||||
|
└────────────────────┘└────────────────────┘
|
||||||
|
Status Bar──────────────────────────────────
|
||||||
|
```
|
||||||
|
|
||||||
## Text and styling
|
## Text and styling
|
||||||
|
|
||||||
|
@ -240,7 +252,7 @@ use ratatui::{
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn ui(frame: &mut Frame) {
|
fn draw(frame: &mut Frame) {
|
||||||
let areas = Layout::vertical([Constraint::Length(1); 4]).split(frame.area());
|
let areas = Layout::vertical([Constraint::Length(1); 4]).split(frame.area());
|
||||||
|
|
||||||
let line = Line::from(vec![
|
let line = Line::from(vec![
|
||||||
|
@ -270,10 +282,6 @@ fn ui(frame: &mut Frame) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Running this example produces the following output:
|
|
||||||
|
|
||||||
![docsrs-styling]
|
|
||||||
|
|
||||||
[Ratatui Website]: https://ratatui.rs/
|
[Ratatui Website]: https://ratatui.rs/
|
||||||
[Installation]: https://ratatui.rs/installation/
|
[Installation]: https://ratatui.rs/installation/
|
||||||
[Rendering]: https://ratatui.rs/concepts/rendering/
|
[Rendering]: https://ratatui.rs/concepts/rendering/
|
||||||
|
@ -296,9 +304,6 @@ Running this example produces the following output:
|
||||||
[Contributing]: https://github.com/ratatui/ratatui/blob/main/CONTRIBUTING.md
|
[Contributing]: https://github.com/ratatui/ratatui/blob/main/CONTRIBUTING.md
|
||||||
[Breaking Changes]: https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md
|
[Breaking Changes]: https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md
|
||||||
[FOSDEM 2024 talk]: https://www.youtube.com/watch?v=NU0q6NOLJ20
|
[FOSDEM 2024 talk]: https://www.youtube.com/watch?v=NU0q6NOLJ20
|
||||||
[docsrs-hello]: https://github.com/ratatui/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-hello.png?raw=true
|
|
||||||
[docsrs-layout]: https://github.com/ratatui/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-layout.png?raw=true
|
|
||||||
[docsrs-styling]: https://github.com/ratatui/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-styling.png?raw=true
|
|
||||||
[`Frame`]: terminal::Frame
|
[`Frame`]: terminal::Frame
|
||||||
[`render_widget`]: terminal::Frame::render_widget
|
[`render_widget`]: terminal::Frame::render_widget
|
||||||
[`Widget`]: widgets::Widget
|
[`Widget`]: widgets::Widget
|
||||||
|
|
|
@ -14,4 +14,5 @@ allowed-duplicate-crates = [
|
||||||
"windows_x86_64_gnu",
|
"windows_x86_64_gnu",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm",
|
||||||
"windows_x86_64_msvc",
|
"windows_x86_64_msvc",
|
||||||
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
|
@ -20,21 +20,21 @@
|
||||||
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
|
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
|
||||||
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
|
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
|
||||||
|
|
||||||
use ratatui::{
|
use crossterm::event::{self, Event};
|
||||||
crossterm::event::{self, Event},
|
use ratatui::{text::Text, Frame};
|
||||||
text::Text,
|
|
||||||
Frame,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut terminal = ratatui::init();
|
let mut terminal = ratatui::init();
|
||||||
loop {
|
loop {
|
||||||
terminal
|
terminal.draw(draw).expect("failed to draw frame");
|
||||||
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
|
|
||||||
.expect("failed to draw frame");
|
|
||||||
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
|
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ratatui::restore();
|
ratatui::restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw(frame: &mut Frame) {
|
||||||
|
let text = Text::raw("Hello World!");
|
||||||
|
frame.render_widget(text, frame.area());
|
||||||
|
}
|
||||||
|
|
201
src/lib.rs
201
src/lib.rs
|
@ -18,28 +18,42 @@
|
||||||
//! lightweight library that provides a set of widgets and utilities to build complex Rust TUIs.
|
//! lightweight library that provides a set of widgets and utilities to build complex Rust TUIs.
|
||||||
//! Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development.
|
//! Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development.
|
||||||
//!
|
//!
|
||||||
//! ## Installation
|
//! ## Quickstart
|
||||||
//!
|
//!
|
||||||
//! Add `ratatui` as a dependency to your cargo.toml:
|
//! Add `ratatui` and `crossterm` as dependencies to your cargo.toml:
|
||||||
//!
|
//!
|
||||||
//! ```shell
|
//! ```shell
|
||||||
//! cargo add ratatui
|
//! cargo add ratatui crossterm
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Ratatui uses [Crossterm] by default as it works on most platforms. See the [Installation]
|
//! Then you can create a simple "Hello World" application:
|
||||||
//! section of the [Ratatui Website] for more details on how to use other backends ([Termion] /
|
|
||||||
//! [Termwiz]).
|
|
||||||
//!
|
//!
|
||||||
//! ## Introduction
|
//! ```rust,no_run
|
||||||
|
//! use crossterm::event::{self, Event};
|
||||||
|
//! use ratatui::{text::Text, Frame};
|
||||||
//!
|
//!
|
||||||
//! Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
|
//! fn main() {
|
||||||
//! that for each frame, your app must render all widgets that are supposed to be part of the UI.
|
//! let mut terminal = ratatui::init();
|
||||||
//! This is in contrast to the retained mode style of rendering where widgets are updated and then
|
//! loop {
|
||||||
//! automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
|
//! terminal.draw(draw).expect("failed to draw frame");
|
||||||
//! for more info.
|
//! if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
|
||||||
|
//! break;
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! ratatui::restore();
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! You can also watch the [FOSDEM 2024 talk] about Ratatui which gives a brief introduction to
|
//! fn draw(frame: &mut Frame) {
|
||||||
//! terminal user interfaces and showcases the features of Ratatui, along with a hello world demo.
|
//! let text = Text::raw("Hello World!");
|
||||||
|
//! frame.render_widget(text, frame.area());
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! The full code for this example which contains a little more detail is in the [Examples]
|
||||||
|
//! directory. For more guidance on different ways to structure your application see the
|
||||||
|
//! [Application Patterns] and [Hello World tutorial] sections in the [Ratatui Website] and the
|
||||||
|
//! various [Examples]. There are also several starter templates available in the [templates]
|
||||||
|
//! repository.
|
||||||
//!
|
//!
|
||||||
//! ## Other documentation
|
//! ## Other documentation
|
||||||
//!
|
//!
|
||||||
|
@ -51,46 +65,84 @@
|
||||||
//! - [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
|
//! - [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
|
||||||
//! - [Breaking Changes] - a list of breaking changes in the library.
|
//! - [Breaking Changes] - a list of breaking changes in the library.
|
||||||
//!
|
//!
|
||||||
//! ## Quickstart
|
//! You can also watch the [FOSDEM 2024 talk] about Ratatui which gives a brief introduction to
|
||||||
|
//! terminal user interfaces and showcases the features of Ratatui, along with a hello world demo.
|
||||||
//!
|
//!
|
||||||
//! The following example demonstrates the minimal amount of code necessary to setup a terminal and
|
//! ## Introduction
|
||||||
//! render "Hello World!". The full code for this example which contains a little more detail is in
|
//!
|
||||||
//! the [Examples] directory. For more guidance on different ways to structure your application see
|
//! Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
|
||||||
//! the [Application Patterns] and [Hello World tutorial] sections in the [Ratatui Website] and the
|
//! that for each frame, your app must render all widgets that are supposed to be part of the UI.
|
||||||
//! various [Examples]. There are also several starter templates available in the [templates]
|
//! This is in contrast to the retained mode style of rendering where widgets are updated and then
|
||||||
//! repository.
|
//! automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
|
||||||
|
//! for more info.
|
||||||
|
//!
|
||||||
|
//! Ratatui uses [Crossterm] by default as it works on most platforms. See the [Installation]
|
||||||
|
//! section of the [Ratatui Website] for more details on how to use other backends ([Termion] /
|
||||||
|
//! [Termwiz]).
|
||||||
//!
|
//!
|
||||||
//! Every application built with `ratatui` needs to implement the following steps:
|
//! Every application built with `ratatui` needs to implement the following steps:
|
||||||
//!
|
//!
|
||||||
//! - Initialize the terminal
|
//! - Initialize the terminal
|
||||||
//! - A main loop to:
|
//! - A main loop that:
|
||||||
//! - Handle input events
|
//! - Draws the UI
|
||||||
//! - Draw the UI
|
//! - Handles input events
|
||||||
//! - Restore the terminal state
|
//! - Restore the terminal state
|
||||||
//!
|
//!
|
||||||
//! The library contains a [`prelude`] module that re-exports the most commonly used traits and
|
|
||||||
//! types for convenience. Most examples in the documentation will use this instead of showing the
|
|
||||||
//! full path of each type.
|
|
||||||
//!
|
|
||||||
//! ### Initialize and restore the terminal
|
//! ### Initialize and restore the terminal
|
||||||
//!
|
//!
|
||||||
//! The [`Terminal`] type is the main entry point for any Ratatui application. It is a light
|
//! The [`Terminal`] type is the main entry point for any Ratatui application. It is generic over a
|
||||||
//! abstraction over a choice of [`Backend`] implementations that provides functionality to draw
|
//! a choice of [`Backend`] implementations that each provide functionality to draw frames, clear
|
||||||
//! each frame, clear the screen, hide the cursor, etc. It is parametrized over any type that
|
//! the screen, hide the cursor, etc. There are backend implementations for [Crossterm], [Termion]
|
||||||
//! implements the [`Backend`] trait which has implementations for [Crossterm], [Termion] and
|
//! and [Termwiz].
|
||||||
//! [Termwiz].
|
|
||||||
//!
|
//!
|
||||||
//! Most applications should enter the Alternate Screen when starting and leave it when exiting and
|
//! The simplest way to initialize the terminal is to use the [`init`] function which returns a
|
||||||
//! also enable raw mode to disable line buffering and enable reading key events. See the [`backend`
|
//! [`DefaultTerminal`] instance with the default options, enters the Alternate Screen and Raw mode
|
||||||
//! module] and the [Backends] section of the [Ratatui Website] for more info.
|
//! and sets up a panic hook that restores the terminal in case of panic. This instance can then be
|
||||||
|
//! used to draw frames and interact with the terminal state. (The [`DefaultTerminal`] instance is a
|
||||||
|
//! type alias for a terminal with the [`crossterm`] backend.) The [`restore`] function restores the
|
||||||
|
//! terminal to its original state.
|
||||||
|
//!
|
||||||
|
//! ```rust,no_run
|
||||||
|
//! fn main() -> std::io::Result<()> {
|
||||||
|
//! let mut terminal = ratatui::init();
|
||||||
|
//! let result = run(&mut terminal);
|
||||||
|
//! ratatui::restore();
|
||||||
|
//! result
|
||||||
|
//! }
|
||||||
|
//! # fn run(terminal: &mut ratatui::DefaultTerminal) -> std::io::Result<()> { Ok(()) }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! See the [`backend` module] and the [Backends] section of the [Ratatui Website] for more info on
|
||||||
|
//! the alternate screen and raw mode.
|
||||||
//!
|
//!
|
||||||
//! ### Drawing the UI
|
//! ### Drawing the UI
|
||||||
//!
|
//!
|
||||||
//! The drawing logic is delegated to a closure that takes a [`Frame`] instance as argument. The
|
//! Drawing the UI is done by calling the [`Terminal::draw`] method on the terminal instance. This
|
||||||
//! [`Frame`] provides the size of the area to draw to and allows the app to render any [`Widget`]
|
//! method takes a closure that is called with a [`Frame`] instance. The [`Frame`] provides the size
|
||||||
//! using the provided [`render_widget`] method. After this closure returns, a diff is performed and
|
//! of the area to draw to and allows the app to render any [`Widget`] using the provided
|
||||||
//! only the changes are drawn to the terminal. See the [Widgets] section of the [Ratatui Website]
|
//! [`render_widget`] method. After this closure returns, a diff is performed and only the changes
|
||||||
//! for more info.
|
//! are drawn to the terminal. See the [Widgets] section of the [Ratatui Website] for more info.
|
||||||
|
//!
|
||||||
|
//! The closure passed to the [`Terminal::draw`] method should handle the rendering of a full frame.
|
||||||
|
//!
|
||||||
|
//! ```rust,no_run
|
||||||
|
//! use ratatui::{widgets::Paragraph, Frame};
|
||||||
|
//!
|
||||||
|
//! fn run(terminal: &mut ratatui::DefaultTerminal) -> std::io::Result<()> {
|
||||||
|
//! loop {
|
||||||
|
//! terminal.draw(|frame| draw(frame))?;
|
||||||
|
//! if handle_events()? {
|
||||||
|
//! break Ok(());
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn draw(frame: &mut Frame) {
|
||||||
|
//! let text = Paragraph::new("Hello World!");
|
||||||
|
//! frame.render_widget(text, frame.area());
|
||||||
|
//! }
|
||||||
|
//! # fn handle_events() -> std::io::Result<bool> { Ok(false) }
|
||||||
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ### Handling events
|
//! ### Handling events
|
||||||
//!
|
//!
|
||||||
|
@ -99,38 +151,23 @@
|
||||||
//! Website] for more info. For example, if you are using [Crossterm], you can use the
|
//! Website] for more info. For example, if you are using [Crossterm], you can use the
|
||||||
//! [`crossterm::event`] module to handle events.
|
//! [`crossterm::event`] module to handle events.
|
||||||
//!
|
//!
|
||||||
//! ### Example
|
|
||||||
//!
|
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! use ratatui::{
|
//! use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
|
||||||
//! crossterm::event::{self, Event, KeyCode, KeyEventKind},
|
|
||||||
//! widgets::{Block, Paragraph},
|
|
||||||
//! };
|
|
||||||
//!
|
//!
|
||||||
//! fn main() -> std::io::Result<()> {
|
//! fn handle_events() -> std::io::Result<bool> {
|
||||||
//! let mut terminal = ratatui::init();
|
//! match event::read()? {
|
||||||
//! loop {
|
//! Event::Key(key) if key.kind == KeyEventKind::Press => match key.code {
|
||||||
//! terminal.draw(|frame| {
|
//! KeyCode::Char('q') => return Ok(true),
|
||||||
//! frame.render_widget(
|
//! // handle other key events
|
||||||
//! Paragraph::new("Hello World!").block(Block::bordered().title("Greeting")),
|
//! _ => {}
|
||||||
//! frame.area(),
|
//! },
|
||||||
//! );
|
//! // handle other events
|
||||||
//! })?;
|
//! _ => {}
|
||||||
//! if let Event::Key(key) = event::read()? {
|
|
||||||
//! if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
|
|
||||||
//! break;
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! }
|
//! }
|
||||||
//! ratatui::restore();
|
//! Ok(false)
|
||||||
//! Ok(())
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Running this example produces the following output:
|
|
||||||
//!
|
|
||||||
//! ![docsrs-hello]
|
|
||||||
//!
|
|
||||||
//! ## Layout
|
//! ## Layout
|
||||||
//!
|
//!
|
||||||
//! The library comes with a basic yet useful layout management object called [`Layout`] which
|
//! The library comes with a basic yet useful layout management object called [`Layout`] which
|
||||||
|
@ -146,15 +183,12 @@
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! fn draw(frame: &mut Frame) {
|
//! fn draw(frame: &mut Frame) {
|
||||||
//! let [title_area, main_area, status_area] = Layout::vertical([
|
//! use Constraint::{Fill, Length, Min};
|
||||||
//! Constraint::Length(1),
|
//!
|
||||||
//! Constraint::Min(0),
|
//! let vertical = Layout::vertical([Length(1), Min(0), Length(1)]);
|
||||||
//! Constraint::Length(1),
|
//! let [title_area, main_area, status_area] = vertical.areas(frame.area());
|
||||||
//! ])
|
//! let horizontal = Layout::horizontal([Fill(1); 2]);
|
||||||
//! .areas(frame.area());
|
//! let [left_area, right_area] = horizontal.areas(main_area);
|
||||||
//! let [left_area, right_area] =
|
|
||||||
//! Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)])
|
|
||||||
//! .areas(main_area);
|
|
||||||
//!
|
//!
|
||||||
//! frame.render_widget(Block::bordered().title("Title Bar"), title_area);
|
//! frame.render_widget(Block::bordered().title("Title Bar"), title_area);
|
||||||
//! frame.render_widget(Block::bordered().title("Status Bar"), status_area);
|
//! frame.render_widget(Block::bordered().title("Status Bar"), status_area);
|
||||||
|
@ -165,7 +199,13 @@
|
||||||
//!
|
//!
|
||||||
//! Running this example produces the following output:
|
//! Running this example produces the following output:
|
||||||
//!
|
//!
|
||||||
//! ![docsrs-layout]
|
//! ```text
|
||||||
|
//! Title Bar───────────────────────────────────
|
||||||
|
//! ┌Left────────────────┐┌Right───────────────┐
|
||||||
|
//! │ ││ │
|
||||||
|
//! └────────────────────┘└────────────────────┘
|
||||||
|
//! Status Bar──────────────────────────────────
|
||||||
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Text and styling
|
//! ## Text and styling
|
||||||
//!
|
//!
|
||||||
|
@ -217,10 +257,6 @@
|
||||||
//! frame.render_widget(paragraph, areas[3]);
|
//! frame.render_widget(paragraph, areas[3]);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
|
||||||
//! Running this example produces the following output:
|
|
||||||
//!
|
|
||||||
//! ![docsrs-styling]
|
|
||||||
#![cfg_attr(feature = "document-features", doc = "\n## Features")]
|
#![cfg_attr(feature = "document-features", doc = "\n## Features")]
|
||||||
#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
|
#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
|
||||||
//!
|
//!
|
||||||
|
@ -246,9 +282,6 @@
|
||||||
//! [Contributing]: https://github.com/ratatui/ratatui/blob/main/CONTRIBUTING.md
|
//! [Contributing]: https://github.com/ratatui/ratatui/blob/main/CONTRIBUTING.md
|
||||||
//! [Breaking Changes]: https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md
|
//! [Breaking Changes]: https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md
|
||||||
//! [FOSDEM 2024 talk]: https://www.youtube.com/watch?v=NU0q6NOLJ20
|
//! [FOSDEM 2024 talk]: https://www.youtube.com/watch?v=NU0q6NOLJ20
|
||||||
//! [docsrs-hello]: https://github.com/ratatui/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-hello.png?raw=true
|
|
||||||
//! [docsrs-layout]: https://github.com/ratatui/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-layout.png?raw=true
|
|
||||||
//! [docsrs-styling]: https://github.com/ratatui/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-styling.png?raw=true
|
|
||||||
//! [`Frame`]: terminal::Frame
|
//! [`Frame`]: terminal::Frame
|
||||||
//! [`render_widget`]: terminal::Frame::render_widget
|
//! [`render_widget`]: terminal::Frame::render_widget
|
||||||
//! [`Widget`]: widgets::Widget
|
//! [`Widget`]: widgets::Widget
|
||||||
|
|
Loading…
Reference in a new issue