Minimal terminal spinner library for Rust with preset collection and no-std support
triggers
["add a spinner to my terminal app","how do I use rattles spinner","terminal spinner in Rust","animate a loading indicator in CLI","ratatui spinner widget","no_std spinner animation","custom spinner keyframes Rust","braille dots spinner terminal"]
Rattles is a minimal, zero-dependency Rust library for terminal spinners. It has no runtime or lifecycle — spinners are constructed directly in render loops with negligible cost. Supports no_std environments.
Installation
# Cargo.toml[dependencies]rattles = "0.1"# with std (default)# no_stdrattles = { version = "0.1", default-features = false }
use rattles::presets::prelude as presets;
use std::time::Duration;
letrattle = presets::dots();
// Get frame based on system clock (std only)letframe: &str = rattle.current_frame();
// Get frame at specific elapsed duration (std + no_std)letframe = rattle.frame_at(Duration::from_millis(500));
// Get frame by indexletframe = rattle.frame(3);
// Change animation intervalletrattle = presets::dots().set_interval(Duration::from_millis(50));
// Reverse directionletrattle = presets::waverows().reverse();
// Convert to tick-based (stateful)letmut ticked = presets::dots().into_ticked();
TickedRattler (Stateful / no_std-friendly)
use rattles::presets::prelude as presets;
letmut rattle = presets::dots().into_ticked();
loop {
rattle.tick();
letframe = rattle.current_frame();
// render frame...
}
TickedRattler must be stored (it holds state). Suitable for no_std contexts where the global clock is unavailable.
Index-Based Animation (no_std)
use rattles::presets::prelude as presets;
letrattle = presets::dots();
letmut i = 0usize;
loop {
letframe = rattle.frame(i);
i = i.wrapping_add(1);
// render frame...
}
Time-Based Animation with External Clock (no_std)
use rattles::presets::prelude as presets;
use core::time::Duration;
letrattle = presets::dots();
// elapsed comes from your platform's timerletelapsed: Duration = get_elapsed(); // your implementationletframe = rattle.frame_at(elapsed);
Custom Spinners with rattle! Macro
use rattles::rattle;
rattle!(
MySpinner, // generated struct name
my_spinner, // generated constructor function name1, // row count (width of spinner)120, // interval in milliseconds
["⣾", "⣷", "⣯", "⣟", "⣻", "⣽"] // keyframes
);
// Use it like any presetlets = my_spinner();
println!("{}", s.current_frame());