spinners-4.1.1/.cargo_vcs_info.json0000644000000001360000000000100127000ustar { "git": { "sha1": "3d4e71edfe34c7c3df3b39310ce0d8460464a86b" }, "path_in_vcs": "" }spinners-4.1.1/Cargo.lock0000644000000045100000000000100106530ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "heck" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "proc-macro2" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2", ] [[package]] name = "rustversion" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "spinners" version = "4.1.1" dependencies = [ "lazy_static", "maplit", "strum", ] [[package]] name = "strum" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", "syn", ] [[package]] name = "syn" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" spinners-4.1.1/Cargo.toml0000644000000022370000000000100107020ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "spinners" version = "4.1.1" authors = [ "Francฬงois-Guillaume RIBREAU ", "jewlexx", ] include = [ "src/**/*", "README.md", ] description = "๐Ÿ›Ž 60+ Elegant terminal spinners for Rust" homepage = "https://github.com/fgribreau/spinners" documentation = "https://docs.rs/spinners" readme = "README.md" keywords = [ "spinner", "spin", "loader", "term", "terminal", ] categories = ["command-line-interface"] license = "MIT" repository = "https://github.com/fgribreau/spinners" [dependencies.lazy_static] version = "1.4.0" [dependencies.maplit] version = "1.0.2" [dependencies.strum] version = "0.24.0" features = ["derive"] spinners-4.1.1/Cargo.toml.orig000064400000000000000000000012221046102023000143540ustar 00000000000000[package] name = "spinners" version = "4.1.1" edition = "2021" authors = ["Francฬงois-Guillaume RIBREAU ", "jewlexx"] homepage = "https://github.com/fgribreau/spinners" repository = "https://github.com/fgribreau/spinners" readme = "README.md" documentation = "https://docs.rs/spinners" description = "๐Ÿ›Ž 60+ Elegant terminal spinners for Rust" keywords = ["spinner", "spin", "loader", "term", "terminal"] categories = ["command-line-interface"] license = "MIT" include = ["src/**/*", "README.md"] [dependencies] lazy_static = { version = "1.4.0" } maplit = { version = "1.0.2" } strum = { version = "0.24.0", features = ["derive"] } spinners-4.1.1/README.md000064400000000000000000000035461046102023000127570ustar 00000000000000# Spinners - ๐Ÿ›Ž 60+ Elegant terminal spinners for Rust [![Cargo version](https://img.shields.io/crates/v/spinners.svg)](https://crates.io/crates/spinners) [![Crates.io](https://img.shields.io/crates/l/spinners.svg)](https://crates.io/crates/spinners) [![docs.rs](https://img.shields.io/badge/docs.rs-๐Ÿ‘Œ-4EC329.svg?)](https://docs.rs/spinners/) [![Crates.io](https://img.shields.io/crates/d/spinners.svg)](https://crates.io/crates/spinners) [![Slack](https://img.shields.io/badge/Slack-Join%20our%20tech%20community-17202A?logo=slack)](https://join.slack.com/t/fgribreau/shared_invite/zt-edpjwt2t-Zh39mDUMNQ0QOr9qOj~jrg)

