ratatui/
lib.rs

1//! ![Demo](https://github.com/ratatui/ratatui/blob/87ae72dbc756067c97f6400d3e2a58eeb383776e/examples/demo2-destroy.gif?raw=true)
2//!
3//! <div align="center">
4//!
5//! [![Crate Badge]][Crate] [![Docs Badge]][API Docs] [![CI Badge]][CI Workflow] [![Deps.rs
6//! Badge]][Deps.rs]<br> [![Codecov Badge]][Codecov] [![License Badge]](./LICENSE) [![Sponsors
7//! Badge]][GitHub Sponsors]<br> [![Discord Badge]][Discord Server] [![Matrix Badge]][Matrix]
8//! [![Forum Badge]][Forum]<br>
9//!
10//! [Ratatui Website] · [API Docs] · [Examples] · [Changelog] · [Breaking Changes]<br>
11//! [Contributing] · [Report a bug] · [Request a Feature] · [Create a Pull Request]
12//!
13//! </div>
14//!
15//! # Ratatui
16//!
17//! [Ratatui][Ratatui Website] is a crate for cooking up terminal user interfaces in Rust. It is a
18//! lightweight library that provides a set of widgets and utilities to build complex Rust TUIs.
19//! Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development.
20//!
21//! ## Quickstart
22//!
23//! Add `ratatui` and `crossterm` as dependencies to your cargo.toml:
24//!
25//! ```shell
26//! cargo add ratatui crossterm
27//! ```
28//!
29//! Then you can create a simple "Hello World" application:
30//!
31//! ```rust,no_run
32//! use crossterm::event::{self, Event};
33//! use ratatui::{text::Text, Frame};
34//!
35//! fn main() {
36//!     let mut terminal = ratatui::init();
37//!     loop {
38//!         terminal.draw(draw).expect("failed to draw frame");
39//!         if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
40//!             break;
41//!         }
42//!     }
43//!     ratatui::restore();
44//! }
45//!
46//! fn draw(frame: &mut Frame) {
47//!     let text = Text::raw("Hello World!");
48//!     frame.render_widget(text, frame.area());
49//! }
50//! ```
51//!
52//! The full code for this example which contains a little more detail is in the [Examples]
53//! directory. For more guidance on different ways to structure your application see the
54//! [Application Patterns] and [Hello World tutorial] sections in the [Ratatui Website] and the
55//! various [Examples]. There are also several starter templates available in the [templates]
56//! repository.
57//!
58//! ## Other documentation
59//!
60//! - [Ratatui Website] - explains the library's concepts and provides step-by-step tutorials
61//! - [Ratatui Forum][Forum] - a place to ask questions and discuss the library
62//! - [API Docs] - the full API documentation for the library on docs.rs.
63//! - [Examples] - a collection of examples that demonstrate how to use the library.
64//! - [Contributing] - Please read this if you are interested in contributing to the project.
65//! - [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
66//! - [Breaking Changes] - a list of breaking changes in the library.
67//!
68//! You can also watch the [FOSDEM 2024 talk] about Ratatui which gives a brief introduction to
69//! terminal user interfaces and showcases the features of Ratatui, along with a hello world demo.
70//!
71//! ## Introduction
72//!
73//! Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
74//! that for each frame, your app must render all widgets that are supposed to be part of the UI.
75//! This is in contrast to the retained mode style of rendering where widgets are updated and then
76//! automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
77//! for more info.
78//!
79//! Ratatui uses [Crossterm] by default as it works on most platforms. See the [Installation]
80//! section of the [Ratatui Website] for more details on how to use other backends ([Termion] /
81//! [Termwiz]).
82//!
83//! Every application built with `ratatui` needs to implement the following steps:
84//!
85//! - Initialize the terminal
86//! - A main loop that:
87//!   - Draws the UI
88//!   - Handles input events
89//! - Restore the terminal state
90//!
91//! ### Initialize and restore the terminal
92//!
93//! The [`Terminal`] type is the main entry point for any Ratatui application. It is generic over a
94//! a choice of [`Backend`] implementations that each provide functionality to draw frames, clear
95//! the screen, hide the cursor, etc. There are backend implementations for [Crossterm], [Termion]
96//! and [Termwiz].
97//!
98//! The simplest way to initialize the terminal is to use the [`init`] function which returns a
99//! [`DefaultTerminal`] instance with the default options, enters the Alternate Screen and Raw mode
100//! and sets up a panic hook that restores the terminal in case of panic. This instance can then be
101//! used to draw frames and interact with the terminal state. (The [`DefaultTerminal`] instance is a
102//! type alias for a terminal with the [`crossterm`] backend.) The [`restore`] function restores the
103//! terminal to its original state.
104//!
105//! ```rust,no_run
106//! fn main() -> std::io::Result<()> {
107//!     let mut terminal = ratatui::init();
108//!     let result = run(&mut terminal);
109//!     ratatui::restore();
110//!     result
111//! }
112//! # fn run(terminal: &mut ratatui::DefaultTerminal) -> std::io::Result<()> { Ok(()) }
113//! ```
114//!
115//! See the [`backend` module] and the [Backends] section of the [Ratatui Website] for more info on
116//! the alternate screen and raw mode.
117//!
118//! ### Drawing the UI
119//!
120//! Drawing the UI is done by calling the [`Terminal::draw`] method on the terminal instance. This
121//! method takes a closure that is called with a [`Frame`] instance. The [`Frame`] provides the size
122//! of the area to draw to and allows the app to render any [`Widget`] using the provided
123//! [`render_widget`] method. After this closure returns, a diff is performed and only the changes
124//! are drawn to the terminal. See the [Widgets] section of the [Ratatui Website] for more info.
125//!
126//! The closure passed to the [`Terminal::draw`] method should handle the rendering of a full frame.
127//!
128//! ```rust,no_run
129//! use ratatui::{widgets::Paragraph, Frame};
130//!
131//! fn run(terminal: &mut ratatui::DefaultTerminal) -> std::io::Result<()> {
132//!     loop {
133//!         terminal.draw(|frame| draw(frame))?;
134//!         if handle_events()? {
135//!             break Ok(());
136//!         }
137//!     }
138//! }
139//!
140//! fn draw(frame: &mut Frame) {
141//!     let text = Paragraph::new("Hello World!");
142//!     frame.render_widget(text, frame.area());
143//! }
144//! # fn handle_events() -> std::io::Result<bool> { Ok(false) }
145//! ```
146//!
147//! ### Handling events
148//!
149//! Ratatui does not include any input handling. Instead event handling can be implemented by
150//! calling backend library methods directly. See the [Handling Events] section of the [Ratatui
151//! Website] for more info. For example, if you are using [Crossterm], you can use the
152//! [`crossterm::event`] module to handle events.
153//!
154//! ```rust,no_run
155//! use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
156//!
157//! fn handle_events() -> std::io::Result<bool> {
158//!     match event::read()? {
159//!         Event::Key(key) if key.kind == KeyEventKind::Press => match key.code {
160//!             KeyCode::Char('q') => return Ok(true),
161//!             // handle other key events
162//!             _ => {}
163//!         },
164//!         // handle other events
165//!         _ => {}
166//!     }
167//!     Ok(false)
168//! }
169//! ```
170//!
171//! ## Layout
172//!
173//! The library comes with a basic yet useful layout management object called [`Layout`] which
174//! allows you to split the available space into multiple areas and then render widgets in each
175//! area. This lets you describe a responsive terminal UI by nesting layouts. See the [Layout]
176//! section of the [Ratatui Website] for more info.
177//!
178//! ```rust,no_run
179//! use ratatui::{
180//!     layout::{Constraint, Layout},
181//!     widgets::Block,
182//!     Frame,
183//! };
184//!
185//! fn draw(frame: &mut Frame) {
186//!     use Constraint::{Fill, Length, Min};
187//!
188//!     let vertical = Layout::vertical([Length(1), Min(0), Length(1)]);
189//!     let [title_area, main_area, status_area] = vertical.areas(frame.area());
190//!     let horizontal = Layout::horizontal([Fill(1); 2]);
191//!     let [left_area, right_area] = horizontal.areas(main_area);
192//!
193//!     frame.render_widget(Block::bordered().title("Title Bar"), title_area);
194//!     frame.render_widget(Block::bordered().title("Status Bar"), status_area);
195//!     frame.render_widget(Block::bordered().title("Left"), left_area);
196//!     frame.render_widget(Block::bordered().title("Right"), right_area);
197//! }
198//! ```
199//!
200//! Running this example produces the following output:
201//!
202//! ```text
203//! Title Bar───────────────────────────────────
204//! ┌Left────────────────┐┌Right───────────────┐
205//! │                    ││                    │
206//! └────────────────────┘└────────────────────┘
207//! Status Bar──────────────────────────────────
208//! ```
209//!
210//! ## Text and styling
211//!
212//! The [`Text`], [`Line`] and [`Span`] types are the building blocks of the library and are used in
213//! many places. [`Text`] is a list of [`Line`]s and a [`Line`] is a list of [`Span`]s. A [`Span`]
214//! is a string with a specific style.
215//!
216//! The [`style` module] provides types that represent the various styling options. The most
217//! important one is [`Style`] which represents the foreground and background colors and the text
218//! attributes of a [`Span`]. The [`style` module] also provides a [`Stylize`] trait that allows
219//! short-hand syntax to apply a style to widgets and text. See the [Styling Text] section of the
220//! [Ratatui Website] for more info.
221//!
222//! ```rust,no_run
223//! use ratatui::{
224//!     layout::{Constraint, Layout},
225//!     style::{Color, Modifier, Style, Stylize},
226//!     text::{Line, Span},
227//!     widgets::{Block, Paragraph},
228//!     Frame,
229//! };
230//!
231//! fn draw(frame: &mut Frame) {
232//!     let areas = Layout::vertical([Constraint::Length(1); 4]).split(frame.area());
233//!
234//!     let line = Line::from(vec![
235//!         Span::raw("Hello "),
236//!         Span::styled(
237//!             "World",
238//!             Style::new()
239//!                 .fg(Color::Green)
240//!                 .bg(Color::White)
241//!                 .add_modifier(Modifier::BOLD),
242//!         ),
243//!         "!".red().on_light_yellow().italic(),
244//!     ]);
245//!     frame.render_widget(line, areas[0]);
246//!
247//!     // using the short-hand syntax and implicit conversions
248//!     let paragraph = Paragraph::new("Hello World!".red().on_white().bold());
249//!     frame.render_widget(paragraph, areas[1]);
250//!
251//!     // style the whole widget instead of just the text
252//!     let paragraph = Paragraph::new("Hello World!").style(Style::new().red().on_white());
253//!     frame.render_widget(paragraph, areas[2]);
254//!
255//!     // use the simpler short-hand syntax
256//!     let paragraph = Paragraph::new("Hello World!").blue().on_yellow();
257//!     frame.render_widget(paragraph, areas[3]);
258//! }
259//! ```
260#![cfg_attr(feature = "document-features", doc = "\n## Features")]
261#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
262//!
263//! [Ratatui Website]: https://ratatui.rs/
264//! [Installation]: https://ratatui.rs/installation/
265//! [Rendering]: https://ratatui.rs/concepts/rendering/
266//! [Application Patterns]: https://ratatui.rs/concepts/application-patterns/
267//! [Hello World tutorial]: https://ratatui.rs/tutorials/hello-world/
268//! [Backends]: https://ratatui.rs/concepts/backends/
269//! [Widgets]: https://ratatui.rs/how-to/widgets/
270//! [Handling Events]: https://ratatui.rs/concepts/event-handling/
271//! [Layout]: https://ratatui.rs/how-to/layout/
272//! [Styling Text]: https://ratatui.rs/how-to/render/style-text/
273//! [templates]: https://github.com/ratatui/templates/
274//! [Examples]: https://github.com/ratatui/ratatui/tree/main/examples/README.md
275//! [Report a bug]: https://github.com/ratatui/ratatui/issues/new?labels=bug&projects=&template=bug_report.md
276//! [Request a Feature]: https://github.com/ratatui/ratatui/issues/new?labels=enhancement&projects=&template=feature_request.md
277//! [Create a Pull Request]: https://github.com/ratatui/ratatui/compare
278//! [git-cliff]: https://git-cliff.org
279//! [Conventional Commits]: https://www.conventionalcommits.org
280//! [API Docs]: https://docs.rs/ratatui
281//! [Changelog]: https://github.com/ratatui/ratatui/blob/main/CHANGELOG.md
282//! [Contributing]: https://github.com/ratatui/ratatui/blob/main/CONTRIBUTING.md
283//! [Breaking Changes]: https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md
284//! [FOSDEM 2024 talk]: https://www.youtube.com/watch?v=NU0q6NOLJ20
285//! [`Frame`]: terminal::Frame
286//! [`render_widget`]: terminal::Frame::render_widget
287//! [`Widget`]: widgets::Widget
288//! [`Layout`]: layout::Layout
289//! [`Text`]: text::Text
290//! [`Line`]: text::Line
291//! [`Span`]: text::Span
292//! [`Style`]: style::Style
293//! [`style` module]: style
294//! [`Stylize`]: style::Stylize
295//! [`Backend`]: backend::Backend
296//! [`backend` module]: backend
297//! [`crossterm::event`]: https://docs.rs/crossterm/latest/crossterm/event/index.html
298//! [Crate]: https://crates.io/crates/ratatui
299//! [Crossterm]: https://crates.io/crates/crossterm
300//! [Termion]: https://crates.io/crates/termion
301//! [Termwiz]: https://crates.io/crates/termwiz
302//! [tui-rs]: https://crates.io/crates/tui
303//! [GitHub Sponsors]: https://github.com/sponsors/ratatui
304//! [Crate Badge]: https://img.shields.io/crates/v/ratatui?logo=rust&style=flat-square&logoColor=E05D44&color=E05D44
305//! [License Badge]: https://img.shields.io/crates/l/ratatui?style=flat-square&color=1370D3
306//! [CI Badge]: https://img.shields.io/github/actions/workflow/status/ratatui/ratatui/ci.yml?style=flat-square&logo=github
307//! [CI Workflow]: https://github.com/ratatui/ratatui/actions/workflows/ci.yml
308//! [Codecov Badge]: https://img.shields.io/codecov/c/github/ratatui/ratatui?logo=codecov&style=flat-square&token=BAQ8SOKEST&color=C43AC3&logoColor=C43AC3
309//! [Codecov]: https://app.codecov.io/gh/ratatui/ratatui
310//! [Deps.rs Badge]: https://deps.rs/repo/github/ratatui/ratatui/status.svg?style=flat-square
311//! [Deps.rs]: https://deps.rs/repo/github/ratatui/ratatui
312//! [Discord Badge]: https://img.shields.io/discord/1070692720437383208?label=discord&logo=discord&style=flat-square&color=1370D3&logoColor=1370D3
313//! [Discord Server]: https://discord.gg/pMCEU9hNEj
314//! [Docs Badge]: https://img.shields.io/docsrs/ratatui?logo=rust&style=flat-square&logoColor=E05D44
315//! [Matrix Badge]: https://img.shields.io/matrix/ratatui-general%3Amatrix.org?style=flat-square&logo=matrix&label=Matrix&color=C43AC3
316//! [Matrix]: https://matrix.to/#/#ratatui:matrix.org
317//! [Forum Badge]: https://img.shields.io/discourse/likes?server=https%3A%2F%2Fforum.ratatui.rs&style=flat-square&logo=discourse&label=forum&color=C43AC3
318//! [Forum]: https://forum.ratatui.rs
319//! [Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui?logo=github&style=flat-square&color=1370D3
320
321// show the feature flags in the generated documentation
322#![cfg_attr(docsrs, feature(doc_auto_cfg))]
323#![doc(
324    html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
325    html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
326)]
327
328/// re-export the `crossterm` crate so that users don't have to add it as a dependency
329#[cfg(feature = "crossterm")]
330pub use crossterm;
331/// re-export the `palette` crate so that users don't have to add it as a dependency
332#[cfg(feature = "palette")]
333pub use palette;
334#[cfg(feature = "crossterm")]
335pub use terminal::{
336    init, init_with_options, restore, try_init, try_init_with_options, try_restore, DefaultTerminal,
337};
338pub use terminal::{CompletedFrame, Frame, Terminal, TerminalOptions, Viewport};
339/// re-export the `termion` crate so that users don't have to add it as a dependency
340#[cfg(all(not(windows), feature = "termion"))]
341pub use termion;
342/// re-export the `termwiz` crate so that users don't have to add it as a dependency
343#[cfg(feature = "termwiz")]
344pub use termwiz;
345
346pub mod backend;
347pub mod buffer;
348pub mod layout;
349pub mod prelude;
350pub mod style;
351pub mod symbols;
352mod terminal;
353pub mod text;
354pub mod widgets;