tui-banner
Cinematic ANSI banner rendering for Rust CLI and TUI apps, with gradients, dithering, shadows, and built-in animations.
Repository Health
Technical Analysis
tui-banner renders cinematic ANSI banners for Rust command-line and terminal-UI applications. A single fluent Banner builder chains together fonts, gradients, dithering, shadows, edge shading, frames, and light-sweep/wave/roll animations, then emits colorized output tuned to the detected terminal’s color capability.
The crate ships as pure Rust with zero third-party dependencies, bundling a DOS Rebel FIGlet font while still accepting any custom .flf font file. A companion tui-banner-cli binary exposes the same builder surface as flags, so teams can prototype a banner on the command line before wiring the identical configuration into their Rust program.
What You Get
- A fluent
Bannerbuilder covering font, gradient, fill, frame, padding, alignment, and color-mode configuration in one chain. - A bundled DOS Rebel FIGlet font plus support for loading any custom
.flffont file. - Built-in visual effects: dot dithering, drop shadows, edge shading, and directional light-sweep tinting.
- Ready-made frame styles (rounded, single, double, custom characters), each with its own independent gradient.
- Sweep, wave, and roll terminal animation helpers built on
std::thread/std::time, with no async runtime required. - A companion
tui-banner-clibinary that exposes the entire builder API as command-line flags.
Common Use Cases
- Splash banners for Rust CLI tools on startup
- Branding headers for TUI dashboards
- Animated banners printed in CI/release logs
- Marketing screenshots or GIFs showcasing a terminal tool’s identity
Under The Hood
Architecture
tui-banner uses a grid-based rendering pipeline centered on Banner (src/banner.rs), a builder that owns text, font, gradient, fill, effects, frame, and color-mode settings; calling .render() runs the FIGlet rasterizer (font::render_text) to produce a Grid of Cells (grid.rs), then layers gradients (gradient.rs), fill/dither (fill.rs), dot dithering, shadow, and edge-shade effects (effects/) directly onto that grid, before an optional Frame wraps it (frame.rs) and emit::emit_ansi serializes the final cells to ANSI escape sequences. The pipeline has zero external dependencies, so every stage communicates purely through the shared Grid/Cell types; changing that core representation would ripple through every effect and the frame/emit stages, which all read and write cells directly rather than through an abstraction layer.
Tech Stack
The core crate targets Rust 2024 edition with no third-party dependencies at all — only std::io, std::thread, and std::time for output and animation timing. A companion tui-banner-cli binary crate (same Cargo workspace) depends solely on the library and hand-rolls its own argument parser in main.rs rather than pulling in clap. GitHub Actions CI runs cargo fmt --check, cargo clippy -D warnings, and cargo test on every push; a separate release workflow cross-compiles standalone CLI binaries for Linux (x86_64/aarch64), macOS (aarch64), and Windows via dtolnay/rust-toolchain.
Code Quality
#![deny(missing_docs)] in lib.rs forces every public item to carry a doc comment, so API documentation is comprehensive. Automated test coverage is thin, however — only one #[cfg(test)] module exists (in frame.rs, covering border-wrapping), with no dedicated tests for the gradient, dithering, shadow, or animation logic; correctness there currently rests on CI’s clippy/fmt gates and manual verification via the extensive example programs in examples/.
API Design
The public surface is a single fluent builder (Banner::new(text)?.style(...).align(...).render()), so getting a colorful banner takes one chained expression with no separate setup step. Naming is consistent across the crate (Fill, Gradient, Frame, Dither all follow the same builder-method pattern), and the abundant example programs double as executable documentation for every effect and animation. The tradeoff is a wide type surface — gradients, palettes, presets, dither modes, and frame styles are all distinct enums/structs the caller must learn — though the bundled examples make each one easy to find.