diff --git a/Cargo.toml b/Cargo.toml
index 34c9a9b..fc33a19 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,11 +26,12 @@ test = true
[features]
-default = ["spinner", "progressbar", "menu"]
+default = ["spinner", "progressbar", "menu", "log"]
spinner = []
progressbar = []
-menu = []
+menu = ["spinner"]
+log = []
[dependencies]
@@ -38,6 +39,9 @@ crossterm = "0.27.0"
supports-color = "3.0.0"
lazy_static = "1.4.0"
regex = "1.10.4"
+log = { version = "0.4.21", features = ["std"] }
+chrono = "0.4.38"
+
[dev-dependencies]
rand = "0.8.5"
diff --git a/README.md b/README.md
index 857a389..b9fcc4f 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
Yet Another Spinner Lib
-
Elevate your Rust command-line interfaces with 100+ spinner animations and Progress Bars + multiline support
+
Upgrade your Rust CLIs with 100+ spinner animations, progress bars, and multiline support, plus user input validation, logging, and automatic requirement checks
diff --git a/examples/all.rs b/examples/all.rs
index 3b5523e..50731ef 100644
--- a/examples/all.rs
+++ b/examples/all.rs
@@ -8,7 +8,8 @@ static TOTAL_ANIMATIONS: AtomicUsize = AtomicUsize::new(0);
macro_rules! test_predefined_animation {
($animation:expr, $text:expr) => {{
- let custom = MultiSpinner::new($animation);
+ let custom = MultiSpinner::new();
+ custom.add($animation);
custom.run_all();
custom.set_text(&custom.get_last(), $text.to_string());
sleep(Duration::from_secs(5));
diff --git a/examples/custom_frames.rs b/examples/custom_frames.rs
index 96d4842..d1c52b3 100644
--- a/examples/custom_frames.rs
+++ b/examples/custom_frames.rs
@@ -15,7 +15,8 @@ fn main() {
};
// create a MultiSpinner instance using the new custom animation
- let spinner = MultiSpinner::new(custom_frames);
+ let spinner = MultiSpinner::new();
+ spinner.add(custom_frames);
spinner.run_all();
// wait for 5 seconds to showcase the loading animation with the custom animation
diff --git a/examples/log.rs b/examples/log.rs
new file mode 100644
index 0000000..2b16ce7
--- /dev/null
+++ b/examples/log.rs
@@ -0,0 +1,42 @@
+use log::Level;
+
+use zenity::log::Logger;
+
+mod foo {
+ mod bar {
+ pub fn run() {
+ log::error!("[bar] error");
+ log::warn!("[bar] warn");
+ log::info!("[bar] info");
+ log::debug!("[bar] debug");
+ log::trace!("[bar] trace");
+ }
+ }
+
+ pub fn run() {
+ log::error!("[foo] error");
+ log::warn!("[foo] warn");
+ log::info!("[foo] info");
+ log::debug!("[foo] debug");
+ log::trace!("[foo] trace");
+ bar::run();
+ }
+}
+
+fn main() {
+ // Set the custom logger as the global logger
+ Logger::new()
+ .with_env("TEST_LEVEL")
+ .with_arg()
+ .set_log_level(Level::Trace)
+ .init()
+ .unwrap();
+
+ // Now you can use log::debug! to output messages
+ log::error!("[root] This is a error message");
+ log::warn!("[root] This is a warn message");
+ log::info!("[root] This is a info message");
+ log::debug!("[root] This is a debug message");
+ log::trace!("[root] This is a trace message");
+ foo::run();
+}
diff --git a/examples/requirements.rs b/examples/requirements.rs
new file mode 100644
index 0000000..d5f31e6
--- /dev/null
+++ b/examples/requirements.rs
@@ -0,0 +1,8 @@
+use zenity::menu::requirements;
+
+fn main() {
+ match requirements::verify_requirements(vec!["uidmap", "bridge-utils"]) {
+ Ok(_) => println!("All required packages are installed."),
+ Err(err) => eprintln!("Error verifying requirements: {}", err),
+ }
+}
diff --git a/src/color.rs b/src/color.rs
index e5727c9..f499ada 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -135,20 +135,24 @@ impl CliColorConfig {
}
}
+ /// parse args to check for --color=always|auto|never
+
/// parse args to check for --color=always|auto|never
fn parse_arguments(args: &[String]) -> ColorOption {
- if args.len() > 1 {
- let arg = &args[1];
- return match arg.as_str() {
- "--color=always" => ColorOption::Always,
- "--color=never" => ColorOption::Never,
- _ => {
- // removed error message print
- ColorOption::Auto
- }
- };
+ for arg in args.iter() {
+ if arg.starts_with("--color=") {
+ return match arg.split('=').nth(1) {
+ Some("always") => ColorOption::Always,
+ Some("auto") => ColorOption::Auto,
+ Some("never") => ColorOption::Never,
+ _ => {
+ ColorOption::Auto // Default to Auto in case of invalid option
+ }
+ };
+ }
}
+ // If no color option is found, default to Auto
ColorOption::Auto
}
diff --git a/src/lib.rs b/src/lib.rs
index c5159ae..c9443f2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -92,6 +92,9 @@ pub mod progress;
#[cfg(feature = "spinner")]
pub mod spinner;
+#[cfg(feature = "log")]
+pub mod log;
+
// Crate
pub(crate) mod iterators;
pub(crate) mod terminal;
diff --git a/src/log/mod.rs b/src/log/mod.rs
new file mode 100644
index 0000000..d721f03
--- /dev/null
+++ b/src/log/mod.rs
@@ -0,0 +1,277 @@
+//! The `log` module provides a customizable logger implementation.
+//!
+//! This logger allows customizing log output format and log levels, and it supports colorized output if enabled.
+//!
+//! # Examples
+//!
+//! ```
+//! use zenity::log::Logger;
+//! use log::Level;
+//!
+//! // Initialize logger with default settings
+//! let logger = Logger::new().init().unwrap();
+//! ```
+//! ```
+//! # use zenity::log::Logger;
+//! # use log::Level;
+//! #
+//! // Set log level based on environment variable
+//! let logger = Logger::new().with_env("LOG_LEVEL").init().unwrap();
+//! ```
+//! ```
+//! # use zenity::log::Logger;
+//! # use log::Level;
+//! #
+//! // Set log level based on command-line argument
+//! let logger = Logger::new().with_arg().init().unwrap();
+//! ```
+//! ```
+//! # use zenity::log::Logger;
+//! # use log::Level;
+//! #
+//! // Set log level directly
+//! let logger = Logger::new().set_log_level(Level::Debug).init().unwrap();
+//! ```
+
+use std::env;
+use std::io::{stdout, Write};
+
+use chrono::Local;
+use crossterm::queue;
+use crossterm::style::{Attribute, ContentStyle};
+use log::{Level, Metadata, Record, SetLoggerError};
+
+use crate::style::combine_attributes;
+use crate::{color::ENABLE_COLOR, style, style::Color};
+
+macro_rules! enable_color {
+ ($stdout:expr, $foreground_color:expr) => {
+ if *ENABLE_COLOR {
+ queue!(
+ $stdout,
+ style::SetStyle(ContentStyle {
+ foreground_color: Some($foreground_color),
+ background_color: None,
+ underline_color: None,
+ attributes: combine_attributes(&[&Attribute::Italic]),
+ }),
+ )
+ .unwrap();
+ }
+ };
+}
+
+// Define a custom logger
+struct MyLogger;
+
+impl log::Log for MyLogger {
+ fn enabled(&self, metadata: &Metadata) -> bool {
+ // This logger will be enabled for all levels based on the configured log level
+ metadata.level() <= log::max_level()
+ }
+
+ fn log(&self, record: &Record) {
+ // Customize the log output format here
+ let current_time = Local::now().format("%Y-%m-%d %H:%M:%S");
+ let level_str = format!("{}", record.level());
+ let padded_level_str = format!("{:^5}", level_str); // Center-align the level string within a width of 5
+ let mut stdout = stdout();
+
+ enable_color!(stdout, Color::DarkGrey);
+
+ queue!(
+ stdout,
+ style::Print(format!("{} ", current_time)),
+ style::ResetColor, // reset colors
+ )
+ .unwrap();
+
+ if *ENABLE_COLOR {
+ let level_color = match record.level() {
+ Level::Error => ContentStyle {
+ foreground_color: Some(Color::Red),
+ background_color: None,
+ underline_color: None,
+ attributes: combine_attributes(&[&Attribute::Bold]),
+ },
+ Level::Warn => ContentStyle {
+ foreground_color: Some(Color::Yellow),
+ background_color: None,
+ underline_color: None,
+ attributes: combine_attributes(&[&Attribute::Bold]),
+ },
+ Level::Info => ContentStyle {
+ foreground_color: Some(Color::Green),
+ background_color: None,
+ underline_color: None,
+ attributes: combine_attributes(&[&Attribute::Bold]),
+ },
+ Level::Debug => ContentStyle {
+ foreground_color: Some(Color::Blue),
+ background_color: None,
+ underline_color: None,
+ attributes: combine_attributes(&[&Attribute::Bold]),
+ },
+ Level::Trace => ContentStyle {
+ foreground_color: Some(Color::Magenta),
+ background_color: None,
+ underline_color: None,
+ attributes: combine_attributes(&[&Attribute::Bold]),
+ },
+ };
+
+ queue!(stdout, style::SetStyle(level_color),).unwrap();
+ }
+
+ queue!(stdout, style::Print(&padded_level_str), style::ResetColor,).unwrap();
+
+ enable_color!(stdout, Color::DarkGrey);
+
+ queue!(
+ stdout,
+ style::Print(format!(
+ " ({}:{:?}):",
+ record.target(),
+ record.line().unwrap()
+ )),
+ style::ResetColor,
+ )
+ .unwrap();
+
+ queue!(
+ stdout,
+ style::Print(format!(" {}", record.args())),
+ style::ResetColor,
+ )
+ .unwrap();
+
+ queue!(stdout, style::Print("\n")).unwrap();
+
+ stdout.flush().unwrap();
+ }
+
+ fn flush(&self) {}
+}
+
+/// Implement a builder pattern for initializing the logger
+pub struct Logger {
+ log_level: Level,
+}
+
+impl Default for Logger {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Logger {
+ /// Constructs a new `Logger` with default log level `Info`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zenity::log::Logger;
+ ///
+ /// let logger = Logger::new();
+ /// ```
+ pub fn new() -> Logger {
+ Logger {
+ log_level: Level::Info,
+ }
+ }
+
+ /// Initializes the logger with the custom formatter and log level based on environment variable.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zenity::log::Logger;
+ ///
+ /// let logger = Logger::new().with_env("LOG_LEVEL").init().unwrap();
+ /// ```
+ ///
+ /// # Notes
+ ///
+ /// This method sets the logger and the log level based on the environment variable or defaults to `Info`.
+ pub fn init(self) -> Result<(), SetLoggerError> {
+ log::set_logger(&MyLogger)?;
+ log::set_max_level(self.log_level.to_level_filter());
+ Ok(())
+ }
+
+ /// Sets log level based on the environment variable.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zenity::log::Logger;
+ ///
+ /// let logger = Logger::new().with_env("LOG_LEVEL");
+ /// ```
+ ///
+ /// # Notes
+ ///
+ /// This method checks the specified environment variable for the log level and updates if it's lower than the current level.
+ pub fn with_env(mut self, env_var: &str) -> Logger {
+ if let Ok(log_level) = env::var(env_var) {
+ if let Ok(level) = log_level.parse::
() {
+ if level < self.log_level {
+ self.log_level = level;
+ }
+ }
+ }
+ self
+ }
+
+ /// Sets log level based on the command-line argument if provided.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zenity::log::Logger;
+ ///
+ /// let logger = Logger::new().with_arg();
+ /// ```
+ ///
+ /// # Notes
+ ///
+ /// This method checks command-line arguments for the `--log-level=` option and updates the log level if provided and higher than the current level.
+ pub fn with_arg(mut self) -> Logger {
+ // Get command-line arguments
+ let args: Vec = env::args().collect();
+
+ // Check if the "--log-level=" option is provided in the arguments
+ if let Some(arg) = args.iter().find(|&arg| arg.starts_with("--log-level=")) {
+ // Extract the log level from the argument
+ if let Some(level_str) = arg.split('=').nth(1) {
+ if let Ok(level) = level_str.parse::() {
+ // Prefer the higher log level between the argument and the one from the environment variable
+ if level < self.log_level {
+ self.log_level = level;
+ }
+ }
+ }
+ }
+ self
+ }
+
+ /// Sets log level. This overwrites the current value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zenity::log::Logger;
+ /// use log::Level;
+ ///
+ /// let logger = Logger::new().set_log_level(Level::Debug);
+ /// ```
+ ///
+ /// # Notes
+ ///
+ /// This method directly sets the log level, overwriting the current value.
+ pub fn set_log_level(mut self, level: Level) -> Logger {
+ self.log_level = level;
+
+ self
+ }
+}
diff --git a/src/menu/mod.rs b/src/menu/mod.rs
index 5aa92b6..66561d6 100644
--- a/src/menu/mod.rs
+++ b/src/menu/mod.rs
@@ -3,6 +3,7 @@
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
pub mod input;
+pub mod requirements;
pub(crate) fn handle_key_input(buffer: &mut String, force: &mut bool) -> bool {
_handle_key_input(buffer, crossterm::event::read().unwrap(), force)
diff --git a/src/menu/requirements/mod.rs b/src/menu/requirements/mod.rs
new file mode 100644
index 0000000..b9b79d4
--- /dev/null
+++ b/src/menu/requirements/mod.rs
@@ -0,0 +1,99 @@
+//! The `requirements` module provides functions to verify that required packages are installed.
+//!
+//! # Examples
+//!
+//! ```
+//! use zenity::menu::requirements::verify_requirements;
+//!
+//! match verify_requirements(vec!["uidmap", "bridge-utils"]) {
+//! Ok(_) => println!("All required packages are installed."),
+//! Err(err) => eprintln!("Error verifying requirements: {}", err),
+//! }
+//! ```
+
+use std::time::Duration;
+use std::{io, thread};
+
+use crossterm::style::Color;
+
+use crate::spinner;
+use crate::spinner::Frames;
+use crate::style::StyledString;
+
+mod pckgm;
+
+// TODO: add windows support
+
+struct LoadingReq {
+ spinner_id: usize,
+ name: String,
+}
+
+/// Verifies that required packages are installed.
+///
+/// This function checks if certain packages are installed on the system.
+///
+/// # Examples
+///
+/// ```
+/// use zenity::menu::requirements::verify_requirements;
+///
+/// match verify_requirements(vec!["uidmap", "bridge-utils"]) {
+/// Ok(_) => println!("All required packages are installed."),
+/// Err(err) => eprintln!("Error verifying requirements: {}", err),
+/// }
+/// ```
+pub fn verify_requirements(packages_to_check: Vec<&str>) -> Result<(), io::Error> {
+ let mut reqs = Vec::new();
+ let spinner = spinner::MultiSpinner::new();
+
+ for package in packages_to_check {
+ let spinner_id = spinner.add(Frames::dot_spinner1());
+ spinner.set_styled_text(
+ &spinner_id,
+ StyledString::simple(package, Some(Color::Yellow), None, None),
+ );
+
+ reqs.push(LoadingReq {
+ spinner_id,
+ name: package.to_string(),
+ });
+ }
+
+ spinner.run_all();
+
+ // Check if each package is installed
+ for package in reqs {
+ spinner.set_styled_text(
+ &package.spinner_id,
+ StyledString::simple(
+ &format!("Checking if {} is installed...", &package.name),
+ Some(Color::Yellow),
+ None,
+ None,
+ ),
+ );
+
+ let (is_installed, msg) = match pckgm::is_package_installed(&package.name) {
+ Ok(_) => (true, format!("{} is installed\n", &package.name)),
+ Err(err) => (false, format!("{}", err)),
+ };
+
+ if is_installed {
+ spinner.set_styled_text(
+ &package.spinner_id,
+ StyledString::simple(&msg, Some(Color::Green), None, None),
+ )
+ } else {
+ spinner.set_styled_text(
+ &package.spinner_id,
+ StyledString::simple(&msg, Some(Color::Red), None, None),
+ )
+ }
+ spinner.stop(&package.spinner_id);
+
+ thread::sleep(Duration::from_secs(3));
+ }
+
+ Ok(())
+}
diff --git a/src/menu/requirements/pckgm.rs b/src/menu/requirements/pckgm.rs
new file mode 100644
index 0000000..a9718f3
--- /dev/null
+++ b/src/menu/requirements/pckgm.rs
@@ -0,0 +1,83 @@
+use std::io;
+use std::process::Command;
+
+use lazy_static::lazy_static;
+
+use crate::menu::requirements::pckgm;
+
+/// determine which package manager is available on the system
+///
+/// NOTES:
+/// - IDK if there is a better way to do this or maybe already a lib for this
+fn detect_package_manager() -> Option<&'static str> {
+ if which("apt-get").is_some() {
+ Some("apt")
+ } else if which("yum").is_some() {
+ Some("yum")
+ } else if which("dnf").is_some() {
+ Some("dnf")
+ } else if which("pacman").is_some() {
+ Some("pacman")
+ } else if which("brew").is_some() {
+ Some("brew")
+ } else if which("zypper").is_some() {
+ Some("zypper")
+ } else if which("apk").is_some() {
+ Some("apk")
+ } else {
+ None
+ }
+}
+
+/// Check if a command is available in the system's PATH
+fn which(command: &str) -> Option {
+ match Command::new("which").arg(command).output() {
+ Ok(output) if output.status.success() => {
+ Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
+ }
+ _ => None,
+ }
+}
+
+lazy_static! {
+ pub static ref PACKAGE_MANAGER: Option<&'static str> = detect_package_manager();
+}
+
+/// Check if a package is installed using the detected package manager
+pub(crate) fn is_package_installed(package: &str) -> Result<(), io::Error> {
+ let package_manager = match *pckgm::PACKAGE_MANAGER {
+ Some(pm) => pm,
+ None => {
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ "No package manager detected",
+ ))
+ }
+ };
+
+ let output = match package_manager {
+ "apt" => Command::new("dpkg-query").args(["-W", package]).output(),
+ "yum" => Command::new("rpm").args(["-q", package]).output(),
+ "dnf" => Command::new("dnf")
+ .args(["list", "installed", package])
+ .output(),
+ "pacman" => Command::new("pacman").args(["-Q", package]).output(),
+ "brew" => Command::new("brew").args(["list", package]).output(),
+ "zypper" => Command::new("zypper").args(["se", "-i", package]).output(),
+ "apk" => Command::new("apk").args(["info", package]).output(),
+ _ => {
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ "Unsupported package manager",
+ ))
+ }
+ };
+
+ match output {
+ Ok(output) if output.status.success() => Ok(()),
+ _ => Err(io::Error::new(
+ io::ErrorKind::Other,
+ format!("Package '{}' is not installed", package),
+ )),
+ }
+}
diff --git a/src/spinner/frames.rs b/src/spinner/frames.rs
index a49fa26..bb4ee13 100644
--- a/src/spinner/frames.rs
+++ b/src/spinner/frames.rs
@@ -52,7 +52,8 @@ impl Default for Frames {
/// ## Example
/// ```
/// use zenity::spinner::{Frames, MultiSpinner};
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// let spinner = MultiSpinner::new();
+ /// spinner.add(Frames::default());
/// ```
fn default() -> Self {
Self::dots_simple_big3()
@@ -67,7 +68,9 @@ impl AsRef for Frames {
/// ```
/// use zenity::spinner::{Frames, MultiSpinner};
-/// let spinner = MultiSpinner::new(Frames::default());
+///
+/// let spinner = MultiSpinner::new();
+/// spinner.add(Frames::default());
/// ```
impl Frames {
/// generates frames for spinner animation based on the provided pattern, inversion flag, and speed
diff --git a/src/spinner/mod.rs b/src/spinner/mod.rs
index ac52319..b3cb596 100644
--- a/src/spinner/mod.rs
+++ b/src/spinner/mod.rs
@@ -42,7 +42,7 @@ pub mod frames;
/// use std::time::Duration;
/// use zenity::spinner::{Frames, MultiSpinner};
///
-/// let spinner = MultiSpinner::new(Frames::dot_spinner11());
+/// let spinner = MultiSpinner::default();
/// spinner.run_all();
///
/// sleep(Duration::from_secs(4));
@@ -69,7 +69,8 @@ impl Default for MultiSpinner {
/// let spinner = MultiSpinner::default();
/// ```
fn default() -> Self {
- let spinner = Self::new(Frames::default());
+ let spinner = Self::new();
+ spinner.add(Frames::default());
spinner.run_all();
spinner
@@ -80,8 +81,8 @@ impl Default for MultiSpinner {
/// use std::time::Duration;
/// use zenity::spinner::{Frames, MultiSpinner};
///
-/// let spinner = MultiSpinner::new(Frames::dot_spinner11());
-/// let spinner1 = spinner.get_last(); // get last created uid
+/// let spinner = MultiSpinner::default();
+/// let spinner1 = spinner.get_last();
/// let spinner2 = spinner.add(Frames::default()); // this already returns the uid
///
/// spinner.run_all();
@@ -100,19 +101,15 @@ impl MultiSpinner {
///
/// ## Example
/// ```
- /// use zenity::spinner::{MultiSpinner, Frames};
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// use zenity::spinner::MultiSpinner;
+ /// let spinner = MultiSpinner::new();
/// ```
- pub fn new(frames: Frames) -> Self {
- let spinner = MultiSpinner {
+ pub fn new() -> Self {
+ MultiSpinner {
spinner: Arc::new(Mutex::new(HashMap::new())),
stop: Arc::new(Mutex::new(false)),
show_line_number: Arc::new(Mutex::new(false)),
- };
-
- spinner.add(frames);
-
- spinner
+ }
}
/// create a new spinner
@@ -126,7 +123,7 @@ impl MultiSpinner {
/// use zenity::spinner::MultiSpinner;
/// use zenity::spinner::Frames;
///
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// let spinner = MultiSpinner::new();
///
/// spinner.add(Frames::aesthetic_load());
/// ```
@@ -150,7 +147,8 @@ impl MultiSpinner {
/// use zenity::spinner::MultiSpinner;
/// use zenity::spinner::Frames;
///
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// let spinner = MultiSpinner::new();
+ /// spinner.add(Frames::default());
///
/// // the return values is an id you will need to edit the spinner later on
/// let spinner1_uid = spinner.get_last();
@@ -158,7 +156,12 @@ impl MultiSpinner {
pub fn get_last(&self) -> usize {
let spinner_map = self.spinner.lock().unwrap();
- // get the maximum key value (uid) from the spinner map
+ // Check if the spinner is empty
+ if spinner_map.is_empty() {
+ return 0;
+ }
+
+ // Get the maximum key value (uid) from the spinner map
spinner_map.keys().copied().max().unwrap()
}
@@ -172,7 +175,7 @@ impl MultiSpinner {
/// use zenity::spinner::Frames;
/// use zenity::style::StyledString;
///
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// let spinner = MultiSpinner::default();
///
/// spinner.set_text(&spinner.get_last(),"example".to_string());
/// ```
@@ -193,7 +196,7 @@ impl MultiSpinner {
/// use zenity::spinner::Frames;
/// use zenity::style::StyledString;
///
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// let spinner = MultiSpinner::default();
///
/// spinner.set_styled_text(&spinner.get_last(),
/// StyledString::simple("test string", Some(Color::Red), Some(Color::Black), None));
@@ -212,7 +215,7 @@ impl MultiSpinner {
/// use zenity::spinner::MultiSpinner;
/// use zenity::spinner::Frames;
///
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// let spinner = MultiSpinner::default();
///
/// spinner.stop(&spinner.get_last());
/// ```
@@ -232,7 +235,7 @@ impl MultiSpinner {
/// use zenity::spinner::MultiSpinner;
/// use zenity::spinner::Frames;
///
- /// let spinner = MultiSpinner::new(Frames::default());
+ /// let spinner = MultiSpinner::default();
///
/// spinner.show_line_number();
/// ```
@@ -248,7 +251,7 @@ impl MultiSpinner {
/// use zenity::spinner::Frames;
///
/// // make spinner mutable
- /// let mut spinner = MultiSpinner::new(Frames::dots_simple_big1());
+ /// let mut spinner = MultiSpinner::default();
///
/// // queue spinners for execution
/// let spinner_num1 = spinner.get_last();