mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-26 22:50:47 +00:00
910ad00059
This enables more consistently formatted code in doc comments, especially since ratatui heavily uses fluent setters. See https://rust-lang.github.io/rustfmt/?version=v1.6.0#format_code_in_doc_comments
363 lines
15 KiB
Rust
363 lines
15 KiB
Rust
#![forbid(unsafe_code)]
|
|
|
|
//! ![Demo](https://raw.githubusercontent.com/ratatui-org/ratatui/b33c878808c4c40591d7a2d9f9d94d6fee95a96f/examples/demo2.gif)
|
|
//!
|
|
//! <div align="center">
|
|
//!
|
|
//! [![Crate Badge]](https://crates.io/crates/ratatui)
|
|
//! [![License Badge]](./LICENSE)
|
|
//! [![CI Badge]](https://github.com/ratatui-org/ratatui/actions?query=workflow%3ACI+)
|
|
//! [![Docs Badge]](https://docs.rs/crate/ratatui/)<br>
|
|
//! [![Dependencies Badge]](https://deps.rs/repo/github/ratatui-org/ratatui)
|
|
//! [![Codecov Badge]](https://app.codecov.io/gh/ratatui-org/ratatui)
|
|
//! [![Discord Badge]](https://discord.gg/pMCEU9hNEj)
|
|
//! [![Matrix Badge]](https://matrix.to/#/#ratatui:matrix.org)<br>
|
|
//!
|
|
//! [Documentation](https://docs.rs/ratatui)
|
|
//! · [Ratatui Website](https://ratatui.rs)
|
|
//! · [Examples](https://github.com/ratatui-org/ratatui/tree/main/examples)
|
|
//! · [Report a bug](https://github.com/ratatui-org/ratatui/issues/new?labels=bug&projects=&template=bug_report.md)
|
|
//! · [Request a Feature](https://github.com/ratatui-org/ratatui/issues/new?labels=enhancement&projects=&template=feature_request.md)
|
|
//! · [Send a Pull Request](https://github.com/ratatui-org/ratatui/compare)
|
|
//!
|
|
//! </div>
|
|
//!
|
|
//! # Ratatui
|
|
//!
|
|
//! [Ratatui] is a crate for cooking up terminal user interfaces in Rust. It is a 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.
|
|
//!
|
|
//! ## Installation
|
|
//!
|
|
//! Add `ratatui` and `crossterm` as dependencies to your cargo.toml:
|
|
//!
|
|
//! ```shell
|
|
//! cargo add ratatui crossterm
|
|
//! ```
|
|
//!
|
|
//! 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]).
|
|
//!
|
|
//! ## Introduction
|
|
//!
|
|
//! Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
|
|
//! that for each frame, your app must render all widgets that are supposed to be part of the UI.
|
|
//! This is in contrast to the retained mode style of rendering where widgets are updated and then
|
|
//! automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
|
|
//! for more info.
|
|
//!
|
|
//! ## Other documentation
|
|
//!
|
|
//! - [Ratatui Website] - explains the library's concepts and provides step-by-step tutorials
|
|
//! - [Examples] - a collection of examples that demonstrate how to use the library.
|
|
//! - [API Documentation] - the full API documentation for the library on docs.rs.
|
|
//! - [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
|
|
//! - [Contributing] - Please read this if you are interested in contributing to the project.
|
|
//! - [Breaking Changes] - a list of breaking changes in the library.
|
|
//!
|
|
//! ## 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]. 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:
|
|
//!
|
|
//! - [template]
|
|
//! - [async-template] (book and template)
|
|
//!
|
|
//! Every application built with `ratatui` needs to implement the following steps:
|
|
//!
|
|
//! - Initialize the terminal
|
|
//! - A main loop to:
|
|
//! - Handle input events
|
|
//! - Draw the UI
|
|
//! - 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
|
|
//!
|
|
//! The [`Terminal`] type is the main entry point for any Ratatui application. It is a light
|
|
//! abstraction over a choice of [`Backend`] implementations that provides functionality to draw
|
|
//! each frame, clear the screen, hide the cursor, etc. It is parametrized over any type that
|
|
//! implements the [`Backend`] trait which has implementations for [Crossterm], [Termion] and
|
|
//! [Termwiz].
|
|
//!
|
|
//! Most applications should enter the Alternate Screen when starting and leave it when exiting and
|
|
//! also enable raw mode to disable line buffering and enable reading key events. See the [`backend`
|
|
//! module] and the [Backends] section of the [Ratatui Website] for more info.
|
|
//!
|
|
//! ### Drawing the UI
|
|
//!
|
|
//! The drawing logic is delegated to a closure that takes a [`Frame`] instance as argument. The
|
|
//! [`Frame`] provides the size of the area to draw to and allows the app to render any [`Widget`]
|
|
//! using the provided [`render_widget`] method. See the [Widgets] section of the [Ratatui Website]
|
|
//! for more info.
|
|
//!
|
|
//! ### Handling events
|
|
//!
|
|
//! Ratatui does not include any input handling. Instead event handling can be implemented by
|
|
//! calling backend library methods directly. See the [Handling Events] section of the [Ratatui
|
|
//! Website] for more info. For example, if you are using [Crossterm], you can use the
|
|
//! [`crossterm::event`] module to handle events.
|
|
//!
|
|
//! ### Example
|
|
//!
|
|
//! ```rust,no_run
|
|
//! use std::io::{self, stdout};
|
|
//!
|
|
//! use crossterm::{
|
|
//! event::{self, Event, KeyCode},
|
|
//! terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
|
//! ExecutableCommand,
|
|
//! };
|
|
//! use ratatui::{prelude::*, widgets::*};
|
|
//!
|
|
//! 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)
|
|
//! }
|
|
//!
|
|
//! fn ui(frame: &mut Frame) {
|
|
//! frame.render_widget(
|
|
//! Paragraph::new("Hello World!")
|
|
//! .block(Block::default().title("Greeting").borders(Borders::ALL)),
|
|
//! frame.size(),
|
|
//! );
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! Running this example produces the following output:
|
|
//!
|
|
//! ![docsrs-hello]
|
|
//!
|
|
//! ## Layout
|
|
//!
|
|
//! The library comes with a basic yet useful layout management object called [`Layout`] which
|
|
//! allows you to split the available space into multiple areas and then render widgets in each
|
|
//! area. This lets you describe a responsive terminal UI by nesting layouts. See the [Layout]
|
|
//! section of the [Ratatui Website] for more info.
|
|
//!
|
|
//! ```rust,no_run
|
|
//! use ratatui::{prelude::*, widgets::*};
|
|
//!
|
|
//! fn ui(frame: &mut Frame) {
|
|
//! let main_layout = Layout::new(
|
|
//! Direction::Vertical,
|
|
//! [
|
|
//! Constraint::Length(1),
|
|
//! Constraint::Min(0),
|
|
//! Constraint::Length(1),
|
|
//! ],
|
|
//! )
|
|
//! .split(frame.size());
|
|
//! frame.render_widget(
|
|
//! Block::new().borders(Borders::TOP).title("Title Bar"),
|
|
//! main_layout[0],
|
|
//! );
|
|
//! frame.render_widget(
|
|
//! Block::new().borders(Borders::TOP).title("Status Bar"),
|
|
//! main_layout[2],
|
|
//! );
|
|
//!
|
|
//! let inner_layout = Layout::new(
|
|
//! Direction::Horizontal,
|
|
//! [Constraint::Percentage(50), Constraint::Percentage(50)],
|
|
//! )
|
|
//! .split(main_layout[1]);
|
|
//! frame.render_widget(
|
|
//! Block::default().borders(Borders::ALL).title("Left"),
|
|
//! inner_layout[0],
|
|
//! );
|
|
//! frame.render_widget(
|
|
//! Block::default().borders(Borders::ALL).title("Right"),
|
|
//! inner_layout[1],
|
|
//! );
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! Running this example produces the following output:
|
|
//!
|
|
//! ![docsrs-layout]
|
|
//!
|
|
//! ## Text and styling
|
|
//!
|
|
//! The [`Text`], [`Line`] and [`Span`] types are the building blocks of the library and are used in
|
|
//! many places. [`Text`] is a list of [`Line`]s and a [`Line`] is a list of [`Span`]s. A [`Span`]
|
|
//! is a string with a specific style.
|
|
//!
|
|
//! The [`style` module] provides types that represent the various styling options. The most
|
|
//! important one is [`Style`] which represents the foreground and background colors and the text
|
|
//! attributes of a [`Span`]. The [`style` module] also provides a [`Stylize`] trait that allows
|
|
//! short-hand syntax to apply a style to widgets and text. See the [Styling Text] section of the
|
|
//! [Ratatui Website] for more info.
|
|
//!
|
|
//! ```rust,no_run
|
|
//! use ratatui::{prelude::*, widgets::*};
|
|
//!
|
|
//! fn ui(frame: &mut Frame) {
|
|
//! let areas = Layout::new(
|
|
//! Direction::Vertical,
|
|
//! [
|
|
//! Constraint::Length(1),
|
|
//! Constraint::Length(1),
|
|
//! Constraint::Length(1),
|
|
//! Constraint::Length(1),
|
|
//! Constraint::Min(0),
|
|
//! ],
|
|
//! )
|
|
//! .split(frame.size());
|
|
//!
|
|
//! let span1 = Span::raw("Hello ");
|
|
//! let span2 = Span::styled(
|
|
//! "World",
|
|
//! Style::new()
|
|
//! .fg(Color::Green)
|
|
//! .bg(Color::White)
|
|
//! .add_modifier(Modifier::BOLD),
|
|
//! );
|
|
//! let span3 = "!".red().on_light_yellow().italic();
|
|
//!
|
|
//! let line = Line::from(vec![span1, span2, span3]);
|
|
//! let text: Text = Text::from(vec![line]);
|
|
//!
|
|
//! frame.render_widget(Paragraph::new(text), areas[0]);
|
|
//! // or using the short-hand syntax and implicit conversions
|
|
//! frame.render_widget(
|
|
//! Paragraph::new("Hello World!".red().on_white().bold()),
|
|
//! areas[1],
|
|
//! );
|
|
//!
|
|
//! // to style the whole widget instead of just the text
|
|
//! frame.render_widget(
|
|
//! Paragraph::new("Hello World!").style(Style::new().red().on_white()),
|
|
//! areas[2],
|
|
//! );
|
|
//! // or using the short-hand syntax
|
|
//! frame.render_widget(Paragraph::new("Hello World!").blue().on_yellow(), 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 = document_features::document_features!())]
|
|
#![cfg_attr(
|
|
feature = "document-features",
|
|
doc = "[`CrossTermBackend`]: backend::CrosstermBackend"
|
|
)]
|
|
#![cfg_attr(
|
|
feature = "document-features",
|
|
doc = "[`TermionBackend`]: backend::TermionBackend"
|
|
)]
|
|
#![cfg_attr(
|
|
feature = "document-features",
|
|
doc = "[`TermwizBackend`]: backend::TermwizBackend"
|
|
)]
|
|
#![cfg_attr(
|
|
feature = "document-features",
|
|
doc = "[`calendar`]: widgets::calendar::Monthly"
|
|
)]
|
|
//!
|
|
//! [Ratatui Website]: https://ratatui.rs/
|
|
//! [Installation]: https://ratatui.rs/installation/
|
|
//! [Rendering]: https://ratatui.rs/concepts/rendering/
|
|
//! [Application Patterns]: https://ratatui.rs/concepts/application-patterns/
|
|
//! [Hello World tutorial]: https://ratatui.rs/tutorials/hello-world/
|
|
//! [Backends]: https://ratatui.rs/concepts/backends/
|
|
//! [Widgets]: https://ratatui.rs/how-to/widgets/
|
|
//! [Handling Events]: https://ratatui.rs/concepts/event-handling/
|
|
//! [Layout]: https://ratatui.rs/how-to/layout/
|
|
//! [Styling Text]: https://ratatui.rs/how-to/render/style-text/
|
|
//! [template]: https://github.com/ratatui-org/template
|
|
//! [async-template]: https://ratatui-org.github.io/async-template
|
|
//! [Examples]: https://github.com/ratatui-org/ratatui/tree/main/examples
|
|
//! [git-cliff]: https://git-cliff.org
|
|
//! [Conventional Commits]: https://www.conventionalcommits.org
|
|
//! [API Documentation]: https://docs.rs/ratatui
|
|
//! [Changelog]: https://github.com/ratatui-org/ratatui/blob/main/CHANGELOG.md
|
|
//! [Contributing]: https://github.com/ratatui-org/ratatui/blob/main/CONTRIBUTING.md
|
|
//! [Breaking Changes]: https://github.com/ratatui-org/ratatui/blob/main/BREAKING-CHANGES.md
|
|
//! [docsrs-hello]: https://github.com/ratatui-org/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-hello.png?raw=true
|
|
//! [docsrs-layout]: https://github.com/ratatui-org/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-layout.png?raw=true
|
|
//! [docsrs-styling]: https://github.com/ratatui-org/ratatui/blob/c3c3c289b1eb8d562afb1931adb4dc719cd48490/examples/docsrs-styling.png?raw=true
|
|
//! [`Frame`]: terminal::Frame
|
|
//! [`render_widget`]: terminal::Frame::render_widget
|
|
//! [`Widget`]: widgets::Widget
|
|
//! [`Layout`]: layout::Layout
|
|
//! [`Text`]: text::Text
|
|
//! [`Line`]: text::Line
|
|
//! [`Span`]: text::Span
|
|
//! [`Style`]: style::Style
|
|
//! [`style` module]: style
|
|
//! [`Stylize`]: style::Stylize
|
|
//! [`Backend`]: backend::Backend
|
|
//! [`backend` module]: backend
|
|
//! [`crossterm::event`]: https://docs.rs/crossterm/latest/crossterm/event/index.html
|
|
//! [Ratatui]: https://ratatui.rs
|
|
//! [Crossterm]: https://crates.io/crates/crossterm
|
|
//! [Termion]: https://crates.io/crates/termion
|
|
//! [Termwiz]: https://crates.io/crates/termwiz
|
|
//! [tui-rs]: https://crates.io/crates/tui
|
|
//! [hello_world.rs]: https://github.com/ratatui-org/ratatui/blob/main/examples/hello_world.rs
|
|
//! [Crate Badge]: https://img.shields.io/crates/v/ratatui?logo=rust&style=flat-square
|
|
//! [CI Badge]:
|
|
//! https://img.shields.io/github/actions/workflow/status/ratatui-org/ratatui/ci.yml?style=flat-square&logo=github
|
|
//! [Codecov Badge]:
|
|
//! https://img.shields.io/codecov/c/github/ratatui-org/ratatui?logo=codecov&style=flat-square&token=BAQ8SOKEST
|
|
//! [Dependencies Badge]: https://deps.rs/repo/github/ratatui-org/ratatui/status.svg?style=flat-square
|
|
//! [Discord Badge]:
|
|
//! https://img.shields.io/discord/1070692720437383208?label=discord&logo=discord&style=flat-square
|
|
//! [Docs Badge]: https://img.shields.io/docsrs/ratatui?logo=rust&style=flat-square
|
|
//! [License Badge]: https://img.shields.io/crates/l/ratatui?style=flat-square
|
|
//! [Matrix Badge]:
|
|
//! https://img.shields.io/matrix/ratatui-general%3Amatrix.org?style=flat-square&logo=matrix&label=Matrix
|
|
|
|
// show the feature flags in the generated documentation
|
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
|
#![doc(
|
|
html_logo_url = "https://raw.githubusercontent.com/ratatui-org/ratatui/main/assets/logo.png",
|
|
html_favicon_url = "https://raw.githubusercontent.com/ratatui-org/ratatui/main/assets/favicon.ico"
|
|
)]
|
|
|
|
pub mod backend;
|
|
pub mod buffer;
|
|
pub mod layout;
|
|
pub mod style;
|
|
pub mod symbols;
|
|
pub mod terminal;
|
|
pub mod text;
|
|
pub mod widgets;
|
|
|
|
#[doc(inline)]
|
|
pub use self::terminal::{CompletedFrame, Frame, Terminal, TerminalOptions, Viewport};
|
|
|
|
pub mod prelude;
|