mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-25 14:10:31 +00:00
feat(logo): Add a Ratatui logo widget
This is a simple logo widget that can be used to render the Ratatui logo in the terminal. It is used in the `examples/ratatui-logo.rs` example, and may be used in your applications' help or about screens. ```rust use ratatui::{Frame, widgets::RatatuiLogo}; fn draw(frame: &mut Frame) { frame.render_widget(RatatuiLogo::tiny(), frame.area()); } ```
This commit is contained in:
parent
baf047f556
commit
2805dddf05
5 changed files with 273 additions and 47 deletions
|
@ -27,6 +27,7 @@ cassowary = "0.3"
|
||||||
compact_str = "0.8.0"
|
compact_str = "0.8.0"
|
||||||
crossterm = { version = "0.28.1", optional = true }
|
crossterm = { version = "0.28.1", optional = true }
|
||||||
document-features = { version = "0.2.7", optional = true }
|
document-features = { version = "0.2.7", optional = true }
|
||||||
|
indoc = "2"
|
||||||
instability = "0.3.1"
|
instability = "0.3.1"
|
||||||
itertools = "0.13"
|
itertools = "0.13"
|
||||||
lru = "0.12.0"
|
lru = "0.12.0"
|
||||||
|
|
|
@ -13,57 +13,42 @@
|
||||||
//! [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 std::{
|
use std::env::args;
|
||||||
io::{self},
|
|
||||||
thread::sleep,
|
use color_eyre::Result;
|
||||||
time::Duration,
|
use crossterm::event::{self, Event};
|
||||||
|
use ratatui::{
|
||||||
|
layout::{Constraint, Layout},
|
||||||
|
widgets::{RatatuiLogo, RatatuiLogoSize},
|
||||||
|
DefaultTerminal, TerminalOptions, Viewport,
|
||||||
};
|
};
|
||||||
|
|
||||||
use indoc::indoc;
|
fn main() -> Result<()> {
|
||||||
use itertools::izip;
|
color_eyre::install()?;
|
||||||
use ratatui::{widgets::Paragraph, TerminalOptions, Viewport};
|
let terminal = ratatui::init_with_options(TerminalOptions {
|
||||||
|
|
||||||
/// A fun example of using half block characters to draw a logo
|
|
||||||
#[allow(clippy::many_single_char_names)]
|
|
||||||
fn logo() -> String {
|
|
||||||
let r = indoc! {"
|
|
||||||
▄▄▄
|
|
||||||
█▄▄▀
|
|
||||||
█ █
|
|
||||||
"};
|
|
||||||
let a = indoc! {"
|
|
||||||
▄▄
|
|
||||||
█▄▄█
|
|
||||||
█ █
|
|
||||||
"};
|
|
||||||
let t = indoc! {"
|
|
||||||
▄▄▄
|
|
||||||
█
|
|
||||||
█
|
|
||||||
"};
|
|
||||||
let u = indoc! {"
|
|
||||||
▄ ▄
|
|
||||||
█ █
|
|
||||||
▀▄▄▀
|
|
||||||
"};
|
|
||||||
let i = indoc! {"
|
|
||||||
▄
|
|
||||||
█
|
|
||||||
█
|
|
||||||
"};
|
|
||||||
izip!(r.lines(), a.lines(), t.lines(), u.lines(), i.lines())
|
|
||||||
.map(|(r, a, t, u, i)| format!("{r:5}{a:5}{t:4}{a:5}{t:4}{u:5}{i:5}"))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
|
||||||
let mut terminal = ratatui::init_with_options(TerminalOptions {
|
|
||||||
viewport: Viewport::Inline(3),
|
viewport: Viewport::Inline(3),
|
||||||
});
|
});
|
||||||
terminal.draw(|frame| frame.render_widget(Paragraph::new(logo()), frame.area()))?;
|
let size = match args().nth(1).as_deref() {
|
||||||
sleep(Duration::from_secs(5));
|
Some("small") => RatatuiLogoSize::Small,
|
||||||
|
Some("tiny") => RatatuiLogoSize::Tiny,
|
||||||
|
_ => RatatuiLogoSize::default(),
|
||||||
|
};
|
||||||
|
let result = run(terminal, size);
|
||||||
ratatui::restore();
|
ratatui::restore();
|
||||||
println!();
|
println!();
|
||||||
Ok(())
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(mut terminal: DefaultTerminal, size: RatatuiLogoSize) -> Result<()> {
|
||||||
|
loop {
|
||||||
|
terminal.draw(|frame| {
|
||||||
|
use Constraint::{Fill, Length};
|
||||||
|
let [top, bottom] = Layout::vertical([Length(1), Fill(1)]).areas(frame.area());
|
||||||
|
frame.render_widget("Powered by", top);
|
||||||
|
frame.render_widget(RatatuiLogo::new(size), bottom);
|
||||||
|
})?;
|
||||||
|
if matches!(event::read()?, Event::Key(_)) {
|
||||||
|
break Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,3 +10,5 @@ Enter
|
||||||
Sleep 2s
|
Sleep 2s
|
||||||
Show
|
Show
|
||||||
Sleep 2s
|
Sleep 2s
|
||||||
|
Hide
|
||||||
|
Escape
|
||||||
|
|
|
@ -31,6 +31,7 @@ mod chart;
|
||||||
mod clear;
|
mod clear;
|
||||||
mod gauge;
|
mod gauge;
|
||||||
mod list;
|
mod list;
|
||||||
|
mod logo;
|
||||||
mod paragraph;
|
mod paragraph;
|
||||||
mod reflow;
|
mod reflow;
|
||||||
mod scrollbar;
|
mod scrollbar;
|
||||||
|
@ -46,6 +47,7 @@ pub use self::{
|
||||||
clear::Clear,
|
clear::Clear,
|
||||||
gauge::{Gauge, LineGauge},
|
gauge::{Gauge, LineGauge},
|
||||||
list::{List, ListDirection, ListItem, ListState},
|
list::{List, ListDirection, ListItem, ListState},
|
||||||
|
logo::{RatatuiLogo, Size as RatatuiLogoSize},
|
||||||
paragraph::{Paragraph, Wrap},
|
paragraph::{Paragraph, Wrap},
|
||||||
scrollbar::{ScrollDirection, Scrollbar, ScrollbarOrientation, ScrollbarState},
|
scrollbar::{ScrollDirection, Scrollbar, ScrollbarOrientation, ScrollbarState},
|
||||||
sparkline::{RenderDirection, Sparkline},
|
sparkline::{RenderDirection, Sparkline},
|
||||||
|
|
236
src/widgets/logo.rs
Normal file
236
src/widgets/logo.rs
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
use indoc::indoc;
|
||||||
|
|
||||||
|
use crate::{buffer::Buffer, layout::Rect, text::Text, widgets::Widget};
|
||||||
|
|
||||||
|
/// A widget that renders the Ratatui logo
|
||||||
|
///
|
||||||
|
/// The Ratatui logo takes up two lines of text and comes in two sizes: `Tiny` and `Small`. This may
|
||||||
|
/// be used in an application's help or about screen to show that it is powered by Ratatui.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// The [Ratatui-logo] example demonstrates how to use the `RatatuiLogo` widget. This can be run by
|
||||||
|
/// cloning the Ratatui repository and then running the following command with an optional size
|
||||||
|
/// argument:
|
||||||
|
///
|
||||||
|
/// ```shell
|
||||||
|
/// cargo run --example ratatui-logo [size]
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Ratatui-logo]: https://github.com/ratatui/ratatui/blob/main/examples/ratatui-logo.rs
|
||||||
|
///
|
||||||
|
/// ## Tiny (default, 2x15 characters)
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ratatui::widgets::RatatuiLogo;
|
||||||
|
///
|
||||||
|
/// # fn draw(frame: &mut ratatui::Frame) {
|
||||||
|
/// frame.render_widget(RatatuiLogo::tiny(), frame.area());
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Renders:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// ▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌
|
||||||
|
/// ▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Small (2x27 characters)
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ratatui::widgets::RatatuiLogo;
|
||||||
|
///
|
||||||
|
/// # fn draw(frame: &mut ratatui::Frame) {
|
||||||
|
/// frame.render_widget(RatatuiLogo::small(), frame.area());
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Renders:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// █▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█ █ █
|
||||||
|
/// █▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █
|
||||||
|
/// ```
|
||||||
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct RatatuiLogo {
|
||||||
|
size: Size,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The size of the logo
|
||||||
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum Size {
|
||||||
|
/// A tiny logo
|
||||||
|
///
|
||||||
|
/// The default size of the logo (2x15 characters)
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// ▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌
|
||||||
|
/// ▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌
|
||||||
|
/// ```
|
||||||
|
#[default]
|
||||||
|
Tiny,
|
||||||
|
/// A small logo
|
||||||
|
///
|
||||||
|
/// A slightly larger version of the logo (2x27 characters)
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// █▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█ █ █
|
||||||
|
/// █▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █
|
||||||
|
/// ```
|
||||||
|
Small,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RatatuiLogo {
|
||||||
|
/// Create a new Ratatui logo widget
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ratatui::widgets::{RatatuiLogo, RatatuiLogoSize};
|
||||||
|
///
|
||||||
|
/// let logo = RatatuiLogo::new(RatatuiLogoSize::Tiny);
|
||||||
|
/// ```
|
||||||
|
pub const fn new(size: Size) -> Self {
|
||||||
|
Self { size }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the size of the logo
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ratatui::widgets::{RatatuiLogo, RatatuiLogoSize};
|
||||||
|
///
|
||||||
|
/// let logo = RatatuiLogo::default().size(RatatuiLogoSize::Small);
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
pub const fn size(self, size: Size) -> Self {
|
||||||
|
let _ = self;
|
||||||
|
Self { size }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new Ratatui logo widget with a tiny size
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ratatui::widgets::RatatuiLogo;
|
||||||
|
///
|
||||||
|
/// let logo = RatatuiLogo::tiny();
|
||||||
|
/// ```
|
||||||
|
pub const fn tiny() -> Self {
|
||||||
|
Self::new(Size::Tiny)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new Ratatui logo widget with a small size
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ratatui::widgets::RatatuiLogo;
|
||||||
|
///
|
||||||
|
/// let logo = RatatuiLogo::small();
|
||||||
|
/// ```
|
||||||
|
pub const fn small() -> Self {
|
||||||
|
Self::new(Size::Small)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for RatatuiLogo {
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
|
let logo = self.size.as_str();
|
||||||
|
Text::raw(logo).render(area, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Size {
|
||||||
|
const fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Tiny => Self::tiny(),
|
||||||
|
Self::Small => Self::small(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn tiny() -> &'static str {
|
||||||
|
indoc! {"
|
||||||
|
▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌
|
||||||
|
▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌
|
||||||
|
"}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn small() -> &'static str {
|
||||||
|
indoc! {"
|
||||||
|
█▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█ █ █
|
||||||
|
█▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █
|
||||||
|
"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case::tiny(Size::Tiny)]
|
||||||
|
#[case::small(Size::Small)]
|
||||||
|
fn new_size(#[case] size: Size) {
|
||||||
|
let logo = RatatuiLogo::new(size);
|
||||||
|
assert_eq!(logo.size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_logo_is_tiny() {
|
||||||
|
let logo = RatatuiLogo::default();
|
||||||
|
assert_eq!(logo.size, Size::Tiny);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set_logo_size_to_small() {
|
||||||
|
let logo = RatatuiLogo::default().size(Size::Small);
|
||||||
|
assert_eq!(logo.size, Size::Small);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tiny_logo_constant() {
|
||||||
|
let logo = RatatuiLogo::tiny();
|
||||||
|
assert_eq!(logo.size, Size::Tiny);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn small_logo_constant() {
|
||||||
|
let logo = RatatuiLogo::small();
|
||||||
|
assert_eq!(logo.size, Size::Small);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn render_tiny() {
|
||||||
|
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 2));
|
||||||
|
RatatuiLogo::tiny().render(buf.area, &mut buf);
|
||||||
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
Buffer::with_lines([
|
||||||
|
"▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌",
|
||||||
|
"▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌",
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn render_small() {
|
||||||
|
let mut buf = Buffer::empty(Rect::new(0, 0, 27, 2));
|
||||||
|
RatatuiLogo::small().render(buf.area, &mut buf);
|
||||||
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
Buffer::with_lines([
|
||||||
|
"█▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█ █ █",
|
||||||
|
"█▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █",
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue