diff --git a/.github/workflows/release_examples.yml b/.github/workflows/release_examples.yml index 3aca3bf..c65751d 100644 --- a/.github/workflows/release_examples.yml +++ b/.github/workflows/release_examples.yml @@ -33,6 +33,7 @@ jobs: target/release/examples/basic.exe target/release/examples/all.exe target/release/examples/multi_spinner.exe + target/release/examples/progress.exe build_unix: @@ -62,6 +63,7 @@ jobs: target/release/examples/basic target/release/examples/all target/release/examples/multi_spinner + target/release/examples/progress release: needs: [build_windows, build_unix] diff --git a/.gitignore b/.gitignore index 198c4ce..d7c5da3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target .idea/ + +Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 95efa15..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,388 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "crossterm" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" -dependencies = [ - "bitflags 2.5.0", - "crossterm_winapi", - "libc", - "mio", - "parking_lot", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - -[[package]] -name = "getrandom" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "is_ci" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" - -[[package]] -name = "libc" -version = "0.2.153" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.9.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31e63ea85be51c423e52ba8f2e68a3efd53eed30203ee029dd09947333693e" -dependencies = [ - "rand_chacha", - "rand_core", - "zerocopy", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78674ef918c19451dbd250f8201f8619b494f64c9aa6f3adb28fd8a0f1f6da46" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc89dffba8377c5ec847d12bb41492bda235dba31a25e8b695cd0fe6589eb8c9" -dependencies = [ - "getrandom", - "zerocopy", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "supports-color" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9829b314621dfc575df4e409e79f9d6a66a3bd707ab73f23cb4aa3a854ac854f" -dependencies = [ - "is_ci", -] - -[[package]] -name = "syn" -version = "2.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-icons" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e7bbd9c649b66137fe3ef97c4c48b293575054bf36f5452057215bfce978e5a" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "zenity" -version = "1.3.2" -dependencies = [ - "crossterm", - "rand", - "supports-color", - "unicode-icons", -] - -[[package]] -name = "zerocopy" -version = "0.8.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db678a6ee512bd06adf35c35be471cae2f9c82a5aed2b5d15e03628c98bddd57" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201585ea96d37ee69f2ac769925ca57160cef31acb137c16f38b02b76f4c1e62" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml index 127b1dc..d952539 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ test = true crossterm = "0.27.0" rand = "0.9.0-alpha.1" supports-color = "3.0.0" +lazy_static = "1.4.0" [dev-dependencies] unicode-icons = { version = "2.1.2", default-features = false, features = ["symbols"] } diff --git a/README.md b/README.md index 2fd3dae..fad907b 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,27 @@ -# zenity (Yet Another Spinner Lib) +
+ Zenity svg logo +

Yet Another Spinner Lib

+

Elevate your Rust command-line interfaces with 100+ spinner animations and Progress Bars + multiline support

