ratatui/src/lib.rs
2024-06-17 17:53:32 +03:00

354 lines
15 KiB
Rust

//! ![Demo](https://github.com/ratatui-org/ratatui/blob/1d39444e3dea6f309cf9035be2417ac711c1abc9/examples/demo2-destroy.gif?raw=true)
//!
//! <div align="center">
//!
//! [![Crate Badge]][Crate] [![Docs Badge]][API Docs] [![CI Badge]][CI Workflow] [![Deps.rs
//! Badge]][Deps.rs]<br> [![Codecov Badge]][Codecov] [![License Badge]](./LICENSE) [![Sponsors
//! Badge]][GitHub Sponsors]<br> [![Discord Badge]][Discord Server] [![Matrix Badge]][Matrix]
//! [![Forum Badge]][Forum]<br>
//!
//! [Ratatui Website] · [API Docs] · [Examples] · [Changelog] · [Breaking Changes]<br>
//! [Contributing] · [Report a bug] · [Request a Feature] · [Create a Pull Request]
//!
//! </div>
//!
//! # Ratatui
//!
//! [Ratatui][Ratatui Website] 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` as a dependency to your cargo.toml:
//!
//! ```shell
//! cargo add ratatui
//! ```
//!
//! 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.
//!
//! 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.
//!
//! ## Other documentation
//!
//! - [Ratatui Website] - explains the library's concepts and provides step-by-step tutorials
//! - [Ratatui Forum][Forum] - a place to ask questions and discuss the library
//! - [API Docs] - the full API documentation for the library on docs.rs.
//! - [Examples] - a collection of examples that demonstrate how to use the library.
//! - [Contributing] - Please read this if you are interested in contributing to the project.
//! - [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
//! - [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
//! 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.
//!
//! 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. After this closure returns, a diff is performed and
//! only the changes are drawn to the terminal. 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 ratatui::{
//! crossterm::{
//! event::{self, Event, KeyCode},
//! terminal::{
//! disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
//! },
//! ExecutableCommand,
//! },
//! 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::bordered().title("Greeting")),
//! 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::bordered().title("Left"), inner_layout[0]);
//! frame.render_widget(Block::bordered().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!())]
//!
//! [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/
//! [templates]: https://github.com/ratatui-org/templates/
//! [Examples]: https://github.com/ratatui-org/ratatui/tree/main/examples/README.md
//! [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
//! [Create a Pull Request]: https://github.com/ratatui-org/ratatui/compare
//! [git-cliff]: https://git-cliff.org
//! [Conventional Commits]: https://www.conventionalcommits.org
//! [API Docs]: 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
//! [FOSDEM 2024 talk]: https://www.youtube.com/watch?v=NU0q6NOLJ20
//! [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
//! [Crate]: https://crates.io/crates/ratatui
//! [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
//! [GitHub Sponsors]: https://github.com/sponsors/ratatui-org
//! [Crate Badge]: https://img.shields.io/crates/v/ratatui?logo=rust&style=flat-square&logoColor=E05D44&color=E05D44
//! [License Badge]: https://img.shields.io/crates/l/ratatui?style=flat-square&color=1370D3
//! [CI Badge]: https://img.shields.io/github/actions/workflow/status/ratatui-org/ratatui/ci.yml?style=flat-square&logo=github
//! [CI Workflow]: https://github.com/ratatui-org/ratatui/actions/workflows/ci.yml
//! [Codecov Badge]: https://img.shields.io/codecov/c/github/ratatui-org/ratatui?logo=codecov&style=flat-square&token=BAQ8SOKEST&color=C43AC3&logoColor=C43AC3
//! [Codecov]: https://app.codecov.io/gh/ratatui-org/ratatui
//! [Deps.rs Badge]: https://deps.rs/repo/github/ratatui-org/ratatui/status.svg?style=flat-square
//! [Deps.rs]: https://deps.rs/repo/github/ratatui-org/ratatui
//! [Discord Badge]: https://img.shields.io/discord/1070692720437383208?label=discord&logo=discord&style=flat-square&color=1370D3&logoColor=1370D3
//! [Discord Server]: https://discord.gg/pMCEU9hNEj
//! [Docs Badge]: https://img.shields.io/docsrs/ratatui?logo=rust&style=flat-square&logoColor=E05D44
//! [Matrix Badge]: https://img.shields.io/matrix/ratatui-general%3Amatrix.org?style=flat-square&logo=matrix&label=Matrix&color=C43AC3
//! [Matrix]: https://matrix.to/#/#ratatui:matrix.org
//! [Forum Badge]: https://img.shields.io/discourse/likes?server=https%3A%2F%2Fforum.ratatui.rs&style=flat-square&logo=discourse&label=forum&color=C43AC3
//! [Forum]: https://forum.ratatui.rs
//! [Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui-org?logo=github&style=flat-square&color=1370D3
// 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"
)]
/// re-export the `crossterm` crate so that users don't have to add it as a dependency
#[cfg(feature = "crossterm")]
pub use crossterm;
#[doc(inline)]
pub use terminal::{CompletedFrame, Frame, Terminal, TerminalOptions, Viewport};
/// re-export the `termion` crate so that users don't have to add it as a dependency
#[cfg(feature = "termion")]
pub use termion;
/// re-export the `termwiz` crate so that users don't have to add it as a dependency
#[cfg(feature = "termwiz")]
pub use termwiz;
pub mod backend;
pub mod buffer;
pub mod layout;
pub mod prelude;
pub mod style;
pub mod symbols;
pub mod terminal;
pub mod text;
pub mod widgets;