> ## โค๏ธ Shameless plug > - [Open-Source **Webhook** as a Service](https://www.hook0.com/) > - [**Charts, simple as a URL**. 1 url = 1 chart - Charts API](https://image-charts.com) > - [Keycloak Identity and Access Management (IAM) as a Service](https://www.cloud-iam.com/) > - [Automate your **RoamResearch** second brain](https://www.roam-bot.com) > - [Blazing Fast Gitlab CI Runners (10x faster)](https://cloud-runner.com/) ![200083093-cf48fcab-d95c-4a59-ac66-6e167dd33e7e](https://github.com/FGRibreau/spinners/assets/138050/a3e4d4f9-44c4-4b54-82a7-e608ab1da742) ## Install See [Cargo page](https://crates.io/crates/spinners) ## Usage ```rust use spinners::{Spinner, Spinners}; use std::thread::sleep; use std::time::Duration; fn main() { let mut sp = Spinner::new(Spinners::Dots9, "Waiting for 3 seconds".into()); sleep(Duration::from_secs(3)); sp.stop(); } ``` - [List of available spinners](src/utils/spinner_names.rs) - [Documentation](https://docs.rs/spinners/) ## Example ```shell cargo run --example cycle ``` ```shell cargo run --example simple ``` ## License MIT ยฉ [Franรงois-Guillaume Ribreau](https://fgribreau.com), James Cordor spinners-4.1.1/src/lib.rs000064400000000000000000000164051046102023000134010ustar 00000000000000use std::thread::JoinHandle; use std::time::Instant; use std::{ sync::mpsc::{channel, Sender, TryRecvError}, thread, time::Duration, }; pub use crate::utils::spinner_names::SpinnerNames as Spinners; use crate::utils::spinners_data::SPINNERS as SpinnersMap; pub use crate::utils::stream::Stream; mod utils; pub struct Spinner { sender: Sender<(Instant, Option)>, join: Option>, stream: Stream } impl Drop for Spinner { fn drop(&mut self) { if self.join.is_some() { self.sender.send((Instant::now(), None)).unwrap(); self.join.take().unwrap().join().unwrap(); } } } impl Spinner { /// Create a new spinner along with a message /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let sp = Spinner::new(Spinners::Dots, "Loading things into memory...".into()); /// ``` /// /// No Message: /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let sp = Spinner::new(Spinners::Dots, String::new()); /// ``` pub fn new(spinner: Spinners, message: String) -> Self { Self::new_inner(spinner, message, None, None) } /// Create a new spinner that logs the time since it was created pub fn with_timer(spinner: Spinners, message: String) -> Self { Self::new_inner(spinner, message, Some(Instant::now()), None) } /// Creates a new spinner along with a message with a specified output stream /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners, Stream}; /// /// let sp = Spinner::with_stream(Spinners::Dots, String::new(), Stream::Stderr); /// ``` pub fn with_stream(spinner: Spinners, message: String, stream: Stream) -> Self { Self::new_inner(spinner, message, None, Some(stream)) } /// Creates a new spinner that logs the time since it was created with a specified output stream /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners, Stream}; /// /// let sp = Spinner::with_timer_and_stream(Spinners::Dots, String::new(), Stream::Stderr); /// ``` pub fn with_timer_and_stream(spinner: Spinners, message: String, stream: Stream) -> Self { Self::new_inner(spinner, message, Some(Instant::now()), Some(stream)) } fn new_inner(spinner: Spinners, message: String, start_time: Option, stream: Option) -> Self { let spinner_name = spinner.to_string(); let spinner_data = SpinnersMap .get(&spinner_name) .unwrap_or_else(|| panic!("No Spinner found with the given name: {}", spinner_name)); let stream = if let Some(stream) = stream { stream } else { Stream::default() }; let (sender, recv) = channel::<(Instant, Option)>(); let join = thread::spawn(move || 'outer: loop { for frame in spinner_data.frames.iter() { let (do_stop, stop_time, stop_symbol) = match recv.try_recv() { Ok((stop_time, stop_symbol)) => (true, Some(stop_time), stop_symbol), Err(TryRecvError::Disconnected) => (true, None, None), Err(TryRecvError::Empty) => (false, None, None), }; let frame = stop_symbol.unwrap_or_else(|| frame.to_string()); stream.write(&frame, &message, start_time, stop_time).expect("IO Error"); if do_stop { break 'outer; } thread::sleep(Duration::from_millis(spinner_data.interval as u64)); } }); Self { sender, join: Some(join), stream } } /// Stops the spinner /// /// Stops the spinner that was created with the [`Spinner::new`] function. /// /// Optionally call [`stop_with_newline`] to print a newline after the spinner is stopped, /// or the [`stop_with_message`] function to print a message after the spinner is stopped. /// /// [`Spinner::new`]: struct.Spinner.html#method.new /// [`stop_with_newline`]: struct.Spinner.html#method.stop_with_newline /// [`stop_with_message`]: struct.Spinner.html#method.stop_with_message /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let mut sp = Spinner::new(Spinners::Dots, "Loading things into memory...".into()); /// /// sp.stop(); /// ``` pub fn stop(&mut self) { self.stop_inner(Instant::now(), None); } /// Stop with a symbol that replaces the spinner /// /// The symbol is a String rather than a Char to allow for more flexibility, such as using ANSI color codes. /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let mut sp = Spinner::new(Spinners::Dots, "Loading things into memory...".into()); /// /// sp.stop_with_symbol("๐Ÿ—ธ"); /// ``` /// /// ANSI colors (green checkmark): /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let mut sp = Spinner::new(Spinners::Dots, "Loading things into memory...".into()); /// /// sp.stop_with_symbol("\x1b[32m๐Ÿ—ธ\x1b[0m"); /// ``` pub fn stop_with_symbol(&mut self, symbol: &str) { self.stop_inner(Instant::now(), Some(symbol.to_owned())); self.stream.stop(None, Some(symbol)).expect("IO error"); } /// Stops the spinner and prints a new line /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let mut sp = Spinner::new(Spinners::Dots, "Loading things into memory...".into()); /// /// sp.stop_with_newline(); /// ``` pub fn stop_with_newline(&mut self) { self.stop(); self.stream.stop(None, None).expect("IO error"); } /// Stops the spinner and prints the provided message /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let mut sp = Spinner::new(Spinners::Dots, "Loading things into memory...".into()); /// /// sp.stop_with_message("Finished loading things into memory!".into()); /// ``` pub fn stop_with_message(&mut self, msg: String) { self.stop(); self.stream.stop(Some(&msg), None).expect("IO Error"); } /// Stops the spinner with a provided symbol and message /// /// # Examples /// /// Basic Usage: /// /// ``` /// use spinners::{Spinner, Spinners}; /// /// let mut sp = Spinner::new(Spinners::Dots, "Loading things into memory...".into()); /// /// sp.stop_and_persist("โœ”", "Finished loading things into memory!".into()); /// ``` pub fn stop_and_persist(&mut self, symbol: &str, msg: String) { self.stop(); self.stream.stop(Some(&msg), Some(symbol)).expect("IO Error"); } fn stop_inner(&mut self, stop_time: Instant, stop_symbol: Option) { self.sender .send((stop_time, stop_symbol)) .expect("Could not stop spinner thread."); self.join.take().unwrap().join().unwrap(); } } spinners-4.1.1/src/utils/mod.rs000064400000000000000000000001241046102023000145410ustar 00000000000000pub mod spinner_data; pub mod spinner_names; pub mod spinners_data; pub mod stream; spinners-4.1.1/src/utils/spinner_data.rs000064400000000000000000000001551046102023000164350ustar 00000000000000#[derive(Debug, Clone)] pub struct SpinnerData { pub frames: Vec<&'static str>, pub interval: u16, } spinners-4.1.1/src/utils/spinner_names.rs000064400000000000000000000023041046102023000166250ustar 00000000000000use strum::{Display, EnumIter, EnumString}; #[derive(Debug, Clone, EnumIter, Display, EnumString)] pub enum SpinnerNames { Dots, Dots2, Dots3, Dots4, Dots5, Dots6, Dots7, Dots8, Dots9, Dots10, Dots11, Dots12, Dots8Bit, Line, Line2, Pipe, SimpleDots, SimpleDotsScrolling, Star, Star2, Flip, Hamburger, GrowVertical, GrowHorizontal, Balloon, Balloon2, Noise, Bounce, BoxBounce, BoxBounce2, Triangle, Arc, Circle, SquareCorners, CircleQuarters, CircleHalves, Squish, Toggle, Toggle2, Toggle3, Toggle4, Toggle5, Toggle6, Toggle7, Toggle8, Toggle9, Toggle10, Toggle11, Toggle12, Toggle13, Arrow, Arrow2, Arrow3, BouncingBar, BouncingBall, Smiley, Monkey, Hearts, Clock, Earth, Material, Moon, Runner, Pong, Shark, Dqpb, Weather, Christmas, Grenade, Point, Layer, BetaWave, FingerDance, FistBump, SoccerHeader, Mindblown, Speaker, OrangePulse, BluePulse, OrangeBluePulse, TimeTravel, Aesthetic, } spinners-4.1.1/src/utils/spinners_data.rs000064400000000000000000000747641046102023000166410ustar 00000000000000use crate::utils::spinner_data::SpinnerData; use lazy_static::lazy_static; use maplit::{self, hashmap}; use std::collections::HashMap; lazy_static! { pub static ref SPINNERS: HashMap = { hashmap! { "Dots".into() => SpinnerData {frames: vec![ "โ ‹", "โ ™", "โ น", "โ ธ", "โ ผ", "โ ด", "โ ฆ", "โ ง", "โ ‡", "โ " ], interval: 80}, "Dots2".into() => SpinnerData {frames: vec![ "โฃพ", "โฃฝ", "โฃป", "โขฟ", "โกฟ", "โฃŸ", "โฃฏ", "โฃท" ], interval: 80}, "Dots3".into() => SpinnerData {frames: vec![ "โ ‹", "โ ™", "โ š", "โ ž", "โ –", "โ ฆ", "โ ด", "โ ฒ", "โ ณ", "โ “" ], interval: 80}, "Dots4".into() => SpinnerData {frames: vec![ "โ „", "โ †", "โ ‡", "โ ‹", "โ ™", "โ ธ", "โ ฐ", "โ  ", "โ ฐ", "โ ธ", "โ ™", "โ ‹", "โ ‡", "โ †" ], interval: 80}, "Dots5".into() => SpinnerData {frames: vec![ "โ ‹", "โ ™", "โ š", "โ ’", "โ ‚", "โ ‚", "โ ’", "โ ฒ", "โ ด", "โ ฆ", "โ –", "โ ’", "โ ", "โ ", "โ ’", "โ “", "โ ‹" ], interval: 80}, "Dots6".into() => SpinnerData {frames: vec![ "โ ", "โ ‰", "โ ™", "โ š", "โ ’", "โ ‚", "โ ‚", "โ ’", "โ ฒ", "โ ด", "โ ค", "โ „", "โ „", "โ ค", "โ ด", "โ ฒ", "โ ’", "โ ‚", "โ ‚", "โ ’", "โ š", "โ ™", "โ ‰", "โ " ], interval: 80}, "Dots7".into() => SpinnerData {frames: vec![ "โ ˆ", "โ ‰", "โ ‹", "โ “", "โ ’", "โ ", "โ ", "โ ’", "โ –", "โ ฆ", "โ ค", "โ  ", "โ  ", "โ ค", "โ ฆ", "โ –", "โ ’", "โ ", "โ ", "โ ’", "โ “", "โ ‹", "โ ‰", "โ ˆ" ], interval: 80}, "Dots8".into() => SpinnerData {frames: vec![ "โ ", "โ ", "โ ‰", "โ ™", "โ š", "โ ’", "โ ‚", "โ ‚", "โ ’", "โ ฒ", "โ ด", "โ ค", "โ „", "โ „", "โ ค", "โ  ", "โ  ", "โ ค", "โ ฆ", "โ –", "โ ’", "โ ", "โ ", "โ ’", "โ “", "โ ‹", "โ ‰", "โ ˆ", "โ ˆ" ], interval: 80}, "Dots9".into() => SpinnerData {frames: vec![ "โขน", "โขบ", "โขผ", "โฃธ", "โฃ‡", "โกง", "โก—", "โก" ], interval: 80}, "Dots10".into() => SpinnerData {frames: vec![ "โข„", "โข‚", "โข", "โก", "โกˆ", "โก", "โก " ], interval: 80}, "Dots11".into() => SpinnerData {frames: vec![ "โ ", "โ ‚", "โ „", "โก€", "โข€", "โ  ", "โ ", "โ ˆ" ], interval: 100}, "Dots12".into() => SpinnerData {frames: vec![ "โข€โ €", "โก€โ €", "โ „โ €", "โข‚โ €", "โก‚โ €", "โ …โ €", "โขƒโ €", "โกƒโ €", "โ โ €", "โข‹โ €", "โก‹โ €", "โ โ ", "โข‹โ ", "โก‹โ ", "โ โ ‰", "โ ‹โ ‰", "โ ‹โ ‰", "โ ‰โ ™", "โ ‰โ ™", "โ ‰โ ฉ", "โ ˆโข™", "โ ˆโก™", "โขˆโ ฉ", "โก€โข™", "โ „โก™", "โข‚โ ฉ", "โก‚โข˜", "โ …โก˜", "โขƒโ จ", "โกƒโข", "โ โก", "โข‹โ  ", "โก‹โข€", "โ โก", "โข‹โ ", "โก‹โ ", "โ โ ‰", "โ ‹โ ‰", "โ ‹โ ‰", "โ ‰โ ™", "โ ‰โ ™", "โ ‰โ ฉ", "โ ˆโข™", "โ ˆโก™", "โ ˆโ ฉ", "โ €โข™", "โ €โก™", "โ €โ ฉ", "โ €โข˜", "โ €โก˜", "โ €โ จ", "โ €โข", "โ €โก", "โ €โ  ", "โ €โข€", "โ €โก€" ], interval: 80}, "Dots8Bit".into() => SpinnerData {frames: vec![ "โ €", "โ ", "โ ‚", "โ ƒ", "โ „", "โ …", "โ †", "โ ‡", "โก€", "โก", "โก‚", "โกƒ", "โก„", "โก…", "โก†", "โก‡", "โ ˆ", "โ ‰", "โ Š", "โ ‹", "โ Œ", "โ ", "โ Ž", "โ ", "โกˆ", "โก‰", "โกŠ", "โก‹", "โกŒ", "โก", "โกŽ", "โก", "โ ", "โ ‘", "โ ’", "โ “", "โ ”", "โ •", "โ –", "โ —", "โก", "โก‘", "โก’", "โก“", "โก”", "โก•", "โก–", "โก—", "โ ˜", "โ ™", "โ š", "โ ›", "โ œ", "โ ", "โ ž", "โ Ÿ", "โก˜", "โก™", "โกš", "โก›", "โกœ", "โก", "โกž", "โกŸ", "โ  ", "โ ก", "โ ข", "โ ฃ", "โ ค", "โ ฅ", "โ ฆ", "โ ง", "โก ", "โกก", "โกข", "โกฃ", "โกค", "โกฅ", "โกฆ", "โกง", "โ จ", "โ ฉ", "โ ช", "โ ซ", "โ ฌ", "โ ญ", "โ ฎ", "โ ฏ", "โกจ", "โกฉ", "โกช", "โกซ", "โกฌ", "โกญ", "โกฎ", "โกฏ", "โ ฐ", "โ ฑ", "โ ฒ", "โ ณ", "โ ด", "โ ต", "โ ถ", "โ ท", "โกฐ", "โกฑ", "โกฒ", "โกณ", "โกด", "โกต", "โกถ", "โกท", "โ ธ", "โ น", "โ บ", "โ ป", "โ ผ", "โ ฝ", "โ พ", "โ ฟ", "โกธ", "โกน", "โกบ", "โกป", "โกผ", "โกฝ", "โกพ", "โกฟ", "โข€", "โข", "โข‚", "โขƒ", "โข„", "โข…", "โข†", "โข‡", "โฃ€", "โฃ", "โฃ‚", "โฃƒ", "โฃ„", "โฃ…", "โฃ†", "โฃ‡", "โขˆ", "โข‰", "โขŠ", "โข‹", "โขŒ", "โข", "โขŽ", "โข", "โฃˆ", "โฃ‰", "โฃŠ", "โฃ‹", "โฃŒ", "โฃ", "โฃŽ", "โฃ", "โข", "โข‘", "โข’", "โข“", "โข”", "โข•", "โข–", "โข—", "โฃ", "โฃ‘", "โฃ’", "โฃ“", "โฃ”", "โฃ•", "โฃ–", "โฃ—", "โข˜", "โข™", "โขš", "โข›", "โขœ", "โข", "โขž", "โขŸ", "โฃ˜", "โฃ™", "โฃš", "โฃ›", "โฃœ", "โฃ", "โฃž", "โฃŸ", "โข ", "โขก", "โขข", "โขฃ", "โขค", "โขฅ", "โขฆ", "โขง", "โฃ ", "โฃก", "โฃข", "โฃฃ", "โฃค", "โฃฅ", "โฃฆ", "โฃง", "โขจ", "โขฉ", "โขช", "โขซ", "โขฌ", "โขญ", "โขฎ", "โขฏ", "โฃจ", "โฃฉ", "โฃช", "โฃซ", "โฃฌ", "โฃญ", "โฃฎ", "โฃฏ", "โขฐ", "โขฑ", "โขฒ", "โขณ", "โขด", "โขต", "โขถ", "โขท", "โฃฐ", "โฃฑ", "โฃฒ", "โฃณ", "โฃด", "โฃต", "โฃถ", "โฃท", "โขธ", "โขน", "โขบ", "โขป", "โขผ", "โขฝ", "โขพ", "โขฟ", "โฃธ", "โฃน", "โฃบ", "โฃป", "โฃผ", "โฃฝ", "โฃพ", "โฃฟ" ], interval: 80}, "Line".into() => SpinnerData {frames: vec![ "-", "\\", "|", "/" ], interval: 130}, "Line2".into() => SpinnerData {frames: vec![ "โ ‚", "-", "โ€“", "โ€”", "โ€“", "-" ], interval: 100}, "Pipe".into() => SpinnerData {frames: vec![ "โ”ค", "โ”˜", "โ”ด", "โ””", "โ”œ", "โ”Œ", "โ”ฌ", "โ”" ], interval: 100}, "SimpleDots".into() => SpinnerData {frames: vec![ ". ", ".. ", "...", " " ], interval: 400}, "SimpleDotsScrolling".into() => SpinnerData {frames: vec![ ". ", ".. ", "...", " ..", " .", " " ], interval: 200}, "Star".into() => SpinnerData {frames: vec![ "โœถ", "โœธ", "โœน", "โœบ", "โœน", "โœท" ], interval: 70}, "Star2".into() => SpinnerData {frames: vec![ "+", "x", "*" ], interval: 80}, "Flip".into() => SpinnerData {frames: vec![ "_", "_", "_", "-", "`", "`", "'", "ยด", "-", "_", "_", "_" ], interval: 70}, "Hamburger".into() => SpinnerData {frames: vec![ "โ˜ฑ", "โ˜ฒ", "โ˜ด" ], interval: 100}, "GrowVertical".into() => SpinnerData {frames: vec![ "โ–", "โ–ƒ", "โ–„", "โ–…", "โ–†", "โ–‡", "โ–†", "โ–…", "โ–„", "โ–ƒ" ], interval: 120}, "GrowHorizontal".into() => SpinnerData {frames: vec![ "โ–", "โ–Ž", "โ–", "โ–Œ", "โ–‹", "โ–Š", "โ–‰", "โ–Š", "โ–‹", "โ–Œ", "โ–", "โ–Ž" ], interval: 120}, "Balloon".into() => SpinnerData {frames: vec![ " ", ".", "o", "O", "@", "*", " " ], interval: 140}, "Balloon2".into() => SpinnerData {frames: vec![ ".", "o", "O", "ยฐ", "O", "o", "." ], interval: 120}, "Noise".into() => SpinnerData {frames: vec![ "โ–“", "โ–’", "โ–‘" ], interval: 100}, "Bounce".into() => SpinnerData {frames: vec![ "โ ", "โ ‚", "โ „", "โ ‚" ], interval: 120}, "BoxBounce".into() => SpinnerData {frames: vec![ "โ––", "โ–˜", "โ–", "โ–—" ], interval: 120}, "BoxBounce2".into() => SpinnerData {frames: vec![ "โ–Œ", "โ–€", "โ–", "โ–„" ], interval: 100}, "Triangle".into() => SpinnerData {frames: vec![ "โ—ข", "โ—ฃ", "โ—ค", "โ—ฅ" ], interval: 50}, "Arc".into() => SpinnerData {frames: vec![ "โ—œ", "โ— ", "โ—", "โ—ž", "โ—ก", "โ—Ÿ" ], interval: 100}, "Circle".into() => SpinnerData {frames: vec![ "โ—ก", "โŠ™", "โ— " ], interval: 120}, "SquareCorners".into() => SpinnerData {frames: vec![ "โ—ฐ", "โ—ณ", "โ—ฒ", "โ—ฑ" ], interval: 180}, "CircleQuarters".into() => SpinnerData {frames: vec![ "โ—ด", "โ—ท", "โ—ถ", "โ—ต" ], interval: 120}, "CircleHalves".into() => SpinnerData {frames: vec![ "โ—", "โ—“", "โ—‘", "โ—’" ], interval: 50}, "Squish".into() => SpinnerData {frames: vec![ "โ•ซ", "โ•ช" ], interval: 100}, "Toggle".into() => SpinnerData {frames: vec![ "โŠถ", "โŠท" ], interval: 250}, "Toggle2".into() => SpinnerData {frames: vec![ "โ–ซ", "โ–ช" ], interval: 80}, "Toggle3".into() => SpinnerData {frames: vec![ "โ–ก", "โ– " ], interval: 120}, "Toggle4".into() => SpinnerData {frames: vec![ "โ– ", "โ–ก", "โ–ช", "โ–ซ" ], interval: 100}, "Toggle5".into() => SpinnerData {frames: vec![ "โ–ฎ", "โ–ฏ" ], interval: 100}, "Toggle6".into() => SpinnerData {frames: vec![ "แ€", "แ€" ], interval: 300}, "Toggle7".into() => SpinnerData {frames: vec![ "โฆพ", "โฆฟ" ], interval: 80}, "Toggle8".into() => SpinnerData {frames: vec![ "โ—", "โ—Œ" ], interval: 100}, "Toggle9".into() => SpinnerData {frames: vec![ "โ—‰", "โ—Ž" ], interval: 100}, "Toggle10".into() => SpinnerData {frames: vec![ "ใŠ‚", "ใŠ€", "ใЁ" ], interval: 100}, "Toggle11".into() => SpinnerData {frames: vec![ "โง‡", "โง†" ], interval: 50}, "Toggle12".into() => SpinnerData {frames: vec![ "โ˜—", "โ˜–" ], interval: 120}, "Toggle13".into() => SpinnerData {frames: vec![ "=", "*", "-" ], interval: 80}, "Arrow".into() => SpinnerData {frames: vec![ "โ†", "โ†–", "โ†‘", "โ†—", "โ†’", "โ†˜", "โ†“", "โ†™" ], interval: 100}, "Arrow2".into() => SpinnerData {frames: vec![ "โฌ†๏ธ ", "โ†—๏ธ ", "โžก๏ธ ", "โ†˜๏ธ ", "โฌ‡๏ธ ", "โ†™๏ธ ", "โฌ…๏ธ ", "โ†–๏ธ " ], interval: 80}, "Arrow3".into() => SpinnerData {frames: vec![ "โ–นโ–นโ–นโ–นโ–น", "โ–ธโ–นโ–นโ–นโ–น", "โ–นโ–ธโ–นโ–นโ–น", "โ–นโ–นโ–ธโ–นโ–น", "โ–นโ–นโ–นโ–ธโ–น", "โ–นโ–นโ–นโ–นโ–ธ" ], interval: 120}, "BouncingBar".into() => SpinnerData {frames: vec![ "[ ]", "[= ]", "[== ]", "[=== ]", "[ ===]", "[ ==]", "[ =]", "[ ]", "[ =]", "[ ==]", "[ ===]", "[====]", "[=== ]", "[== ]", "[= ]" ], interval: 80}, "BouncingBall".into() => SpinnerData {frames: vec![ "( โ— )", "( โ— )", "( โ— )", "( โ— )", "( โ—)", "( โ— )", "( โ— )", "( โ— )", "( โ— )", "(โ— )" ], interval: 80}, "Smiley".into() => SpinnerData {frames: vec![ "๐Ÿ˜„ ", "๐Ÿ˜ " ], interval: 200}, "Monkey".into() => SpinnerData {frames: vec![ "๐Ÿ™ˆ ", "๐Ÿ™ˆ ", "๐Ÿ™‰ ", "๐Ÿ™Š " ], interval: 300}, "Hearts".into() => SpinnerData {frames: vec![ "๐Ÿ’› ", "๐Ÿ’™ ", "๐Ÿ’œ ", "๐Ÿ’š ", "โค๏ธ " ], interval: 100}, "Clock".into() => SpinnerData {frames: vec![ "๐Ÿ•› ", "๐Ÿ• ", "๐Ÿ•‘ ", "๐Ÿ•’ ", "๐Ÿ•“ ", "๐Ÿ•” ", "๐Ÿ•• ", "๐Ÿ•– ", "๐Ÿ•— ", "๐Ÿ•˜ ", "๐Ÿ•™ ", "๐Ÿ•š " ], interval: 100}, "Earth".into() => SpinnerData {frames: vec![ "๐ŸŒ ", "๐ŸŒŽ ", "๐ŸŒ " ], interval: 180}, "Material".into() => SpinnerData {frames: vec![ "โ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–", "โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–", "โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–", "โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–", "โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–", "โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–", "โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–", "โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–", "โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–", "โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆ", "โ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆ", "โ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆ", "โ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆ", "โ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆ", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆ", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆ", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆ", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–", "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–โ–", "โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–", "โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–โ–", "โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–โ–", "โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–", "โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–", "โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆโ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–ˆ", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–", "โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–โ–" ], interval: 17}, "Moon".into() => SpinnerData {frames: vec![ "๐ŸŒ‘ ", "๐ŸŒ’ ", "๐ŸŒ“ ", "๐ŸŒ” ", "๐ŸŒ• ", "๐ŸŒ– ", "๐ŸŒ— ", "๐ŸŒ˜ " ], interval: 80}, "Runner".into() => SpinnerData {frames: vec![ "๐Ÿšถ ", "๐Ÿƒ " ], interval: 140}, "Pong".into() => SpinnerData {frames: vec![ "โ–โ ‚ โ–Œ", "โ–โ ˆ โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ   โ–Œ", "โ– โก€ โ–Œ", "โ– โ   โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ ˆ โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ   โ–Œ", "โ– โก€ โ–Œ", "โ– โ   โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ ˆ โ–Œ", "โ– โ ‚โ–Œ", "โ– โ  โ–Œ", "โ– โก€โ–Œ", "โ– โ   โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ ˆ โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ   โ–Œ", "โ– โก€ โ–Œ", "โ– โ   โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ ˆ โ–Œ", "โ– โ ‚ โ–Œ", "โ– โ   โ–Œ", "โ– โก€ โ–Œ", "โ–โ   โ–Œ" ], interval: 80}, "Shark".into() => SpinnerData {frames: vec![ "โ–|\\____________โ–Œ", "โ–_|\\___________โ–Œ", "โ–__|\\__________โ–Œ", "โ–___|\\_________โ–Œ", "โ–____|\\________โ–Œ", "โ–_____|\\_______โ–Œ", "โ–______|\\______โ–Œ", "โ–_______|\\_____โ–Œ", "โ–________|\\____โ–Œ", "โ–_________|\\___โ–Œ", "โ–__________|\\__โ–Œ", "โ–___________|\\_โ–Œ", "โ–____________|\\โ–Œ", "โ–____________/|โ–Œ", "โ–___________/|_โ–Œ", "โ–__________/|__โ–Œ", "โ–_________/|___โ–Œ", "โ–________/|____โ–Œ", "โ–_______/|_____โ–Œ", "โ–______/|______โ–Œ", "โ–_____/|_______โ–Œ", "โ–____/|________โ–Œ", "โ–___/|_________โ–Œ", "โ–__/|__________โ–Œ", "โ–_/|___________โ–Œ", "โ–/|____________โ–Œ" ], interval: 120}, "Dqpb".into() => SpinnerData {frames: vec![ "d", "q", "p", "b" ], interval: 100}, "Weather".into() => SpinnerData {frames: vec![ "โ˜€๏ธ ", "โ˜€๏ธ ", "โ˜€๏ธ ", "๐ŸŒค ", "โ›…๏ธ ", "๐ŸŒฅ ", "โ˜๏ธ ", "๐ŸŒง ", "๐ŸŒจ ", "๐ŸŒง ", "๐ŸŒจ ", "๐ŸŒง ", "๐ŸŒจ ", "โ›ˆ ", "๐ŸŒจ ", "๐ŸŒง ", "๐ŸŒจ ", "โ˜๏ธ ", "๐ŸŒฅ ", "โ›…๏ธ ", "๐ŸŒค ", "โ˜€๏ธ ", "โ˜€๏ธ " ], interval: 100}, "Christmas".into() => SpinnerData {frames: vec![ "๐ŸŒฒ", "๐ŸŽ„" ], interval: 400}, "Grenade".into() => SpinnerData {frames: vec![ "ุŒ ", "โ€ฒ ", " ยด ", " โ€พ ", " โธŒ", " โธŠ", " |", " โŽ", " โ•", " เทด ", " โ“", " ", " ", " " ], interval: 80}, "Point".into() => SpinnerData {frames: vec![ "โˆ™โˆ™โˆ™", "โ—โˆ™โˆ™", "โˆ™โ—โˆ™", "โˆ™โˆ™โ—", "โˆ™โˆ™โˆ™" ], interval: 125}, "Layer".into() => SpinnerData {frames: vec![ "-", "=", "โ‰ก" ], interval: 150}, "BetaWave".into() => SpinnerData {frames: vec![ "ฯฮฒฮฒฮฒฮฒฮฒฮฒ", "ฮฒฯฮฒฮฒฮฒฮฒฮฒ", "ฮฒฮฒฯฮฒฮฒฮฒฮฒ", "ฮฒฮฒฮฒฯฮฒฮฒฮฒ", "ฮฒฮฒฮฒฮฒฯฮฒฮฒ", "ฮฒฮฒฮฒฮฒฮฒฯฮฒ", "ฮฒฮฒฮฒฮฒฮฒฮฒฯ" ], interval: 80}, "FingerDance".into() => SpinnerData {frames: vec![ "๐Ÿค˜ ", "๐ŸคŸ ", "๐Ÿ–– ", "โœ‹ ", "๐Ÿคš ", "๐Ÿ‘† " ], interval: 160}, "FistBump".into() => SpinnerData {frames: vec![ "๐Ÿคœใ€€ใ€€ใ€€ใ€€๐Ÿค› ", "๐Ÿคœใ€€ใ€€ใ€€ใ€€๐Ÿค› ", "๐Ÿคœใ€€ใ€€ใ€€ใ€€๐Ÿค› ", "ใ€€๐Ÿคœใ€€ใ€€๐Ÿค›ใ€€ ", "ใ€€ใ€€๐Ÿคœ๐Ÿค›ใ€€ใ€€ ", "ใ€€๐Ÿคœโœจ๐Ÿค›ใ€€ใ€€ ", "๐Ÿคœใ€€โœจใ€€๐Ÿค›ใ€€ " ], interval: 80}, "SoccerHeader".into() => SpinnerData {frames: vec![ " ๐Ÿง‘โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ ", "๐Ÿง‘ โšฝ๏ธ ๐Ÿง‘ " ], interval: 80}, "Mindblown".into() => SpinnerData {frames: vec![ "๐Ÿ˜ ", "๐Ÿ˜ ", "๐Ÿ˜ฎ ", "๐Ÿ˜ฎ ", "๐Ÿ˜ฆ ", "๐Ÿ˜ฆ ", "๐Ÿ˜ง ", "๐Ÿ˜ง ", "๐Ÿคฏ ", "๐Ÿ’ฅ ", "โœจ ", "ใ€€ ", "ใ€€ ", "ใ€€ " ], interval: 160}, "Speaker".into() => SpinnerData {frames: vec![ "๐Ÿ”ˆ ", "๐Ÿ”‰ ", "๐Ÿ”Š ", "๐Ÿ”‰ " ], interval: 160}, "OrangePulse".into() => SpinnerData {frames: vec![ "๐Ÿ”ธ ", "๐Ÿ”ถ ", "๐ŸŸ  ", "๐ŸŸ  ", "๐Ÿ”ถ " ], interval: 100}, "BluePulse".into() => SpinnerData {frames: vec![ "๐Ÿ”น ", "๐Ÿ”ท ", "๐Ÿ”ต ", "๐Ÿ”ต ", "๐Ÿ”ท " ], interval: 100}, "OrangeBluePulse".into() => SpinnerData {frames: vec![ "๐Ÿ”ธ ", "๐Ÿ”ถ ", "๐ŸŸ  ", "๐ŸŸ  ", "๐Ÿ”ถ ", "๐Ÿ”น ", "๐Ÿ”ท ", "๐Ÿ”ต ", "๐Ÿ”ต ", "๐Ÿ”ท " ], interval: 100}, "TimeTravel".into() => SpinnerData {frames: vec![ "๐Ÿ•› ", "๐Ÿ•š ", "๐Ÿ•™ ", "๐Ÿ•˜ ", "๐Ÿ•— ", "๐Ÿ•– ", "๐Ÿ•• ", "๐Ÿ•” ", "๐Ÿ•“ ", "๐Ÿ•’ ", "๐Ÿ•‘ ", "๐Ÿ• " ], interval: 100}, "Aesthetic".into() => SpinnerData {frames: vec![ "โ–ฐโ–ฑโ–ฑโ–ฑโ–ฑโ–ฑโ–ฑ", "โ–ฐโ–ฐโ–ฑโ–ฑโ–ฑโ–ฑโ–ฑ", "โ–ฐโ–ฐโ–ฐโ–ฑโ–ฑโ–ฑโ–ฑ", "โ–ฐโ–ฐโ–ฐโ–ฐโ–ฑโ–ฑโ–ฑ", "โ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฑโ–ฑ", "โ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฑ", "โ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฐ", "โ–ฐโ–ฑโ–ฑโ–ฑโ–ฑโ–ฑโ–ฑ" ], interval: 80} } }; } spinners-4.1.1/src/utils/stream.rs000064400000000000000000000045731046102023000152710ustar 00000000000000use std::{io::{Write, stdout, stderr, Result}, time::Instant}; /// Handles the Printing logic for the Spinner #[derive(Default, Copy, Clone)] pub enum Stream { #[default] Stderr, Stdout, } impl Stream { /// Matches on self and returns the internal writer fn match_target(&self) -> Box { match self { Self::Stderr => Box::new(stderr()), Self::Stdout => Box::new(stdout()) } } /// Writes the message without duration fn print_message( writer: &mut Box, frame: &str, message: &str) -> Result<()> { write!(writer, "\r{} {}", frame, message)?; writer.flush() } /// Writes the message with the duration fn print_message_with_duration( writer: &mut Box, frame: &str, message: &str, start_time: Instant, stop_time: Option) -> Result<()> { let now = stop_time.unwrap_or_else(Instant::now); let duration = now.duration_since(start_time).as_secs_f64(); write!(writer, "\r{}{:>10.3} s\t{}", frame, duration, message)?; writer.flush() } /// Writes the current message and optionally prints the durations pub fn write( &self, frame: &str, message: &str, start_time: Option, stop_time: Option) -> Result<()> { let mut writer = self.match_target(); match start_time { None => Self::print_message( &mut writer, frame, message)?, Some(start_time) => Self::print_message_with_duration( &mut writer, frame, message, start_time, stop_time)? }; Ok(()) } /// Handles the stopping logic given an optional message and symbol pub fn stop( &self, message: Option<&str>, symbol: Option<&str>) -> Result<()> { let mut writer = self.match_target(); match (message, symbol) { // persist with symbol and message (Some(m), Some(s)) => writeln!(writer, "\x1b[2K\r{} {}", s, m), // persist with message only (Some(m), None) => writeln!(writer, "\x1b[2K\r{}", m), // simple newline _ => writeln!(writer) }?; writer.flush() } }