+ + Publish to Crates + + + Compile Rust + + Crates.io Version + docs.rs +
+ + CodeFactor + +
-Elevate your Rust command-line interfaces with 100+ spinner animations and Progress Bars + multiline support - -[![Publish to Crates](https://github.com/Arteiii/zenity/actions/workflows/publish_crate.yml/badge.svg)](https://github.com/Arteiii/zenity/actions/workflows/publish_crate.yml) -[![Compile Rust](https://github.com/Arteiii/zenity/actions/workflows/release_examples.yml/badge.svg)](https://github.com/Arteiii/zenity/actions/workflows/release_examples.yml) -![Crates.io Version](https://img.shields.io/crates/v/zenity) -![docs.rs](https://img.shields.io/docsrs/zenity) - -[![CodeFactor](https://www.codefactor.io/repository/github/arteiii/zenity/badge)](https://www.codefactor.io/repository/github/arteiii/zenity) +![progress bar](./images/rustrover64_WupAJU44Lu.gif) ![multiline preview](./images/rustrover64_4bzlv2mWxK.gif) -![](./images/rustrover64_tlGiHM9JP0.gif) - -![progress bar](./images/rustrover64_WupAJU44Lu.gif) - -checkout the examples for this^^ +[**CHANGELOG**](CHANGELOG.md) Do you often find yourself gazing into the void of your terminal, wondering if your computer has decided to take a coffee break without notifying you? @@ -98,6 +103,23 @@ These projects not only provided delightful animations but also spared me from t - [supports_color](https://docs.rs/supports-color/latest/supports_color/) +## Contribution + +Contributions are welcome! + +### How to Contribute + +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/YourFeature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin feature/YourFeature`) +5. Create a new Pull Request + +## Feature Requests and Bug Reports + +If you have any ideas for new features or encounter any bugs while using Zenity, please don't hesitate to open an issue on [GitHub](https://github.com/Arteiii/zenity/issues). Your feedback is valuable and will help improve the library for everyone. + + ## License This project is licensed under the **DWFYW** License. diff --git a/examples/all.rs b/examples/all.rs index bd59160..54f447d 100644 --- a/examples/all.rs +++ b/examples/all.rs @@ -2,16 +2,17 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread::sleep; use std::time::Duration; -use zenity::{spinner::PreDefined, LoadingAnimation}; +use zenity::spinner::{MultiSpinner, Frames}; static TOTAL_ANIMATIONS: AtomicUsize = AtomicUsize::new(0); macro_rules! test_predefined_animation { ($animation:expr, $text:expr) => {{ - let mut custom_loading_animation = LoadingAnimation::new($animation); - custom_loading_animation.set_text($text); + let custom = MultiSpinner::new($animation); + custom.run_all(); + custom.set_text(&custom.get_last(), $text.to_string()); sleep(Duration::from_secs(5)); - custom_loading_animation.stop_and_persist(None, None, None); + custom.stop(&custom.get_last()); TOTAL_ANIMATIONS.fetch_add(1, Ordering::Relaxed); }}; @@ -19,123 +20,123 @@ macro_rules! test_predefined_animation { fn main() { // new: - test_predefined_animation!(PreDefined::dwarf_fortress(false), "dwarf_fortress"); + test_predefined_animation!(Frames::dwarf_fortress(false), "dwarf_fortress"); - test_predefined_animation!(PreDefined::matrix_glitch(false), "matrix_glitch"); - test_predefined_animation!(PreDefined::matrix_glitch2(false), "matrix_glitch2"); + test_predefined_animation!(Frames::matrix_glitch(false), "matrix_glitch"); + test_predefined_animation!(Frames::matrix_glitch2(false), "matrix_glitch2"); test_predefined_animation!( - PreDefined::matrix_glitch2_small(false), + Frames::matrix_glitch2_small(false), "matrix_glitch2_small" ); - test_predefined_animation!(PreDefined::layer(false), "layer"); - test_predefined_animation!(PreDefined::soccer(false), "soccer"); - test_predefined_animation!(PreDefined::wavy(false), "wavy"); - test_predefined_animation!(PreDefined::wavy2(false), "wavy2"); - test_predefined_animation!(PreDefined::wavy3(false), "wavy3"); - test_predefined_animation!(PreDefined::wavy4(false), "wavy4"); - test_predefined_animation!(PreDefined::pray(false), "pray"); + test_predefined_animation!(Frames::layer(false), "layer"); + test_predefined_animation!(Frames::soccer(false), "soccer"); + test_predefined_animation!(Frames::wavy(false), "wavy"); + test_predefined_animation!(Frames::wavy2(false), "wavy2"); + test_predefined_animation!(Frames::wavy3(false), "wavy3"); + test_predefined_animation!(Frames::wavy4(false), "wavy4"); + test_predefined_animation!(Frames::pray(false), "pray"); - test_predefined_animation!(PreDefined::red_pulse(false), "red_pulse"); - test_predefined_animation!(PreDefined::dot_bounce2(false), "dot_bounce2"); - test_predefined_animation!(PreDefined::dot_box(false), "dot_box"); - test_predefined_animation!(PreDefined::arrows(false), "arrows"); - test_predefined_animation!(PreDefined::bomb(false), "bomb"); - test_predefined_animation!(PreDefined::simple_line_spin(false), "simple_line_spin"); - test_predefined_animation!(PreDefined::orange_pulse(false), "orange_pulse"); - test_predefined_animation!(PreDefined::blue_pulse(false), "blue_pulse"); - test_predefined_animation!(PreDefined::green_pulse(false), "green_pulse"); - test_predefined_animation!(PreDefined::other(false), "other"); + test_predefined_animation!(Frames::red_pulse(false), "red_pulse"); + test_predefined_animation!(Frames::dot_bounce2(false), "dot_bounce2"); + test_predefined_animation!(Frames::dot_box(false), "dot_box"); + test_predefined_animation!(Frames::arrows(false), "arrows"); + test_predefined_animation!(Frames::bomb(false), "bomb"); + test_predefined_animation!(Frames::simple_line_spin(false), "simple_line_spin"); + test_predefined_animation!(Frames::orange_pulse(false), "orange_pulse"); + test_predefined_animation!(Frames::blue_pulse(false), "blue_pulse"); + test_predefined_animation!(Frames::green_pulse(false), "green_pulse"); + test_predefined_animation!(Frames::other(false), "other"); test_predefined_animation!( - PreDefined::short_loading_bar_with_arrow(false), + Frames::short_loading_bar_with_arrow(false), "short_loading_bar_with_arrow" ); test_predefined_animation!( - PreDefined::loading_bar_with_arrow(false), + Frames::loading_bar_with_arrow(false), "loading_bar_with_arrow" ); - test_predefined_animation!(PreDefined::speaker(false), "speaker"); - test_predefined_animation!(PreDefined::finger_dance(false), "finger_dance"); - test_predefined_animation!(PreDefined::fist_bump(false), "fist_bump"); - test_predefined_animation!(PreDefined::mind_blown(false), "mind_blown"); - test_predefined_animation!(PreDefined::dots_simple_big1(false), "dots_simple_big1"); - test_predefined_animation!(PreDefined::dots_simple_big2(false), "dots_simple_big2"); - test_predefined_animation!(PreDefined::dots_simple_big3(false), "dots_simple_big3"); - test_predefined_animation!(PreDefined::dots_simple_big4(false), "dots_simple_big4"); - test_predefined_animation!(PreDefined::nade(false), "nade"); - test_predefined_animation!(PreDefined::christmas_tree(false), "christmas_tree"); - test_predefined_animation!(PreDefined::weather(false), "weather"); - test_predefined_animation!(PreDefined::raining(false), "raining"); - test_predefined_animation!(PreDefined::runner(false), "runner"); - test_predefined_animation!(PreDefined::hearts(false), "hearts"); - test_predefined_animation!(PreDefined::smiley(false), "smiley"); - test_predefined_animation!(PreDefined::monkey(false), "monkey"); - test_predefined_animation!(PreDefined::bouncing_ball(false), "bouncing_ball"); - test_predefined_animation!(PreDefined::square_corners(false), "square_corners"); - test_predefined_animation!(PreDefined::circle_corners(false), "circle_corners"); - test_predefined_animation!(PreDefined::circle_halves(false), "circle_halves"); - test_predefined_animation!(PreDefined::circle(false), "circle"); - test_predefined_animation!(PreDefined::arc(false), "arc"); - test_predefined_animation!(PreDefined::binary(false), "binary"); - test_predefined_animation!(PreDefined::flip(false), "flip"); - test_predefined_animation!(PreDefined::star1(false), "star1"); - test_predefined_animation!(PreDefined::star2(false), "star2"); - test_predefined_animation!(PreDefined::dots_simple1(false), "dots_simple1"); - test_predefined_animation!(PreDefined::dots_simple2(false), "dots_simple2"); - test_predefined_animation!(PreDefined::dot_spinner1(false), "dot_spinner1"); - test_predefined_animation!(PreDefined::dot_spinner2(false), "dot_spinner2"); - test_predefined_animation!(PreDefined::dot_spinner3(false), "dot_spinner3"); - test_predefined_animation!(PreDefined::dot_spinner4(false), "dot_spinner4"); - test_predefined_animation!(PreDefined::dot_spinner5(false), "dot_spinner5"); - test_predefined_animation!(PreDefined::dot_spinner6(false), "dot_spinner6"); - test_predefined_animation!(PreDefined::dot_spinner7(false), "dot_spinner7"); - test_predefined_animation!(PreDefined::dot_spinner8(false), "dot_spinner8"); - test_predefined_animation!(PreDefined::dot_spinner9(false), "dot_spinner9"); - test_predefined_animation!(PreDefined::dot_spinner10(false), "dot_spinner10"); - test_predefined_animation!(PreDefined::dot_spinner11(false), "dot_spinner11"); - test_predefined_animation!(PreDefined::toggle(false), "toggle"); - test_predefined_animation!(PreDefined::toggle2(false), "toggle2"); - test_predefined_animation!(PreDefined::toggle3(false), "toggle3"); - test_predefined_animation!(PreDefined::toggle4(false), "toggle4"); - test_predefined_animation!(PreDefined::toggle5(false), "toggle5"); - test_predefined_animation!(PreDefined::toggle6(false), "toggle6"); - test_predefined_animation!(PreDefined::toggle7(false), "toggle7"); - test_predefined_animation!(PreDefined::toggle8(false), "toggle8"); - test_predefined_animation!(PreDefined::toggle9(false), "toggle9"); - test_predefined_animation!(PreDefined::toggle10(false), "toggle10"); - test_predefined_animation!(PreDefined::toggle11(false), "toggle11"); - test_predefined_animation!(PreDefined::toggle12(false), "toggle12"); - test_predefined_animation!(PreDefined::toggle13(false), "toggle13"); - test_predefined_animation!(PreDefined::stack(false), "stack"); - test_predefined_animation!(PreDefined::big_loading_bar(false), "big_loading_bar"); - test_predefined_animation!(PreDefined::dot_bounce(false), "dot_bounce"); - test_predefined_animation!(PreDefined::fractions(false), "fractions"); - test_predefined_animation!(PreDefined::wall_bounce_line(false), "wall_bounce_line"); - test_predefined_animation!(PreDefined::wall_bounce(false), "wall_bounce"); - test_predefined_animation!(PreDefined::earth(false), "earth"); - test_predefined_animation!(PreDefined::arrow_row(false), "arrow_row"); - test_predefined_animation!(PreDefined::block(false), "block"); - test_predefined_animation!(PreDefined::block_spinn(false), "block_spinn"); - test_predefined_animation!(PreDefined::line(false), "line"); - test_predefined_animation!(PreDefined::line2(false), "line2"); - test_predefined_animation!(PreDefined::moon(false), "moon"); - test_predefined_animation!(PreDefined::kaomoji(false), "kaomoji"); - test_predefined_animation!(PreDefined::aesthetic_spin(false), "aesthetic_spin"); - test_predefined_animation!(PreDefined::aesthetic_load(false), "aesthetic_load"); - test_predefined_animation!(PreDefined::clock(false), "clock"); - test_predefined_animation!(PreDefined::small_bouncing_bar(false), "small_bouncing_bar"); - test_predefined_animation!(PreDefined::small_loading_bar(false), "small_loading_bar"); - test_predefined_animation!(PreDefined::material(false), "material"); - test_predefined_animation!(PreDefined::arrow_spinn(false), "arrow_spinn"); - test_predefined_animation!(PreDefined::line_spinner(false), "line_spinner"); - test_predefined_animation!(PreDefined::corner(false), "corner"); + test_predefined_animation!(Frames::speaker(false), "speaker"); + test_predefined_animation!(Frames::finger_dance(false), "finger_dance"); + test_predefined_animation!(Frames::fist_bump(false), "fist_bump"); + test_predefined_animation!(Frames::mind_blown(false), "mind_blown"); + test_predefined_animation!(Frames::dots_simple_big1(false), "dots_simple_big1"); + test_predefined_animation!(Frames::dots_simple_big2(false), "dots_simple_big2"); + test_predefined_animation!(Frames::dots_simple_big3(false), "dots_simple_big3"); + test_predefined_animation!(Frames::dots_simple_big4(false), "dots_simple_big4"); + test_predefined_animation!(Frames::nade(false), "nade"); + test_predefined_animation!(Frames::christmas_tree(false), "christmas_tree"); + test_predefined_animation!(Frames::weather(false), "weather"); + test_predefined_animation!(Frames::raining(false), "raining"); + test_predefined_animation!(Frames::runner(false), "runner"); + test_predefined_animation!(Frames::hearts(false), "hearts"); + test_predefined_animation!(Frames::smiley(false), "smiley"); + test_predefined_animation!(Frames::monkey(false), "monkey"); + test_predefined_animation!(Frames::bouncing_ball(false), "bouncing_ball"); + test_predefined_animation!(Frames::square_corners(false), "square_corners"); + test_predefined_animation!(Frames::circle_corners(false), "circle_corners"); + test_predefined_animation!(Frames::circle_halves(false), "circle_halves"); + test_predefined_animation!(Frames::circle(false), "circle"); + test_predefined_animation!(Frames::arc(false), "arc"); + test_predefined_animation!(Frames::binary(false), "binary"); + test_predefined_animation!(Frames::flip(false), "flip"); + test_predefined_animation!(Frames::star1(false), "star1"); + test_predefined_animation!(Frames::star2(false), "star2"); + test_predefined_animation!(Frames::dots_simple1(false), "dots_simple1"); + test_predefined_animation!(Frames::dots_simple2(false), "dots_simple2"); + test_predefined_animation!(Frames::dot_spinner1(false), "dot_spinner1"); + test_predefined_animation!(Frames::dot_spinner2(false), "dot_spinner2"); + test_predefined_animation!(Frames::dot_spinner3(false), "dot_spinner3"); + test_predefined_animation!(Frames::dot_spinner4(false), "dot_spinner4"); + test_predefined_animation!(Frames::dot_spinner5(false), "dot_spinner5"); + test_predefined_animation!(Frames::dot_spinner6(false), "dot_spinner6"); + test_predefined_animation!(Frames::dot_spinner7(false), "dot_spinner7"); + test_predefined_animation!(Frames::dot_spinner8(false), "dot_spinner8"); + test_predefined_animation!(Frames::dot_spinner9(false), "dot_spinner9"); + test_predefined_animation!(Frames::dot_spinner10(false), "dot_spinner10"); + test_predefined_animation!(Frames::dot_spinner11(false), "dot_spinner11"); + test_predefined_animation!(Frames::toggle(false), "toggle"); + test_predefined_animation!(Frames::toggle2(false), "toggle2"); + test_predefined_animation!(Frames::toggle3(false), "toggle3"); + test_predefined_animation!(Frames::toggle4(false), "toggle4"); + test_predefined_animation!(Frames::toggle5(false), "toggle5"); + test_predefined_animation!(Frames::toggle6(false), "toggle6"); + test_predefined_animation!(Frames::toggle7(false), "toggle7"); + test_predefined_animation!(Frames::toggle8(false), "toggle8"); + test_predefined_animation!(Frames::toggle9(false), "toggle9"); + test_predefined_animation!(Frames::toggle10(false), "toggle10"); + test_predefined_animation!(Frames::toggle11(false), "toggle11"); + test_predefined_animation!(Frames::toggle12(false), "toggle12"); + test_predefined_animation!(Frames::toggle13(false), "toggle13"); + test_predefined_animation!(Frames::stack(false), "stack"); + test_predefined_animation!(Frames::big_loading_bar(false), "big_loading_bar"); + test_predefined_animation!(Frames::dot_bounce(false), "dot_bounce"); + test_predefined_animation!(Frames::fractions(false), "fractions"); + test_predefined_animation!(Frames::wall_bounce_line(false), "wall_bounce_line"); + test_predefined_animation!(Frames::wall_bounce(false), "wall_bounce"); + test_predefined_animation!(Frames::earth(false), "earth"); + test_predefined_animation!(Frames::arrow_row(false), "arrow_row"); + test_predefined_animation!(Frames::block(false), "block"); + test_predefined_animation!(Frames::block_spinn(false), "block_spinn"); + test_predefined_animation!(Frames::line(false), "line"); + test_predefined_animation!(Frames::line2(false), "line2"); + test_predefined_animation!(Frames::moon(false), "moon"); + test_predefined_animation!(Frames::kaomoji(false), "kaomoji"); + test_predefined_animation!(Frames::aesthetic_spin(false), "aesthetic_spin"); + test_predefined_animation!(Frames::aesthetic_load(false), "aesthetic_load"); + test_predefined_animation!(Frames::clock(false), "clock"); + test_predefined_animation!(Frames::small_bouncing_bar(false), "small_bouncing_bar"); + test_predefined_animation!(Frames::small_loading_bar(false), "small_loading_bar"); + test_predefined_animation!(Frames::material(false), "material"); + test_predefined_animation!(Frames::arrow_spinn(false), "arrow_spinn"); + test_predefined_animation!(Frames::line_spinner(false), "line_spinner"); + test_predefined_animation!(Frames::corner(false), "corner"); test_predefined_animation!( - PreDefined::line_spinner_simple(false), + Frames::line_spinner_simple(false), "line_spinner_simple" ); - test_predefined_animation!(PreDefined::abc(false), "abc"); - test_predefined_animation!(PreDefined::big_arrow_spinn(false), "big_arrow_spinn"); - test_predefined_animation!(PreDefined::japanese(false), "japanese"); + test_predefined_animation!(Frames::abc(false), "abc"); + test_predefined_animation!(Frames::big_arrow_spinn(false), "big_arrow_spinn"); + test_predefined_animation!(Frames::japanese(false), "japanese"); println!( "Total Animations: {}", diff --git a/examples/basic.rs b/examples/basic.rs index 6408a9a..036d7b9 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -2,7 +2,7 @@ use std::thread::sleep; use std::time::Duration; -use zenity::{style::Color, LoadingAnimation}; +use zenity::spinner::MultiSpinner; fn main() { println!("println test"); @@ -11,11 +11,10 @@ fn main() { fn scope_example() { // create a LoadingAnimation instance using one of the predefined animations - let spinner = LoadingAnimation::default(); + let spinner = MultiSpinner::default(); // optional: - spinner.set_text("Loading..."); // sets the text to "Loading..." - spinner.set_text_color(Color::DarkBlue); // set the color + spinner.set_text(&spinner.get_last(), "Loading...".to_string()); // sets the text to "Loading..." sleep(Duration::from_secs(5)); // `loading_animation` will run out of scope now and get dropped, diff --git a/examples/custom_frames.rs b/examples/custom_frames.rs new file mode 100644 index 0000000..1bfa74f --- /dev/null +++ b/examples/custom_frames.rs @@ -0,0 +1,20 @@ +use std::thread::sleep; +use std::time::Duration; + +use zenity::spinner::{Frames, MultiSpinner}; + +fn main() { + // custom animations + let custom_frames: Frames = Frames { + frames: vec!["⚫", "⚪", "⚫", "⚪"], // custom frames for animation + speed_ms: 150, // custom speed for animation in milliseconds + }; + + // create a MultiSpinner instance using the new custom animation + let spinner = MultiSpinner::new(custom_frames); + spinner.run_all(); + + // wait for 5 seconds to showcase the loading animation with the custom animation + sleep(Duration::from_secs(5)); + // end! +} diff --git a/examples/main.rs b/examples/main.rs deleted file mode 100644 index 4c779d0..0000000 --- a/examples/main.rs +++ /dev/null @@ -1,77 +0,0 @@ -use std::thread::sleep; -use std::time::Duration; -use unicode_icons::icons::symbols; -use zenity::{ - combine_attributes, - spinner::{Frames, PreDefined}, - style::{Attribute, Color, ContentStyle}, - LoadingAnimation, -}; - -fn main() { - { - // custom animations - let custom_frames: Frames = Frames { - frames: vec!["⚫", "⚪", "⚫", "⚪"], // custom frames for animation - speed_ms: 150, // custom speed for animation in milliseconds - }; - - // create a LoadingAnimation instance using the new custom animation - let _custom_loading_animation = LoadingAnimation::new(custom_frames); - - // wait for 5 seconds to showcase the loading animation with the custom animation - sleep(Duration::from_secs(5)); - // end! - } - - let mut spinner = LoadingAnimation::new(PreDefined::dot_spinner3(false)); - - spinner.set_text("Loading..."); // sets the text to "Loading..." - - sleep(Duration::from_secs(5)); - - // change colors during the animation - change_colors_during_animation(&mut spinner, Duration::from_secs(2)); - - let content_style = ContentStyle { - foreground_color: Some(Color::Green), - background_color: None, - underline_color: Some(Color::Green), - attributes: Attribute::Bold.into(), - }; - - spinner.stop_and_persist( - Some(&symbols::check_mark_button().to_string()), - Some("Successfully"), - Some(content_style), - ); - - sleep(Duration::from_secs(5)); -} - -fn change_colors_during_animation(spinner: &mut LoadingAnimation, text_color_duration: Duration) { - spinner.set_text("MOREEEEEEE Loading... (but with color)"); // overwrite current text - - // custom rgb color (50, 60, 70) - spinner.set_text_color(Color::Rgb { r: 255, g: 0, b: 0 }); - sleep(text_color_duration); - - spinner.set_text("Styled Text and loading"); - - // custom style - let content_style = ContentStyle { - foreground_color: Some(Color::Yellow), - background_color: Some(Color::Blue), - underline_color: Some(Color::Green), - attributes: combine_attributes(&[ - &Attribute::Bold, - &Attribute::Underlined, - &Attribute::Italic, // add another attribute here - ]), - }; - - spinner.set_animation_style(content_style); - sleep(text_color_duration); - - // for more information, refer to the cross-term documentation (https://docs.rs/crossterm/latest/crossterm/style) -} diff --git a/examples/multi_spinner.rs b/examples/multi_spinner.rs index e04a1bf..cc3f21d 100644 --- a/examples/multi_spinner.rs +++ b/examples/multi_spinner.rs @@ -3,30 +3,25 @@ use std::time::Duration; use unicode_icons::icons::symbols::{check_mark_button, cross_mark}; -use zenity::multi_spinner::MultiSpinner; -use zenity::spinner::PreDefined; +use zenity::spinner::MultiSpinner; +use zenity::spinner::Frames; fn main() { { let check_mark_text = check_mark_button(); let cross_mark_text = cross_mark(); - let mut spinner = MultiSpinner::default(); + let spinner = MultiSpinner::new(Frames::dot_spinner11(false)); + let spinner1 = spinner.get_last(); // main thread operations - let spinner1 = spinner.add(PreDefined::dot_spinner11(false)); - let spinner2 = spinner.add(PreDefined::binary(false)); - let spinner3 = spinner.add(PreDefined::dot_spinner9(false)); - let spinner4 = spinner.add(PreDefined::dot_spinner8(false)); + let spinner2 = spinner.add(Frames::binary(false)); + let spinner3 = spinner.add(Frames::dot_spinner9(false)); + let spinner4 = spinner.add(Frames::dot_spinner8(false)); - sleep(Duration::from_secs(2)); - - // access the spinner through the Arc> reference spinner.run_all(); - sleep(Duration::from_secs(2)); - - sleep(Duration::from_secs(8)); + sleep(Duration::from_secs(4)); spinner.set_text(&spinner2, "spinner2".to_string()); // stop spinner1 spinner.set_text(&spinner1, "spinner1".to_string()); diff --git a/examples/progress.rs b/examples/progress.rs index 8affb75..4f4d3a2 100644 --- a/examples/progress.rs +++ b/examples/progress.rs @@ -1,39 +1,42 @@ -use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use rand::Rng; -use zenity::animations::{ - frames::progress::ProgressBarFrames, - progress::{Bar, Progress}, -}; +use zenity::progress::{ProgressBar, Frames}; fn main() { - // I know that this is not the best solution I will rework it asap - // contributions welcome + { + let progress = ProgressBar::default(); - println!("test Header line"); - thread::sleep(Duration::from_secs(8)); + let loading = 1_usize; - let mut progress = Progress::default(); + for loading in loading..=100 { + thread::sleep(Duration::from_millis(rand::thread_rng().gen_range(1..=70))); + progress.set(&progress.get_last(), &loading); + } + } + + multiple(); + println!("test line ending") +} - let progress1 = progress.add(Bar::default()); +fn multiple() { + println!("multiple progressbar"); - // TODO: create wrapper for this - let progress2 = progress.add(Bar { - frames: Arc::new(Mutex::new(ProgressBarFrames::rect())), - size: Arc::new(Mutex::new(70_usize)), - current: Arc::new(Mutex::new(0_usize)), - goal: Arc::new(Mutex::new(253_usize)), - }); + let progress = ProgressBar::new(Frames::rect().set_goal(253)); + let progress1 = progress.get_last(); - let progress3 = progress.add(Bar { - frames: Arc::new(Mutex::new(ProgressBarFrames::hash())), - size: Arc::new(Mutex::new(7_usize)), - current: Arc::new(Mutex::new(0_usize)), - goal: Arc::new(Mutex::new(253_usize)), - }); + let progress2 = progress.add( + Frames::equal() + .set_goal(253) + .set_size(7), + ); + let progress3 = progress.add( + Frames::hash() + .set_goal(253) + .set_size(60), + ); progress.run_all(); @@ -44,9 +47,6 @@ fn main() { progress.set(&progress2, &loading); progress.set(&progress3, &loading); - let sleep_time = rand::thread_rng().gen_range(1..=70); - thread::sleep(Duration::from_millis(sleep_time)); + thread::sleep(Duration::from_millis(rand::thread_rng().gen_range(1..=70))); } - - thread::sleep(Duration::from_millis(1000)); } diff --git a/images/ZENITY.svg b/images/ZENITY.svg new file mode 100644 index 0000000..0dcab80 --- /dev/null +++ b/images/ZENITY.svg @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/images/rustrover64_tlGiHM9JP0.gif b/images/rustrover64_tlGiHM9JP0.gif deleted file mode 100644 index e3ed016..0000000 Binary files a/images/rustrover64_tlGiHM9JP0.gif and /dev/null differ diff --git a/src/animations/animation.rs b/src/animations/animation.rs deleted file mode 100644 index c5a8287..0000000 --- a/src/animations/animation.rs +++ /dev/null @@ -1,155 +0,0 @@ -//! Single Animation priv mod - -use std::io::stdout; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; - -use crossterm::style::{ContentStyle, Print, ResetColor, SetStyle}; -use crossterm::{cursor, execute, terminal}; - -use super::frames::spinner::Frames; - -/// spinner struct encapsulating the spinner animation -pub struct Spinner { - frames: Arc>, - should_stop: Arc>, - text: Arc>>, - animation_style: Arc>, - text_style: Arc>, - end_sequence: Arc>>, - cleanup_on_exit: Arc>, -} - -impl Spinner { - /// creates a new instance of Spinner - pub fn new( - frames: Arc>, - should_stop: Arc>, - text: Arc>>, - animation_style: Arc>, - text_style: Arc>, - end_sequence: Arc>>, - cleanup_on_exit: Arc>, - ) -> Self { - Spinner { - frames, - should_stop, - text, - animation_style, - text_style, - end_sequence, - cleanup_on_exit, - } - } - - /// runs the spinner animation - pub fn run(&self) { - let mut frame_index = 0; - let longest_frame_len = self - .frames - .lock() - .unwrap() - .frames - .iter() - .map(|frame| frame.len()) - .max() - .unwrap_or(0); - - execute!( - stdout(), - terminal::Clear(terminal::ClearType::CurrentLine), - cursor::MoveToColumn(0), - cursor::Hide, // hide cursor - ) - .unwrap(); - - while !*self.should_stop.lock().unwrap() { - self.display_frame(&mut frame_index); - thread::sleep(Duration::from_millis(self.frames.lock().unwrap().speed_ms)); - } - - self.display_end_sequence(); - self.cleanup(longest_frame_len); - - execute!( - stdout(), - cursor::Show, // show cursor - ) - .unwrap(); - } - - /// displays a frame of the spinner animation - fn display_frame(&self, frame_index: &mut usize) { - let frame = { - let frames = self.frames.lock().unwrap(); - let frame = &frames.frames[*frame_index]; - frame.to_owned() - }; - - execute!( - stdout(), - terminal::Clear(terminal::ClearType::CurrentLine), - cursor::MoveToColumn(0), - cursor::Hide, - SetStyle(*self.animation_style.lock().unwrap()), // set animation color - Print(frame), - Print(" "), - SetStyle(*self.text_style.lock().unwrap()), // set text color - Print( - self.text - .lock() - .unwrap() - .as_ref() - .unwrap_or(&"".to_string()) - ), - ResetColor, // reset colors - ) - .unwrap(); - - *frame_index = (*frame_index + 1) % self.frames.lock().unwrap().frames.len(); - } - - /// displays the end sequence of the spinner animation - fn display_end_sequence(&self) { - if let Some(end_seq) = &*self.end_sequence.lock().unwrap() { - execute!( - stdout(), - terminal::Clear(terminal::ClearType::CurrentLine), - cursor::MoveToColumn(0), - cursor::Hide, - ResetColor, - Print(end_seq), - Print(" "), - SetStyle(*self.text_style.lock().unwrap()), - Print( - self.text - .lock() - .unwrap() - .as_ref() - .unwrap_or(&"".to_string()) - ), - ResetColor, - Print("\n"), - ) - .unwrap(); - } - } - - /// cleans up after the spinner animation - fn cleanup(&self, longest_frame_len: usize) { - if *self.cleanup_on_exit.lock().unwrap() { - let clear_length = " ".repeat(longest_frame_len); - execute!( - stdout(), - terminal::Clear(terminal::ClearType::CurrentLine), - cursor::MoveToColumn(0), - Print(&clear_length), - Print("\r"), - ) - .unwrap(); - } else { - execute!(stdout(), Print("\n"),).unwrap(); - } - } -} diff --git a/src/animations/frames/mod.rs b/src/animations/frames/mod.rs deleted file mode 100644 index 5bc3b5b..0000000 --- a/src/animations/frames/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! stores predefined animations and the `Frames` struct - -/// -pub mod progress; -pub mod spinner; diff --git a/src/animations/frames/progress.rs b/src/animations/frames/progress.rs deleted file mode 100644 index e192875..0000000 --- a/src/animations/frames/progress.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! progressbar frames - -/// struct storing the data needed to render a ProgressBar -pub struct ProgressBarFrames { - /// begin string - pub begin: Vec<&'static str>, - - /// string to place on complete places - pub bar_complete_char: Vec<&'static str>, - - /// string to place on incomplete places - pub bar_incomplete_char: Vec<&'static str>, - - /// ending string - pub end: Vec<&'static str>, -} - -// TODO: add animations by adding +1 for each bar so you can have a wave animation and others - -impl ProgressBarFrames { - /// '=' as the complete char and '-' as the incomplete char - pub fn equal() -> Self { - Self { - begin: vec!["["], - bar_complete_char: vec!["="], - bar_incomplete_char: vec!["-"], - end: vec!["]"], - } - } - - /// '#' as the complete char and '.' as the incomplete char - pub fn hash() -> Self { - Self { - begin: vec!["["], - bar_complete_char: vec!["#"], - bar_incomplete_char: vec!["."], - end: vec!["]"], - } - } - /// '#' as the complete char and '.' as the incomplete char - pub fn rect() -> Self { - Self { - begin: vec![" "], - bar_complete_char: vec!["\u{25A0}"], - bar_incomplete_char: vec![" "], - end: vec![" "], - } - } - - // TODO: add more -} diff --git a/src/animations/mod.rs b/src/animations/mod.rs deleted file mode 100644 index bd6b29d..0000000 --- a/src/animations/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Animations Mod - -pub(crate) mod animation; -pub mod frames; - -pub mod progress; -pub mod spinner; diff --git a/src/helper/colors.rs b/src/color.rs similarity index 51% rename from src/helper/colors.rs rename to src/color.rs index 0abe04c..b941a1a 100644 --- a/src/helper/colors.rs +++ b/src/color.rs @@ -1,41 +1,24 @@ -//! Collection of helper functions and classes related to colors - -use crossterm::style; - -/// combines multiple attributes into a single `style::Attributes` instance -/// -/// this function takes a slice of attribute references and combines them into a single -/// `style::Attributes` instance using bitwise OR (`|`) operation -/// -/// # Arguments -/// -/// * `attr_list` - a slice containing references to the attributes to be combined -/// -/// # Returns -/// -/// A `style::Attributes` instance representing the combined attributes -/// -/// # Example -/// -/// ``` -/// use zenity::{style::Attribute, combine_attributes}; -/// -/// let attributes = combine_attributes(&[ -/// &Attribute::Bold, -/// &Attribute::Underlined, -/// &Attribute::Italic, -/// ]); -/// ``` -pub fn combine_attributes(attr_list: &[&style::Attribute]) -> style::Attributes { - attr_list - .iter() - .fold(style::Attributes::default(), |acc, &attr| { - acc | style::Attributes::from(*attr) - }) +//! Mod for color related methods + +use lazy_static::lazy_static; + + +lazy_static! { + /// supported color pallet (which colors are supported if ENABLE_COLOR) + pub static ref COLOR_PALETTE: ColorPalette = { + CliColorConfig::get_supported_color_palette() + }; + + /// lazy static ENABLE color bool true if color should be enabled false otherwise + pub static ref ENABLE_COLOR: bool = { + let conf = CliColorConfig::default(); + conf.should_enable_color() + }; } /// represents different color palettes supported by terminals -#[derive(PartialEq)] +#[allow(dead_code)] +#[derive(PartialEq, Debug)] pub enum ColorPalette { /// color support not available (pipe or otherwise disabled) None, @@ -52,34 +35,6 @@ pub enum ColorPalette { Truecolor, } -/// Represents a color palette used in the CLI app -pub struct AppColorPalette { - /// the color palette enum representing the colors - color_palette: ColorPalette, -} - -impl AppColorPalette { - /// creates a new `AppColorPalette` instance with the specified color palette - pub fn new(color_palette: ColorPalette) -> Self { - Self { color_palette } - } - - pub fn get_color_palette(&self) -> &ColorPalette { - &self.color_palette - } - - // TODO: implement - // /// modify a given color to align with the supported colors in the palette - // /// - // /// returns a modified version of the color that matches the closest supported color, or `None` if no suitable match is found - // pub fn modify_color(&self, color: &str) -> Option {} - - // TODO: implement - // fn convert_to_16(&self, ) { - // - // } -} - /// represents different options for controlling color output in the cli /// /// - Always: always enable color output @@ -87,8 +42,9 @@ impl AppColorPalette { /// - Never: never enable color output /// /// [Read More](https://rust-cli-recommendations.sunshowers.io/colors.html#general-recommendations) +#[allow(dead_code)] #[derive(Debug, PartialEq)] -pub enum ColorOption { +enum ColorOption { /// always enable color output Always, @@ -99,32 +55,19 @@ pub enum ColorOption { Never, } -impl ColorOption { - /// parses a string representation into a `ColorOption` enum variant - /// - /// the function takes a string slice as input and attempts to match it to one of the - /// predefined variants of the `ColorOption` enum - /// Case insensitivity and whitespace trimming are applied to improve robustness - pub fn from_string(s: &str) -> Option { - match s.trim().to_lowercase().as_str() { - "always" => Some(Self::Always), - "auto" => Some(Self::Auto), - "never" => Some(Self::Never), - _ => None, - } - } -} /// configuration struct for managing cli color settings -pub struct CliColorConfig { +#[allow(dead_code)] +struct CliColorConfig { /// the chosen color option for cli output #[allow(dead_code)] color_option: ColorOption, /// the color palette supported by the terminal - color_palette: AppColorPalette, + color_palette: ColorPalette, } +#[allow(dead_code)] impl Default for CliColorConfig { /// creates a new `CliColorConfig` instance with default settings /// @@ -139,11 +82,11 @@ impl Default for CliColorConfig { Self { color_option, - color_palette: AppColorPalette::new(color_palette), + color_palette, } } } - +#[allow(dead_code)] impl CliColorConfig { /// creates a new `CliColorConfig` instance with custom settings /// @@ -151,7 +94,7 @@ impl CliColorConfig { /// /// * `color_option` - the chosen color option for CLI output /// * `color_palette` - the color palette supported by the terminal - pub fn new(color_option: ColorOption, color_palette: AppColorPalette) -> Self { + fn new(color_option: ColorOption, color_palette: ColorPalette) -> Self { Self { color_option, color_palette, @@ -167,7 +110,7 @@ impl CliColorConfig { match self.color_option { ColorOption::Never => false, ColorOption::Always => true, - ColorOption::Auto => self.color_palette.get_color_palette() != &ColorPalette::None, + ColorOption::Auto => self.color_palette != ColorPalette::None, } } @@ -176,8 +119,8 @@ impl CliColorConfig { /// # Returns /// /// * the color palette enum representing the supported colors - pub fn supported_colors(&self) -> &ColorPalette { - self.color_palette.get_color_palette() + fn supported_colors(&self) -> &ColorPalette { + &self.color_palette } /// parse args to check for --color=always|auto|never @@ -222,6 +165,7 @@ impl CliColorConfig { #[cfg(test)] mod tests { use super::*; + use crate::style::*; #[test] fn test_valid_arguments() { @@ -239,58 +183,13 @@ mod tests { assert_eq!(result, ColorOption::Auto); } - #[test] - fn test_color_option_from_string() { - assert_eq!( - ColorOption::from_string("always"), - Some(ColorOption::Always) - ); - assert_eq!(ColorOption::from_string("auto"), Some(ColorOption::Auto)); - assert_eq!(ColorOption::from_string("never"), Some(ColorOption::Never)); - assert_eq!(ColorOption::from_string("invalid"), None); - assert_eq!( - ColorOption::from_string(" Always "), - Some(ColorOption::Always) - ); - assert_eq!(ColorOption::from_string("neVeR"), Some(ColorOption::Never)); - } - - #[test] - fn test_cli_color_config_should_enable_color() { - let config_always = CliColorConfig::new( - ColorOption::Always, - AppColorPalette::new(ColorPalette::Truecolor), - ); - let config_auto = CliColorConfig::new( - ColorOption::Auto, - AppColorPalette::new(ColorPalette::Palette256), - ); - let config_auto_failed = - CliColorConfig::new(ColorOption::Auto, AppColorPalette::new(ColorPalette::None)); - let config_never = CliColorConfig::new( - ColorOption::Never, - AppColorPalette::new(ColorPalette::Palette16), - ); - - assert!(config_always.should_enable_color()); - assert!(config_auto.should_enable_color()); - assert!(!config_auto_failed.should_enable_color()); - assert!(!config_never.should_enable_color()); - } - #[test] fn test_combine_attributes() { - let attributes = combine_attributes(&[ - &style::Attribute::Bold, - &style::Attribute::Underlined, - &style::Attribute::Italic, - ]); + let attributes = + combine_attributes(&[&Attribute::Bold, &Attribute::Underlined, &Attribute::Italic]); assert_eq!( attributes, - style::Attributes::default() - | style::Attribute::Bold - | style::Attribute::Underlined - | style::Attribute::Italic + Attributes::default() | Attribute::Bold | Attribute::Underlined | Attribute::Italic ); } } diff --git a/src/helper/mod.rs b/src/helper/mod.rs deleted file mode 100644 index 9dd2c85..0000000 --- a/src/helper/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! helper mods - -pub(crate) mod colors; -pub(crate) mod iterators; diff --git a/src/helper/iterators.rs b/src/iterators.rs similarity index 97% rename from src/helper/iterators.rs rename to src/iterators.rs index 1c45d10..6e269b4 100644 --- a/src/helper/iterators.rs +++ b/src/iterators.rs @@ -1,3 +1,5 @@ +//! collection of reusable iterators + /// iterates over a collection of vectors in a balanced manner based on indices /// /// it allows users to retrieve values from each vector at specified index positions diff --git a/src/lib.rs b/src/lib.rs index b8d454e..2a8b6c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,39 +1,58 @@ #![warn(missing_docs)] #![warn(rustdoc::missing_crate_level_docs)] -#![warn(rustdoc::missing_doc_code_examples)] //! # Yet Another Spinner Lib //! +//! ## Changes +//! +//! **CHANGELOG.md** //! //! ## How to Use? //! //! It's as easy as pie (or maybe even easier, depending on your pie-making skills)! Just follow these simple steps: //! +//! ## Spinner +//! //! ```rust -//! // example/basic.rs -//! use std::thread::sleep; -//! use std::time::Duration; -//! use zenity::{style::Color, LoadingAnimation}; +//! // example/multi_spinner.rs +//! # use std::thread::sleep; +//! # use std::time::Duration; +//! use zenity::spinner::{MultiSpinner, Frames}; //! -//! fn main() { -//! println!("println test"); -//! scope_example(); -//! } +//! # fn main() { +//! let spinner = MultiSpinner::default(); +//! let spinner1 = spinner.get_last(); +//! let spinner2 = spinner.add(Frames::binary(false)); +//! +//! // start all spinners +//! spinner.run_all(); +//! # sleep(Duration::from_secs(2)); +//! +//! spinner.stop(&spinner2); +//! spinner.set_text(&spinner2, "Successfully".to_string()); +//!# } +//! ``` //! -//! fn scope_example() { -//! // create a LoadingAnimation instance using one of the predefined animations -//! let spinner = LoadingAnimation::default(); +//! ## Progress Bar +//!``` +//! // examples/progress.rs +//! # use rand::Rng; +//! # use std::thread; +//! # use std::time::Duration; +//! use zenity::progress::ProgressBar; //! -//! // optional: -//! spinner.set_text("Loading..."); // sets the text to "Loading..." -//! spinner.set_text_color(Color::DarkBlue); // set the color +//! # fn main() { +//! let progress = ProgressBar::default(); +//!# let loading = 1_usize; //! -//! sleep(Duration::from_secs(5)); -//! // `loading_animation` will run out of scope now and get dropped, -//! // thus the animation will stop and remove itself from the console +//! for loading in loading..=100 { +//! # thread::sleep(Duration::from_millis(rand::thread_rng().gen_range(1..=70))); +//! // do work... +//! progress.set(&progress.get_last(), &loading); //! } +//! +//! # } //! ``` -//! //! # Color Configuration //! //! To configure the color output, you can use the `--color` option with one of the following values: @@ -44,361 +63,16 @@ //! //! **Note**: If the stdout is a pipe or if the terminal doesn't support colors, colors will be automatically disabled //! -//! Check out the examples for more. - -use std::sync::{Arc, Mutex}; -use std::thread; - -pub use crossterm::style; - -pub use animations::spinner as multi_spinner; - -use crate::animations::animation::Spinner; -pub use crate::animations::frames::spinner; -pub use crate::helper::colors::{combine_attributes, CliColorConfig}; - -pub mod animations; -pub(crate) mod helper; +//! Check out the examples for more +//! +//! ## Feature Requests and Bug Reports +//! +//! If you have any ideas for new features or encounter any bugs while using Zenity, please don't hesitate to open an issue on [GitHub](https://github.com/Arteiii/zenity/issues). +//! Your feedback is valuable and will help improve the library for everyone. + +pub mod color; +mod iterators; +pub mod progress; +pub mod spinner; +pub mod style; pub(crate) mod terminal; - -/// `LoadingAnimation` is a struct that provides a straightforward interface for creating and managing customizable loading animations. -/// -/// # Examples -/// -/// ``` -/// use zenity::{spinner::PreDefined, LoadingAnimation}; -/// -/// // Create a loading animation instance using one of the predefined animations -/// let spinner = LoadingAnimation::new(PreDefined::dot_spinner1(false)); -/// spinner.set_text("Loading..."); // Sets the text to "Loading..." -/// ``` -/// -/// The `LoadingAnimation` struct offers various methods for customizing the loading animation: -/// -/// - `new(frames: spinner::Frames) -> Self`: Creates a new `LoadingAnimation` instance with the specified frames for the animation -/// - `set_text(text: &str)`: Sets the text content for the loading animation -/// - `finish()`: Stops the loading animation -/// - `set_animation_color(color: style::Color)`: Sets the color of the animation -/// - `set_text_color(color: style::Color)`: Sets the color of the text -/// - `set_animation_style(color: style::ContentStyle)`: Sets the style for the animation -/// - `set_text_style(color: style::ContentStyle)`: Sets the style for the text -/// -/// # Notes -/// -/// The `LoadingAnimation` struct automatically stops the loading animation when it goes out of scope. However, you can explicitly call the `finish()` method to stop the animation at any time -/// -/// # Thread Safety -/// -/// `LoadingAnimation` is thread-safe and can be safely shared across multiple threads. It uses `Arc` and `Mutex` internally to ensure safe concurrent access to its fields -/// -/// # Error Handling -/// -/// Error handling is minimal in this struct. However, methods that may encounter errors (e.g., `set_text()`) return a `Result` type to handle potential errors gracefully -/// -/// # Performance Considerations -/// -/// While `LoadingAnimation` strives for efficiency, creating complex animations or frequently updating the animation's appearance may impact performance. Consider optimizing your usage based on performance requirements -pub struct LoadingAnimation { - should_stop: Arc>, - handle: Option>, - text: Arc>>, - end_sequence: Arc>>, - animation_style: Arc>, - text_style: Arc>, - cleanup_on_exit: Arc>, - color_support: Arc>, -} - -impl Default for LoadingAnimation { - fn default() -> Self { - let animation_style = Arc::new(Mutex::new(style::ContentStyle { - foreground_color: Some(style::Color::White), - background_color: None, - underline_color: None, - attributes: style::Attributes::default(), - })); - - let text_style = Arc::new(Mutex::new(style::ContentStyle { - foreground_color: Some(style::Color::White), - background_color: None, - underline_color: None, - attributes: style::Attributes::default(), - })); - - Self::with_colors( - spinner::PreDefined::dot_spinner1(false), - animation_style, - text_style, - CliColorConfig::default(), - ) - } -} - -impl LoadingAnimation { - /// creates a new `LoadingAnimation` instance and starts the loading animation - /// - /// # Arguments - /// - /// * `frames` - The frames to be used for the loading animation - /// (you can find predefined ones in PreDefined::) - /// - /// # Returns - /// - /// a new `LoadingAnimation` instance - pub fn new(frames: spinner::Frames) -> Self { - let default_animation = Self::default(); - Self::with_colors( - frames, - Arc::clone(&default_animation.animation_style), - Arc::clone(&default_animation.text_style), - CliColorConfig::default(), - ) - } - - /// creates a new `LoadingAnimation` instance with specified colors and starts the loading animation - /// - /// # Arguments - /// - /// * `frames` - the frames to be used for the loading animation - /// * `animation_color` - the color of the animation - /// * `text_color` - the color of the text - /// - /// # Returns - /// - /// a new `LoadingAnimation` instance with specified colors - pub fn with_colors( - frames: spinner::Frames, - animation_style_mutex: Arc>, - text_style_mutex: Arc>, - color_support: CliColorConfig, - ) -> Self { - let frames = Arc::new(Mutex::new(frames)); - let cleanup_on_exit = Arc::new(Mutex::new(true)); - let should_stop = Arc::new(Mutex::new(false)); - let text = Arc::new(Mutex::new(None)); - let end_sequence = Arc::new(Mutex::new(None)); - let color_support = Arc::new(Mutex::new(color_support)); - - let should_stop_clone = Arc::clone(&should_stop); - let text_clone = Arc::clone(&text); - let end_sequence_clone = Arc::clone(&end_sequence); - let animation_style_clone = Arc::clone(&animation_style_mutex); - let text_style_clone = Arc::clone(&text_style_mutex); - let cleanup_on_exit_clone = Arc::clone(&cleanup_on_exit); - - // TODO: implement - // let color_support_clone = Arc::clone(&color_support); - - let spinner = Spinner::new( - frames, - should_stop_clone, - text_clone, - animation_style_clone, - text_style_clone, - end_sequence_clone, - cleanup_on_exit_clone, - ); - - let handle = thread::spawn(move || spinner.run()); - - Self { - should_stop, - handle: Some(handle), - text, - animation_style: animation_style_mutex, - text_style: text_style_mutex, - end_sequence, - cleanup_on_exit, - color_support, - } - } - - /// sets the text content for the loading animation - /// - /// this function updates the text content displayed alongside the loading animation - /// - /// # Arguments - /// - /// * `text` - a string slice (`&str`) representing the new text content to be displayed - /// - /// # Example - /// - /// ``` - /// use zenity::LoadingAnimation; - /// let spinner = LoadingAnimation::default(); - /// // update the text content of the spinner animation. - /// spinner.set_text("Loading..."); // ets the text to "Loading..." - /// ``` - pub fn set_text(&self, text: &str) { - let mut guard = self.text.lock().unwrap(); - *guard = Some(text.to_string()); // update the text value - } - - /// sets the color of the animation - /// - /// # Arguments - /// - /// * `color` - the color to set for the animation - /// - /// # Example - /// - /// ``` - /// use zenity::{LoadingAnimation, style::Color}; - /// let spinner = LoadingAnimation::default(); - /// - /// spinner.set_animation_color(Color::Red); // sets the animation color to Red - /// ``` - pub fn set_animation_color(&self, color: style::Color) { - if !self.color_support.lock().unwrap().should_enable_color() { - *self.animation_style.lock().unwrap() = style::ContentStyle { - foreground_color: Some(color), - background_color: None, - underline_color: None, - attributes: style::Attributes::default(), - }; - } - } - - /// sets the color of the text - /// - /// # Arguments - /// - /// * `color` - the color to set for the text - /// # Example - /// - /// ``` - /// use zenity::{LoadingAnimation, style::Color}; - /// let spinner = LoadingAnimation::default(); - /// - /// spinner.set_text_color(Color::Red); // sets the text color to Red - /// ``` - pub fn set_text_color(&self, color: style::Color) { - if !self.color_support.lock().unwrap().should_enable_color() { - *self.text_style.lock().unwrap() = style::ContentStyle { - foreground_color: Some(color), - background_color: None, - underline_color: None, - attributes: style::Attributes::default(), - }; - } - } - - /// sets the style of the animation - /// - /// not all styles/color can be applied to all animations - /// - /// # Example - /// - /// ``` - /// use zenity::{LoadingAnimation, style::{Attribute, ContentStyle, Color}, combine_attributes}; - /// let spinner = LoadingAnimation::default(); - /// - /// let style = ContentStyle { - /// background_color: None, - /// underline_color: Some(Color::Red), - /// foreground_color: Some(Color::Rgb {r: 255, g:255, b:255}), - /// - /// // combine attributes is a helper function to combine multiple style elements and apply them - /// attributes: combine_attributes(&[ - /// &Attribute::Bold, - /// &Attribute::Underlined, - /// ]), - /// }; - /// spinner.set_animation_style(style); // sets the aniamtion style - /// ``` - pub fn set_animation_style(&self, color: style::ContentStyle) { - if !self.color_support.lock().unwrap().should_enable_color() { - *self.animation_style.lock().unwrap() = color; - } - } - - /// sets the style of the text - /// - /// # Example - /// - /// ``` - /// use zenity::{LoadingAnimation, style::{Attribute, ContentStyle, Color}, combine_attributes}; - /// let spinner = LoadingAnimation::default(); - /// - /// let style = ContentStyle { - /// background_color: None, - /// underline_color: Some(Color::Red), - /// foreground_color: Some(Color::Rgb {r: 255, g:255, b:255}), - /// - /// // combine attributes is a helper function to combine multiple style elements and apply them - /// attributes: combine_attributes(&[ - /// &Attribute::Bold, - /// &Attribute::Underlined, - /// ]), - /// }; - /// spinner.set_text_style(style); // sets the text style - /// ``` - pub fn set_text_style(&self, color: style::ContentStyle) { - if !self.color_support.lock().unwrap().should_enable_color() { - *self.text_style.lock().unwrap() = color; - } - } - - /// stop and delete the animation from the console - pub fn stop_and_discard(&mut self) { - self.finish(); - } - - /// stops the loading animation without clearing it from the console - /// - /// # Arguments - /// - /// * `spinner` - optional string slice (`&str`) representing the new spinner frame - /// * `text` - optional string slice (`&str`) representing the new text content to be displayed - /// * `text_color` - optional `ContentStyle` representing the color of the text - /// - /// if `spinner` is provided, it will replace the last spinner frame - /// if `text` is provided, it will replace the text field - /// if `text_color` is provided, it will set the color of the text - /// - /// the loading animation will be stopped after this method is called, but it won't be cleared from the console - pub fn stop_and_persist( - &mut self, - spinner: Option<&str>, - text: Option<&str>, - text_color: Option, - ) { - // set cleanup_on_exit to false - *self.cleanup_on_exit.lock().unwrap() = false; - - if let Some(spinner_seq) = spinner { - *self.end_sequence.lock().unwrap() = Some(spinner_seq.to_string()); - } - - if let Some(text_seq) = text { - let mut guard = self.text.lock().unwrap(); - *guard = Some(text_seq.to_string()); - } - - if let Some(color) = text_color { - if !self.color_support.lock().unwrap().should_enable_color() { - *self.text_style.lock().unwrap() = color; - } - } - - // stop the animation - self.finish(); - } - - /// stops the loading animation - /// - /// this method sets the flag to stop the animation and waits for the animation thread to join - fn finish(&mut self) { - *self.should_stop.lock().unwrap() = true; - if let Some(handle) = self.handle.take() { - handle.join().unwrap(); - } - } -} - -impl Drop for LoadingAnimation { - /// stops the loading animation thread when the `LoadingAnimation` object is dropped - fn drop(&mut self) { - self.finish(); - } -} diff --git a/src/progress/frames.rs b/src/progress/frames.rs new file mode 100644 index 0000000..37c87e3 --- /dev/null +++ b/src/progress/frames.rs @@ -0,0 +1,142 @@ +//! progressbar frames + +use std::sync::{Arc, Mutex}; + +/// struct storing the data needed to render a ProgressBar +#[derive(Clone)] +pub struct Frames { + /// begin string + pub begin: Vec<&'static str>, + + /// string to place on complete places + pub bar_complete_char: Vec<&'static str>, + + /// string to place on incomplete places + pub bar_incomplete_char: Vec<&'static str>, + + /// ending string + pub end: Vec<&'static str>, + + /// size of progress bar + pub size: Arc>, + + /// goal value + pub goal: Arc>, + + /// current value + pub current: Arc>, +} + +// TODO: add animations by adding +1 for each bar so you can have a wave animation and others + +impl Default for Frames { + fn default() -> Self { + Self::equal() + } +} + +impl Frames { + /// generates frames for + /// + /// # Arguments + /// + /// * `pattern` - a vector of strings representing the frames of the spinner animation + /// * `inverted` - a boolean flag indicating whether the direction of rotation should be reversed + /// * `speed_ms` - the speed at which each frame should be displayed, in milliseconds + /// + /// # Example + /// + /// ``` + /// use zenity::progress::Frames; + /// + /// let spinner_frames = Frames::new(vec!["["], vec!["="], vec!["-"], vec!["]"]); + /// + /// # assert_eq!(spinner_frames.begin, vec!["["]); + /// # assert_eq!(spinner_frames.bar_complete_char, vec!["="]); + /// # assert_eq!(spinner_frames.bar_incomplete_char, vec!["-"]); + /// # assert_eq!(spinner_frames.end, vec!["]"]); + /// ``` + pub fn new( + begin: Vec<&'static str>, + bar_complete_char: Vec<&'static str>, + bar_incomplete_char: Vec<&'static str>, + end: Vec<&'static str>, + ) -> Frames { + Frames { + begin, + bar_complete_char, + bar_incomplete_char, + end, + size: Arc::new(Mutex::new(30)), + goal: Arc::new(Mutex::new(100)), + current: Arc::new(Mutex::new(0)), + } + } + + /// Sets the size of the progress bar. + /// + /// # Arguments + /// + /// * `size` - The size of the progress bar as an usize, where 1 represents one character in the loading bar. + /// + /// # Returns + /// + /// A new Bar object with the modified size. + pub fn set_size(&self, size: usize) -> Self { + *self.size.lock().unwrap() = size; + + self.clone() + } + + /// sets the goal value + /// + /// # Arguments + /// + /// * `goal` - the new goal value + /// + /// # Returns + /// + /// a new Bar object with the modified goal value + pub fn set_goal(&self, goal: usize) -> Self { + let mut current = self.current.lock().unwrap(); + let mut goal_ref = self.goal.lock().unwrap(); + *goal_ref = goal; + *current = current.min(goal); + + self.clone() + } + + /// increments the current value + /// + /// # Arguments + /// + /// * `num` - the amount to increment by + /// + /// # Returns + /// + /// a new object with the modified current value + pub fn inc(&self, num: &usize) -> Self { + let mut current = self.current.lock().unwrap(); + let goal = *self.goal.lock().unwrap(); + let new_current = (*current + num).min(goal); + *current = new_current; + + self.clone() + } + + /// '=' as the complete char and '-' as the incomplete char + pub fn equal() -> Self { + Self::new(vec!["["], vec!["="], vec!["-"], vec!["]"]) + } + + /// '#' as the complete char and '.' as the incomplete char + pub fn hash() -> Self { + Self::new(vec!["["], vec!["#"], vec!["."], vec!["]"]) + } + /// '#' as the complete char and '.' as the incomplete char + pub fn rect() -> Self { + Self::new(vec![" "], vec!["\u{25A0}"], vec![" "], vec![" "]) + } + + // TODO: add more +} diff --git a/src/animations/progress.rs b/src/progress/mod.rs similarity index 62% rename from src/animations/progress.rs rename to src/progress/mod.rs index 19d3394..215b9fa 100644 --- a/src/animations/progress.rs +++ b/src/progress/mod.rs @@ -1,91 +1,76 @@ //! mod for progress bars - use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::thread; -use rand::Rng; +pub use frames::*; -use crate::animations::frames::progress::ProgressBarFrames; use crate::terminal::{console_cursor, console_render}; -/// bar struct encapsulating the loading bar data animation -pub struct Bar { - /// frames to use for animation - pub frames: Arc>, - - /// size of progress bar - pub size: Arc>, +pub mod frames; - /// goal value - pub goal: Arc>, - - /// current value - pub current: Arc>, -} - -impl Default for Bar { - fn default() -> Self { - Bar { - frames: Arc::new(Mutex::new(ProgressBarFrames::equal())), - size: Arc::new(Mutex::new(31)), - goal: Arc::new(Mutex::new(253)), - current: Arc::new(Mutex::new(0)), - } - } -} /// struct holding multiple bars -pub struct Progress { +#[derive(Clone)] +pub struct ProgressBar { // TODO: instead of random ids go after creation and increment by one // this would allow to render them line for line based on this and order them correctly - bar: Arc>>, + bar: Arc>>, stop: Arc>, } -impl Default for Progress { +impl Default for ProgressBar { fn default() -> Self { - Self::new() + let progress = Self::new(Frames::default()); + + progress.run_all(); + + progress } } -impl Progress { +impl ProgressBar { /// creates a new Progress instance /// /// ## Example /// ``` - /// # use zenity::multi_spinner::MultiSpinner; - /// let _spinner = MultiSpinner::new(); + /// # use zenity::progress::{Frames, ProgressBar}; + /// let _spinner = ProgressBar::new(Frames::default()); /// ``` - pub fn new() -> Self { + pub fn new(bar: Frames) -> Self { // console_cursor::reset_cursor(); console_cursor::save_hide_cursor(); - Progress { + let progress = ProgressBar { bar: Arc::new(Mutex::new(HashMap::new())), stop: Arc::new(Mutex::new(false)), - } - } + }; - /// add a new progress bar - pub fn add(&self, bar: Bar) -> usize { - let mut rng = rand::thread_rng(); - let mut uid: usize; + progress.add(bar); - loop { - uid = rng.gen(); - if !self.bar.lock().unwrap().contains_key(&uid) { - break; - } - } + progress + } - self.bar.lock().unwrap().insert(uid, bar); + /// adds a new progress bar with an incremental UID starting from 1 + /// + /// # Arguments + /// + /// * `bar` - the progress bar to add + /// + /// # Returns + /// + /// the UID assigned to the added progress bar + pub fn add(&self, bar: Frames) -> usize { + let mut bar_map = self.bar.lock().unwrap(); + let uid: usize = bar_map.len() + 1_usize; // Incremental UID starting from 1 + + bar_map.insert(uid, bar); uid } - /// set the current + /// Set the current value /// /// # Arguments /// @@ -94,16 +79,18 @@ impl Progress { /// /// **NOTE:** /// - if the UID is invalid, this function does nothing - /// - this function locks the progress bar associated with the provided uid and updates its current value + /// - this function locks the progress bar associated with the provided UID and updates its current value incrementally pub fn set(&self, uid: &usize, new_current: &usize) { if let Some(bar) = self.bar.lock().unwrap().get(uid) { - let mut current = bar.current.lock().unwrap(); - *current = *new_current; + let current = bar.current.lock().unwrap(); + let diff = new_current.saturating_sub(*current); + drop(current); + bar.inc(&diff); } } /// start each queued progressbar - pub fn run_all(&mut self) { + pub fn run_all(&self) { let bars = Arc::clone(&self.bar); let stop = Arc::clone(&self.stop); @@ -111,16 +98,15 @@ impl Progress { while !*stop.lock().unwrap() { let mut rendered_frames = Vec::new(); - for (_, spinner) in bars.lock().unwrap().iter() { - let frames = spinner.frames.lock().unwrap(); + for (_, frames) in bars.lock().unwrap().iter() { let begin: &str = frames.begin[0]; let end: &str = frames.end[0]; let current_incomplete: &str = frames.bar_incomplete_char[0]; let current_complete: &str = frames.bar_complete_char[0]; - let size: usize = *spinner.size.lock().unwrap(); - let goal = *spinner.goal.lock().unwrap(); - let current: usize = *spinner.current.lock().unwrap(); + let size: usize = *frames.size.lock().unwrap(); + let goal = *frames.goal.lock().unwrap(); + let current: usize = *frames.current.lock().unwrap(); // calculate percentage completion let completion_percentage = (current as f64 / goal as f64) * 100.0; @@ -149,13 +135,24 @@ impl Progress { } }); } + + /// retrieves the UID of the last created progress bar + /// + /// # Returns + /// + /// the UID of the last created progress bar + pub fn get_last(&self) -> usize { + let bar_map = self.bar.lock().unwrap(); + bar_map.len() + } } -impl Drop for Progress { +impl Drop for ProgressBar { /// stops the thread when the object is dropped fn drop(&mut self) { + *self.stop.lock().unwrap() = true; // cleanup methods - console_render::cleanup(); console_cursor::reset_cursor(); + console_cursor::next_line(self.bar.lock().unwrap().len() as u16); } } diff --git a/src/animations/frames/spinner.rs b/src/spinner/frames.rs similarity index 79% rename from src/animations/frames/spinner.rs rename to src/spinner/frames.rs index fe95dec..7d2dcbf 100644 --- a/src/animations/frames/spinner.rs +++ b/src/spinner/frames.rs @@ -5,7 +5,7 @@ /// # Example /// /// ``` -/// use zenity::animations::frames::spinner::Frames; +/// use zenity::spinner::Frames; /// /// let frames: Frames = Frames { frames: vec!["◐", "◓", "◑", "◒"], speed_ms: 100 }; /// assert_eq!(frames.frames, vec!["◐", "◓", "◑", "◒"]); @@ -18,10 +18,13 @@ pub struct Frames { pub speed_ms: u64, } -/// Provides predefined spinner animations -pub struct PreDefined; +impl Default for Frames { + fn default() -> Self { + Self::dots_simple_big1(false) + } +} -impl PreDefined { +impl Frames { /// generates frames for spinner animation based on the provided pattern, inversion flag, and speed /// /// # Arguments @@ -33,9 +36,9 @@ impl PreDefined { /// # Example /// /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::generate_frames(vec!["◐", "◓", "◑", "◒"], false, 100); + /// let spinner_frames = Frames::generate_frames(vec!["◐", "◓", "◑", "◒"], false, 100); /// /// assert_eq!(spinner_frames.frames, vec!["◐", "◓", "◑", "◒"]); /// assert_eq!(spinner_frames.speed_ms, 100); @@ -50,15 +53,16 @@ impl PreDefined { Frames { frames, speed_ms } } + /// ⠋ /// ⠹ /// ⠧ /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::Frames; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner1(false); + /// let spinner_frames: Frames = Frames::dot_spinner1(false); /// ``` pub fn dot_spinner1(inverted: bool) -> Frames { let pattern = vec!["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; @@ -69,9 +73,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner2(false); + /// let spinner_frames: Frames = Frames::dot_spinner2(false); /// ``` pub fn dot_spinner2(inverted: bool) -> Frames { let pattern = vec!["⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾"]; @@ -82,9 +86,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner3(false); + /// let spinner_frames: Frames = Frames::dot_spinner3(false); /// ``` pub fn dot_spinner3(inverted: bool) -> Frames { let pattern = vec!["⠋", "⠙", "⠚", "⠞", "⠖", "⠦", "⠴", "⠲", "⠳", "⠓"]; @@ -95,9 +99,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner4(false); + /// let spinner_frames: Frames = Frames::dot_spinner4(false); /// ``` pub fn dot_spinner4(inverted: bool) -> Frames { let pattern = vec![ @@ -110,9 +114,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner5(false); + /// let spinner_frames: Frames = Frames::dot_spinner5(false); /// ``` pub fn dot_spinner5(inverted: bool) -> Frames { let pattern = vec![ @@ -142,9 +146,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner6(false); + /// let spinner_frames: Frames = Frames::dot_spinner6(false); /// ``` pub fn dot_spinner6(inverted: bool) -> Frames { let pattern = vec!["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"]; @@ -155,9 +159,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner7(false); + /// let spinner_frames: Frames = Frames::dot_spinner7(false); /// ``` pub fn dot_spinner7(inverted: bool) -> Frames { let pattern = vec!["⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"]; @@ -168,9 +172,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner8(false); + /// let spinner_frames: Frames = Frames::dot_spinner8(false); /// ``` pub fn dot_spinner8(inverted: bool) -> Frames { let pattern = vec![ @@ -185,9 +189,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner9(false); + /// let spinner_frames: Frames = Frames::dot_spinner9(false); /// ``` pub fn dot_spinner9(inverted: bool) -> Frames { let pattern = vec![ @@ -203,9 +207,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner10(false); + /// let spinner_frames: Frames = Frames::dot_spinner10(false); /// ``` pub fn dot_spinner10(inverted: bool) -> Frames { let pattern = vec!["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"]; @@ -216,9 +220,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_spinner11(false); + /// let spinner_frames: Frames = Frames::dot_spinner11(false); /// ``` pub fn dot_spinner11(inverted: bool) -> Frames { let pattern = vec!["⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"]; @@ -233,9 +237,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::kaomoji(false); + /// let spinner_frames: Frames = Frames::kaomoji(false); /// ``` pub fn kaomoji(inverted: bool) -> Frames { let pattern = vec![ @@ -260,9 +264,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::kaomoji(false); + /// let spinner_frames: Frames = Frames::kaomoji(false); /// ``` pub fn aesthetic_spin(inverted: bool) -> Frames { let pattern = vec![ @@ -289,9 +293,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::aesthetic_load(false); + /// let spinner_frames: Frames = Frames::aesthetic_load(false); /// ``` pub fn aesthetic_load(inverted: bool) -> Frames { let pattern = vec![ @@ -313,9 +317,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::clock(false); + /// let spinner_frames: Frames = Frames::clock(false); /// ``` pub fn clock(inverted: bool) -> Frames { let pattern = vec![ @@ -330,9 +334,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::small_bouncing_bar(false); + /// let spinner_frames: Frames = Frames::small_bouncing_bar(false); /// ``` pub fn small_bouncing_bar(inverted: bool) -> Frames { let pattern = vec![ @@ -348,9 +352,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::small_loading_bar(false); + /// let spinner_frames: Frames = Frames::small_loading_bar(false); /// ``` pub fn small_loading_bar(inverted: bool) -> Frames { let pattern = vec![ @@ -363,9 +367,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::loading_bar_with_arrow(false); + /// let spinner_frames: Frames = Frames::loading_bar_with_arrow(false); /// ``` pub fn loading_bar_with_arrow(inverted: bool) -> Frames { let pattern = vec![ @@ -389,9 +393,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::short_loading_bar_with_arrow(false); + /// let spinner_frames: Frames = Frames::short_loading_bar_with_arrow(false); /// ``` pub fn short_loading_bar_with_arrow(inverted: bool) -> Frames { let pattern = vec![ @@ -419,9 +423,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::material(false); + /// let spinner_frames: Frames = Frames::material(false); /// ``` pub fn material(inverted: bool) -> Frames { let pattern = vec![ @@ -527,9 +531,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::moon(false); + /// let spinner_frames: Frames = Frames::moon(false); /// ``` pub fn moon(inverted: bool) -> Frames { let pattern = vec!["🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "]; @@ -542,9 +546,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dots_simple1(false); + /// let spinner_frames: Frames = Frames::dots_simple1(false); /// ``` pub fn dots_simple1(inverted: bool) -> Frames { let pattern = vec![". ", ".. ", "...", " ..", " .", " "]; @@ -557,9 +561,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dots_simple2(false); + /// let spinner_frames: Frames = Frames::dots_simple2(false); /// ``` pub fn dots_simple2(inverted: bool) -> Frames { let pattern = vec![" ", ". ", ".. ", "..."]; @@ -572,9 +576,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::japanese(false); + /// let spinner_frames: Frames = Frames::japanese(false); /// ``` pub fn japanese(inverted: bool) -> Frames { let pattern = vec![ @@ -592,9 +596,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::line(false); + /// let spinner_frames: Frames = Frames::line(false); /// ``` pub fn line(inverted: bool) -> Frames { let pattern = vec![ @@ -611,9 +615,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::line2(false); + /// let spinner_frames: Frames = Frames::line2(false); /// ``` pub fn line2(inverted: bool) -> Frames { let pattern = vec![ @@ -642,9 +646,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::block(false); + /// let spinner_frames: Frames = Frames::block(false); /// ``` pub fn block(inverted: bool) -> Frames { let pattern = vec![ @@ -659,9 +663,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::block_spinn(false); + /// let spinner_frames: Frames = Frames::block_spinn(false); /// ``` pub fn block_spinn(inverted: bool) -> Frames { let pattern = vec!["▖", "▘", "▝", "▗"]; @@ -674,9 +678,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::arrow_spinn(false); + /// let spinner_frames: Frames = Frames::arrow_spinn(false); /// ``` pub fn arrow_spinn(inverted: bool) -> Frames { let pattern = vec!["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"]; @@ -689,9 +693,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::big_arrow_spinn(false); + /// let spinner_frames: Frames = Frames::big_arrow_spinn(false); /// ``` pub fn big_arrow_spinn(inverted: bool) -> Frames { let pattern = vec!["⇐", "⇖", "⇑", "⇗", "⇒", "⇘", "⇓", "⇙"]; @@ -704,9 +708,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::line_spinner(false); + /// let spinner_frames: Frames = Frames::line_spinner(false); /// ``` pub fn line_spinner(inverted: bool) -> Frames { let pattern = vec!["┤", "┘", "┴", "└", "├", "┌", "┬", "┐"]; @@ -719,9 +723,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::line_spinner_simple(false); + /// let spinner_frames: Frames = Frames::line_spinner_simple(false); /// ``` pub fn line_spinner_simple(inverted: bool) -> Frames { let pattern = vec!["|", "/", "-", "\\"]; @@ -734,9 +738,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::corner(false); + /// let spinner_frames: Frames = Frames::corner(false); /// ``` pub fn corner(inverted: bool) -> Frames { let pattern = vec!["◢", "◣", "◤", "◥"]; @@ -749,9 +753,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::abc(false); + /// let spinner_frames: Frames = Frames::abc(false); /// ``` pub fn abc(inverted: bool) -> Frames { let pattern = vec![ @@ -767,9 +771,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::earth(false); + /// let spinner_frames: Frames = Frames::earth(false); /// ``` pub fn earth(inverted: bool) -> Frames { let pattern = vec!["🌍", "🌎", "🌏"]; @@ -782,9 +786,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::arrow_row(false); + /// let spinner_frames: Frames = Frames::arrow_row(false); /// ``` pub fn arrow_row(inverted: bool) -> Frames { let pattern = vec!["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"]; @@ -797,9 +801,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::fractions(false); + /// let spinner_frames: Frames = Frames::fractions(false); /// ``` pub fn fractions(inverted: bool) -> Frames { let pattern = vec!["½", "⅓", "⅔", "¼", "¾", "⅛", "⅜", "⅝", "⅞"]; @@ -812,9 +816,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::star1(false); + /// let spinner_frames: Frames = Frames::star1(false); /// ``` pub fn star1(inverted: bool) -> Frames { let pattern = vec!["✶", "✸", "✹", "✺", "✹", "✷"]; @@ -826,9 +830,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::star2(false); + /// let spinner_frames: Frames = Frames::star2(false); /// ``` pub fn star2(inverted: bool) -> Frames { let pattern = vec!["+", "x", "*"]; @@ -841,9 +845,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_bounce(false); + /// let spinner_frames: Frames = Frames::dot_bounce(false); /// ``` pub fn dot_bounce(inverted: bool) -> Frames { let pattern = vec![".", "o", "O", "°", "O", "o", "."]; @@ -855,9 +859,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::flip(false); + /// let spinner_frames: Frames = Frames::flip(false); /// ``` pub fn flip(inverted: bool) -> Frames { let pattern = vec!["_", "_", "_", "-", "`", "`", "'", "´", "-", "_", "_", "_"]; @@ -869,9 +873,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::binary(false); + /// let spinner_frames: Frames = Frames::binary(false); /// ``` pub fn binary(inverted: bool) -> Frames { let pattern = vec![ @@ -887,9 +891,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::big_loading_bar(false); + /// let spinner_frames: Frames = Frames::big_loading_bar(false); /// ``` pub fn big_loading_bar(inverted: bool) -> Frames { let pattern = vec![ @@ -909,9 +913,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::wall_bounce(false); + /// let spinner_frames: Frames = Frames::wall_bounce(false); /// ``` pub fn wall_bounce(inverted: bool) -> Frames { let pattern = vec![ @@ -955,9 +959,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::wall_bounce_line(false); + /// let spinner_frames: Frames = Frames::wall_bounce_line(false); /// ``` pub fn wall_bounce_line(inverted: bool) -> Frames { let pattern = vec![ @@ -997,9 +1001,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::stack(false); + /// let spinner_frames: Frames = Frames::stack(false); /// ``` pub fn stack(inverted: bool) -> Frames { let pattern = vec!["☱", "☲", "☴"]; @@ -1012,9 +1016,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle(false); + /// let spinner_frames: Frames = Frames::toggle(false); /// ``` pub fn toggle(inverted: bool) -> Frames { let pattern = vec!["⊶", "⊷"]; @@ -1027,9 +1031,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle2(false); + /// let spinner_frames: Frames = Frames::toggle2(false); /// ``` pub fn toggle2(inverted: bool) -> Frames { let pattern = vec!["▫", "▪"]; @@ -1042,9 +1046,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle3(false); + /// let spinner_frames: Frames = Frames::toggle3(false); /// ``` pub fn toggle3(inverted: bool) -> Frames { let pattern = vec!["□", "■"]; @@ -1057,9 +1061,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle4(false); + /// let spinner_frames: Frames = Frames::toggle4(false); /// ``` pub fn toggle4(inverted: bool) -> Frames { let pattern = vec!["■", "□", "▪", "▫"]; @@ -1072,9 +1076,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle5(false); + /// let spinner_frames: Frames = Frames::toggle5(false); /// ``` pub fn toggle5(inverted: bool) -> Frames { let pattern = vec!["▮ ", "▯ "]; @@ -1087,9 +1091,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle6(false); + /// let spinner_frames: Frames = Frames::toggle6(false); /// ``` pub fn toggle6(inverted: bool) -> Frames { let pattern = vec!["ဝ", "၀"]; @@ -1102,9 +1106,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle7(false); + /// let spinner_frames: Frames = Frames::toggle7(false); /// ``` pub fn toggle7(inverted: bool) -> Frames { let pattern = vec!["⦾", "⦿"]; @@ -1117,9 +1121,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle8(false); + /// let spinner_frames: Frames = Frames::toggle8(false); /// ``` pub fn toggle8(inverted: bool) -> Frames { let pattern = vec!["◍", "◌"]; @@ -1132,9 +1136,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle9(false); + /// let spinner_frames: Frames = Frames::toggle9(false); /// ``` pub fn toggle9(inverted: bool) -> Frames { let pattern = vec!["◉", "◎"]; @@ -1147,9 +1151,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle10(false); + /// let spinner_frames: Frames = Frames::toggle10(false); /// ``` pub fn toggle10(inverted: bool) -> Frames { let pattern = vec!["㊂", "㊀", "㊁"]; @@ -1162,9 +1166,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle11(false); + /// let spinner_frames: Frames = Frames::toggle11(false); /// ``` pub fn toggle11(inverted: bool) -> Frames { let pattern = vec!["⧇", "⧆"]; @@ -1177,9 +1181,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle12(false); + /// let spinner_frames: Frames = Frames::toggle12(false); /// ``` pub fn toggle12(inverted: bool) -> Frames { let pattern = vec!["☗", "☖"]; @@ -1192,9 +1196,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::toggle13(false); + /// let spinner_frames: Frames = Frames::toggle13(false); /// ``` pub fn toggle13(inverted: bool) -> Frames { let pattern = vec!["=", "*", "-"]; @@ -1206,9 +1210,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::arc(false); + /// let spinner_frames: Frames = Frames::arc(false); /// ``` pub fn arc(inverted: bool) -> Frames { let pattern = vec!["◜", "◠", "◝", "◞", "◡", "◟"]; @@ -1220,9 +1224,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::circle(false); + /// let spinner_frames: Frames = Frames::circle(false); /// ``` pub fn circle(inverted: bool) -> Frames { let pattern = vec!["◡", "⊙", "◠"]; @@ -1234,9 +1238,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::square_corners(false); + /// let spinner_frames: Frames = Frames::square_corners(false); /// ``` pub fn square_corners(inverted: bool) -> Frames { let pattern = vec!["◰ ", "◳ ", "◲ ", "◱ "]; @@ -1248,9 +1252,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::circle_corners(false); + /// let spinner_frames: Frames = Frames::circle_corners(false); /// ``` pub fn circle_corners(inverted: bool) -> Frames { let pattern = vec!["◴ ", "◷ ", "◶ ", "◵ "]; @@ -1262,9 +1266,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::circle_halves(false); + /// let spinner_frames: Frames = Frames::circle_halves(false); /// ``` pub fn circle_halves(inverted: bool) -> Frames { let pattern = vec!["◐ ", "◓ ", "◑ ", "◒ "]; @@ -1276,9 +1280,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::bouncing_ball(false); + /// let spinner_frames: Frames = Frames::bouncing_ball(false); /// ``` pub fn bouncing_ball(inverted: bool) -> Frames { let pattern = vec![ @@ -1302,9 +1306,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::smiley(false); + /// let spinner_frames: Frames = Frames::smiley(false); /// ``` pub fn smiley(inverted: bool) -> Frames { let pattern = vec!["😄 ", "😝 "]; @@ -1317,9 +1321,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::monkey(false); + /// let spinner_frames: Frames = Frames::monkey(false); /// ``` pub fn monkey(inverted: bool) -> Frames { let pattern = vec!["🙈 ", "🙈 ", "🙉 ", "🙊 "]; @@ -1332,9 +1336,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::hearts(false); + /// let spinner_frames: Frames = Frames::hearts(false); /// ``` pub fn hearts(inverted: bool) -> Frames { let pattern = vec!["💛 ", "💙 ", "💜 ", "💚 ", "❤️ "]; @@ -1347,9 +1351,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::runner(false); + /// let spinner_frames: Frames = Frames::runner(false); /// ``` pub fn runner(inverted: bool) -> Frames { let pattern = vec!["🚶 ", "🏃 "]; @@ -1362,9 +1366,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::raining(false); + /// let spinner_frames: Frames = Frames::raining(false); /// ``` pub fn raining(inverted: bool) -> Frames { let pattern = vec!["🌧 ", "🌨 ", "🌧 ", "🌨 ", "🌧 ", "🌨 ", "🌨 ", "🌧 ", "🌨 "]; @@ -1377,9 +1381,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::weather(false); + /// let spinner_frames: Frames = Frames::weather(false); /// ``` pub fn weather(inverted: bool) -> Frames { let pattern = vec![ @@ -1394,9 +1398,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::christmas_tree(false); + /// let spinner_frames: Frames = Frames::christmas_tree(false); /// ``` pub fn christmas_tree(inverted: bool) -> Frames { let pattern = vec!["🌲", "🎄"]; @@ -1408,9 +1412,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::nade(false); + /// let spinner_frames: Frames = Frames::nade(false); /// ``` pub fn nade(inverted: bool) -> Frames { let pattern = vec![ @@ -1425,9 +1429,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dots_simple_big1(false); + /// let spinner_frames: Frames = Frames::dots_simple_big1(false); /// ``` pub fn dots_simple_big1(inverted: bool) -> Frames { let pattern = vec!["●∙∙", "∙●∙", "∙∙●"]; @@ -1439,9 +1443,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dots_simple_big2(false); + /// let spinner_frames: Frames = Frames::dots_simple_big2(false); /// ``` pub fn dots_simple_big2(inverted: bool) -> Frames { let pattern = vec!["∙∙∙", "●∙∙", "∙●∙", "∙∙●"]; @@ -1453,9 +1457,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dots_simple_big3(false); + /// let spinner_frames: Frames = Frames::dots_simple_big3(false); /// ``` pub fn dots_simple_big3(inverted: bool) -> Frames { let pattern = vec!["∙∙∙", "●∙∙", "●●∙", "●●●", "∙●●", "∙∙●"]; @@ -1467,9 +1471,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dots_simple_big4(false); + /// let spinner_frames: Frames = Frames::dots_simple_big4(false); /// ``` pub fn dots_simple_big4(inverted: bool) -> Frames { let pattern = vec!["∙∙∙", "●∙∙", "●●∙", "●●●"]; @@ -1481,9 +1485,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::fist_bump(false); + /// let spinner_frames: Frames = Frames::fist_bump(false); /// ``` pub fn fist_bump(inverted: bool) -> Frames { let pattern = vec![ @@ -1504,9 +1508,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::finger_dance(false); + /// let spinner_frames: Frames = Frames::finger_dance(false); /// ``` pub fn finger_dance(inverted: bool) -> Frames { let pattern = vec!["🤘 ", "🤟 ", "🖖 ", "✋ ", "🤚 ", "👆 "]; @@ -1518,9 +1522,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::mind_blown(false); + /// let spinner_frames: Frames = Frames::mind_blown(false); /// ``` pub fn mind_blown(inverted: bool) -> Frames { let pattern = vec![ @@ -1535,9 +1539,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::speaker(false); + /// let spinner_frames: Frames = Frames::speaker(false); /// ``` pub fn speaker(inverted: bool) -> Frames { let pattern = vec!["🔈 ", "🔉 ", "🔊 ", "🔉 "]; @@ -1549,9 +1553,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::arrows(false); + /// let spinner_frames: Frames = Frames::arrows(false); /// ``` pub fn arrows(inverted: bool) -> Frames { let pattern = vec!["⇢", "⇨", "⇒", "⇉", "⇶"]; @@ -1563,9 +1567,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_box(false); + /// let spinner_frames: Frames = Frames::dot_box(false); /// ``` pub fn dot_box(inverted: bool) -> Frames { let pattern = vec![".", "·", "•", "¤", "°", "¤", "•", "·"]; @@ -1577,9 +1581,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::simple_line_spin(false); + /// let spinner_frames: Frames = Frames::simple_line_spin(false); /// ``` pub fn simple_line_spin(inverted: bool) -> Frames { let pattern = vec!["+", "\\", "|", "!", "/", "-", "x"]; @@ -1591,9 +1595,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::bomb(false); + /// let spinner_frames: Frames = Frames::bomb(false); /// ``` pub fn bomb(inverted: bool) -> Frames { let pattern = vec![ @@ -1607,9 +1611,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dot_bounce2(false); + /// let spinner_frames: Frames = Frames::dot_bounce2(false); /// ``` pub fn dot_bounce2(inverted: bool) -> Frames { let pattern = vec![".", "·", "˙", "·", "."]; @@ -1621,9 +1625,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::orange_pulse(false); + /// let spinner_frames: Frames = Frames::orange_pulse(false); /// ``` pub fn orange_pulse(inverted: bool) -> Frames { let pattern = vec!["🔸", "🔶", "🟠", "🟠", "🔶"]; @@ -1635,9 +1639,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::blue_pulse(false); + /// let spinner_frames: Frames = Frames::blue_pulse(false); /// ``` pub fn blue_pulse(inverted: bool) -> Frames { let pattern = vec!["🔹", "🔷", "🔵", "🔵", "🔷"]; @@ -1649,9 +1653,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::green_pulse(false); + /// let spinner_frames: Frames = Frames::green_pulse(false); /// ``` pub fn green_pulse(inverted: bool) -> Frames { let pattern = vec!["🟢", "🟩", "🟩", "🟢"]; @@ -1663,9 +1667,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::red_pulse(false); + /// let spinner_frames: Frames = Frames::red_pulse(false); /// ``` pub fn red_pulse(inverted: bool) -> Frames { let pattern = vec!["🔴", "🟥", "🟥", "🔴"]; @@ -1677,9 +1681,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::other(false); + /// let spinner_frames: Frames = Frames::other(false); /// ``` pub fn other(inverted: bool) -> Frames { let pattern = vec!["d", "q", "p", "b"]; @@ -1691,9 +1695,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::pray(false); + /// let spinner_frames: Frames = Frames::pray(false); /// ``` pub fn pray(inverted: bool) -> Frames { let pattern = vec!["🧍 ", "🚶 ", "🧎 ", "🙇 "]; @@ -1705,9 +1709,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::wavy(false); + /// let spinner_frames: Frames = Frames::wavy(false); /// ``` pub fn wavy(inverted: bool) -> Frames { let pattern = vec![ @@ -1735,9 +1739,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::wavy2(false); + /// let spinner_frames: Frames = Frames::wavy2(false); /// ``` pub fn wavy2(inverted: bool) -> Frames { let pattern = vec![ @@ -1759,9 +1763,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::wavy3(false); + /// let spinner_frames: Frames = Frames::wavy3(false); /// ``` pub fn wavy3(inverted: bool) -> Frames { let pattern = vec![ @@ -1785,9 +1789,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::wavy4(false); + /// let spinner_frames: Frames = Frames::wavy4(false); /// ``` pub fn wavy4(inverted: bool) -> Frames { let pattern = vec![ @@ -1807,9 +1811,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::soccer(false); + /// let spinner_frames: Frames = Frames::soccer(false); /// ``` pub fn soccer(inverted: bool) -> Frames { let pattern = vec![ @@ -1834,9 +1838,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::layer(false); + /// let spinner_frames: Frames = Frames::layer(false); /// ``` pub fn layer(inverted: bool) -> Frames { let pattern = vec!["-", "=", "≡"]; @@ -1848,9 +1852,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::matrix_glitch(false); + /// let spinner_frames: Frames = Frames::matrix_glitch(false); /// ``` pub fn matrix_glitch(inverted: bool) -> Frames { let pattern = vec![ @@ -1873,9 +1877,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::matrix_glitch2(false); + /// let spinner_frames: Frames = Frames::matrix_glitch2(false); /// ``` pub fn matrix_glitch2(inverted: bool) -> Frames { let pattern = vec![ @@ -1898,9 +1902,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::Frames; /// - /// let spinner_frames: Frames = PreDefined::matrix_glitch2_small(false); + /// let spinner_frames: Frames = Frames::matrix_glitch2_small(false); /// ``` pub fn matrix_glitch2_small(inverted: bool) -> Frames { let pattern = vec![ @@ -1923,9 +1927,9 @@ impl PreDefined { /// /// # Example /// ``` - /// use zenity::animations::frames::spinner::{Frames, PreDefined}; + /// use zenity::spinner::{Frames}; /// - /// let spinner_frames: Frames = PreDefined::dwarf_fortress(false); + /// let spinner_frames: Frames = Frames::dwarf_fortress(false); /// ``` pub fn dwarf_fortress(inverted: bool) -> Frames { let pattern = vec![ @@ -2066,3 +2070,4 @@ impl PreDefined { Self::generate_frames(pattern, inverted, 100) } } + diff --git a/src/animations/spinner.rs b/src/spinner/mod.rs similarity index 68% rename from src/animations/spinner.rs rename to src/spinner/mod.rs index 0ef7a3c..ace96a4 100644 --- a/src/animations/spinner.rs +++ b/src/spinner/mod.rs @@ -5,20 +5,22 @@ use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; -use rand::Rng; +pub use frames::*; -use crate::helper::iterators; -use crate::spinner::Frames; +use crate::iterators; use crate::terminal::{console_cursor, console_render}; +pub mod frames; + /// spinner struct encapsulating the spinner animation -pub struct Spinner { +struct Spinner { frames: Arc>, text: Arc>, should_stop: Arc>, } /// struct holding multiple spinners +#[derive(Clone)] pub struct MultiSpinner { spinner: Arc>>, stop: Arc>, @@ -27,7 +29,10 @@ pub struct MultiSpinner { impl Default for MultiSpinner { fn default() -> Self { - Self::new() + let spinner = Self::new(Frames::dot_spinner11(false)); + spinner.run_all(); + + spinner } } @@ -36,15 +41,19 @@ impl MultiSpinner { /// /// ## Example /// ``` - /// # use zenity::multi_spinner::MultiSpinner; - /// let _spinner = MultiSpinner::new(); + /// # use zenity::spinner::{MultiSpinner, Frames}; + /// let _spinner = MultiSpinner::new(Frames::default()); /// ``` - pub fn new() -> Self { - MultiSpinner { + pub fn new(frames: Frames) -> Self { + let spinner = MultiSpinner { spinner: Arc::new(Mutex::new(HashMap::new())), stop: Arc::new(Mutex::new(false)), // index: 1_usize, - } + }; + + spinner.add(frames); + + spinner } /// create a new spinner @@ -55,17 +64,16 @@ impl MultiSpinner { /// /// ## Example /// ``` - /// use zenity::multi_spinner::MultiSpinner; - /// use zenity::spinner::PreDefined; + /// use zenity::spinner::MultiSpinner; + /// use zenity::spinner::Frames; /// - /// let spinner = MultiSpinner::new(); + /// let spinner = MultiSpinner::new(Frames::default()); /// - /// // the return values is an id you will need to edit the spinner later on - /// let spinner_num1 = spinner.new(PreDefined::dots_simple_big1(false)); + /// spinner.add(Frames::aesthetic_load(false)); /// ``` pub fn add(&self, frames: Frames) -> usize { - let mut rng = rand::thread_rng(); - let mut uid: usize; + let mut spinner_map = self.spinner.lock().unwrap(); + let uid = spinner_map.len() + 1; let new_spinner = Spinner { frames: Arc::new(Mutex::new(frames)), @@ -73,30 +81,46 @@ impl MultiSpinner { should_stop: Arc::new(Mutex::new(false)), }; - loop { - uid = rng.gen(); - if !self.spinner.lock().unwrap().contains_key(&uid) { - break; - } - } + spinner_map.insert(uid, new_spinner); - self.spinner.lock().unwrap().insert(uid, new_spinner); uid } + /// get the last create uid + /// + /// # Returns + /// + /// unique identifier of the last created spinner + /// + /// ## Example + /// ``` + /// use zenity::spinner::MultiSpinner; + /// use zenity::spinner::Frames; + /// + /// let spinner = MultiSpinner::new(Frames::default()); + /// + /// // the return values is an id you will need to edit the spinner later on + /// let spinner1_uid = spinner.get_last(); + /// ``` + pub fn get_last(&self) -> usize { + let spinner_map = self.spinner.lock().unwrap(); + + // get the maximum key value (uid) from the spinner map + spinner_map.keys().copied().max().unwrap() + } + /// set text of a specific spinner /// /// if the uid is invalid this does nothing /// /// ## Example /// ``` - /// use zenity::multi_spinner::MultiSpinner; - /// use zenity::spinner::PreDefined; + /// use zenity::spinner::MultiSpinner; + /// use zenity::spinner::Frames; /// - /// let spinner = MultiSpinner::new(); - /// let spinner_num1 = spinner.new(PreDefined::dots_simple_big1(false)); + /// let spinner = MultiSpinner::new(Frames::default()); /// - /// spinner.set_text(spinner_num1, "this is a text...".to_string()); + /// spinner.set_text(&spinner.get_last(), "this is a text...".to_string()); /// ``` pub fn set_text(&self, uid: &usize, new_text: String) { if let Some(spinner) = self.spinner.lock().unwrap().get(uid) { @@ -110,13 +134,12 @@ impl MultiSpinner { /// ## Example /// /// ``` - /// use zenity::multi_spinner::MultiSpinner; - /// use zenity::spinner::PreDefined; + /// use zenity::spinner::MultiSpinner; + /// use zenity::spinner::Frames; /// - /// let spinner = MultiSpinner::new(); - /// let spinner_num1 = spinner.new(PreDefined::dots_simple_big1(false)); + /// let spinner = MultiSpinner::new(Frames::default()); /// - /// spinner.stop(spinner_num1); + /// spinner.stop(&spinner.get_last()); /// ``` pub fn stop(&self, uid: &usize) { if let Some(spinner) = self.spinner.lock().unwrap().get(uid) { @@ -128,20 +151,20 @@ impl MultiSpinner { /// ## Example /// /// ``` - /// use zenity::multi_spinner::MultiSpinner; - /// use zenity::spinner::PreDefined; + /// use zenity::spinner::MultiSpinner; + /// use zenity::spinner::Frames; /// /// // make spinner mutable - /// let mut spinner = MultiSpinner::new(); + /// let mut spinner = MultiSpinner::new(Frames::dots_simple_big1(false)); /// /// // queu spinners for execution - /// let spinner_num1 = spinner.new(PreDefined::dots_simple_big1(false)); - /// let spinner_num2 = spinner.new(PreDefined::dots_simple_big1(false)); + /// let spinner_num1 = spinner.get_last(); + /// let spinner_num2 = spinner.add(Frames::dots_simple_big1(false)); /// /// //start the spinners /// spinner.run_all(); /// ``` - pub fn run_all(&mut self) { + pub fn run_all(&self) { let spinners = Arc::clone(&self.spinner); let stop = Arc::clone(&self.stop); @@ -170,7 +193,7 @@ impl MultiSpinner { index += 1; - thread::sleep(Duration::from_millis(100)); + thread::sleep(Duration::from_millis(80)); } }); } diff --git a/src/style.rs b/src/style.rs new file mode 100644 index 0000000..637509e --- /dev/null +++ b/src/style.rs @@ -0,0 +1,33 @@ +//! Collection of helper functions and classes related to colors + +pub use crossterm::style::*; + +/// combines multiple attributes into a single `style::Attributes` instance +/// +/// this function takes a slice of attribute references and combines them into a single +/// `style::Attributes` instance using bitwise OR (`|`) operation +/// +/// # Arguments +/// +/// * `attr_list` - a slice containing references to the attributes to be combined +/// +/// # Returns +/// +/// A `style::Attributes` instance representing the combined attributes +/// +/// # Example +/// +/// ``` +/// use zenity::style::{Attribute, combine_attributes}; +/// +/// let attributes = combine_attributes(&[ +/// &Attribute::Bold, +/// &Attribute::Underlined, +/// &Attribute::Italic, +/// ]); +/// ``` +pub fn combine_attributes(attr_list: &[&Attribute]) -> Attributes { + attr_list.iter().fold(Attributes::default(), |acc, &attr| { + acc | Attributes::from(*attr) + }) +} diff --git a/src/terminal.rs b/src/terminal.rs index 95e7520..dba98c4 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,6 +1,7 @@ pub(crate) mod console_render { use std::io::stdout; + use crate::style::ContentStyle; use crossterm::{cursor, execute, style, terminal}; // use crossterm::style::ContentStyle; @@ -9,16 +10,17 @@ pub(crate) mod console_render { execute!(stdout(), cursor::RestorePosition, style::Print(frame),).unwrap(); } - // pub fn render_styled_frame(frame: &String, style: ContentStyle) { - // execute!( - // stdout(), - // cursor::RestorePosition, - // style::SetStyle(style), // set animation color - // style::Print(frame), - // style::ResetColor, // reset colors - // ) - // .unwrap(); - // } + #[allow(dead_code)] + pub fn render_styled_frame(frame: &String, style: ContentStyle) { + execute!( + stdout(), + cursor::RestorePosition, + style::SetStyle(style), // set animation color + style::Print(frame), + style::ResetColor, // reset colors + ) + .unwrap(); + } pub fn cleanup() { execute!( @@ -41,6 +43,7 @@ pub(crate) mod console_cursor { pub fn save_hide_cursor() { execute!( stdout(), + cursor::MoveTo(0, 1), cursor::Hide, cursor::SavePosition, terminal::Clear(terminal::ClearType::FromCursorDown), @@ -52,4 +55,9 @@ pub(crate) mod console_cursor { pub fn reset_cursor() { execute!(stdout(), cursor::RestorePosition, cursor::Show).unwrap(); } + + /// resets the cursor to be shown and restores its saved position + pub fn next_line(num: u16) { + execute!(stdout(), cursor::MoveToNextLine(num)).unwrap(); + } }