diff options
Diffstat (limited to 'vendor/indicatif')
40 files changed, 0 insertions, 9566 deletions
diff --git a/vendor/indicatif/.cargo-checksum.json b/vendor/indicatif/.cargo-checksum.json deleted file mode 100644 index 9d239a9..0000000 --- a/vendor/indicatif/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.lock":"845bf05f1597386e99bd44e894b23e8e0d9d672b399c9c93a834d1d7f2b2f89a","Cargo.toml":"c2a073c9a96010063b677181a5acee2d65f1573d2286b537f0d11a7c74e00c94","LICENSE":"2022c11b24fc1e50fa06a5959e40198a3464f560729ad3d00139abb8a328362d","README.md":"5a49e063ebe6751f6e7eb10051a0e0a212ca7b067665dfd7905d8f9175ec2040","deny.toml":"22979f2da49546b27a5c892d5216bf74215987810a2d011b58870471883b9437","examples/cargo.rs":"486b024214f200432f8ea3c803bf8ee2fa03a289705cf490c501d390388b8ad7","examples/cargowrap.rs":"6341fc972a8ef36354d12a2a17eb3d0a2ff2a43e4c73410ce9570d9a139041c2","examples/download-continued.rs":"a4d78fe65f8b83e23edabe2b4d4da1cba0d88ae7c8eb73efec11dd33dab57524","examples/download-speed.rs":"694ad313c33a8ffe13f6db9b8b84c74a32ca2397b047fa38e488c74100753ea5","examples/download.rs":"ba7a8b6979a7c98aaee3770792956646b8d6570424e94695afee69a89d3d34d9","examples/fastbar.rs":"15fd733b7e058544005e68399d93550e7eb46c90a7c2248804887c5c521710c5","examples/finebars.rs":"c7a1a93bfcc2f8e7ec3d071e1e41575788b81506915894a8b7dcf9f573c58076","examples/iterator.rs":"9d3d965d81f1c7bed4247205e4f8978cdce870de8c8b0ed93097a403351360ba","examples/log.rs":"fd88f4d8a56726c1e3f91e2a3b7b68262dd6a48c7f30f4af5184a6efe177736c","examples/long-spinner.rs":"f753a118d0e553a0fd74bc875dc691804db32fbdad8119d53ea5e304f39cfaad","examples/message.rs":"9b6c19bb19bebce185ab23a54bc90e74ced6ea09d5aac7cc082e4fc55b5126d4","examples/morebars.rs":"a073505554dc477b509f351bb82c703d70ac256407ce32cd41a734da5604d6f9","examples/multi-tree-ext.rs":"1fdd8a9d649bfa43d8843ef975db919240108c23df027ffc2213cfc4815379df","examples/multi-tree.rs":"a42879ef63db7860aa0306147f117749efa8c9de0435040a54cb785225d23ab0","examples/multi.rs":"d90f657883eaf3b78aea0def07aa49154414e614ef96bb8df3d13154ffe76ab7","examples/single.rs":"576c342c93b5493cd78257d0eecc8abd24b2bd4a3ad3d674d1023f2a3cad833d","examples/slow.rs":"f0152c6c35bbdfcbad44153b63c895bcd1e6929cb98ee49a67fefd942e2a2631","examples/spinner-loop.rs":"492f10d3ee0781b8c78e36a12ed62c833996f69eb7aec61366a35fd28c1bf87a","examples/steady.rs":"981338f2fbf3ec3967fabde198ab973c8dc8926e6cae1a8acf53494cb47e9c89","examples/tokio.rs":"ef637f87461db3cd14de36498ad05ec3bf30f77cc67ea9315766ccbe84a96884","examples/yarnish.rs":"1931843d12d90eb1f9b63f274df39b35ed2b8eeb28f4597b98afbb709d95f6bd","src/draw_target.rs":"26dd5a33d156541d2261f37d53f3f618787541d22e078b3be5fe47353dccc421","src/format.rs":"991deb3a33eb529bede01144577a530a8330e5c7d7953e90257b28a4906bd9b2","src/in_memory.rs":"fa920e7ed034ea2af4c1adc36558384e609e34702765885de697c4db36ff943c","src/iter.rs":"a41128537c11fe0200f6d1444ddeb75694ae0298bb64081dec8c2567813606aa","src/lib.rs":"adc99e8fa6a7bbafa16209f30e6bb5da85b100368bb6ef2a238c278147f24f92","src/multi.rs":"b8f90c9f7224076657f070c43b788df81b6e041f53a21967747270c898cdba77","src/progress_bar.rs":"6c9be96df20d603f2351c29774300f389919eb77323459904dbdf6bbe03f91c5","src/rayon.rs":"4663403f972eb3fa2ee4dbff026fab784f1346298cccb35f31e3fe01d185cbb6","src/state.rs":"de8df1272f28ea6333a23c8bf687bf22d92fb1726d6e2815fc70cef62b5d2b32","src/style.rs":"019a4f953cbf0e50e0385a6936d334342160c95d031375e11f5353c91922de90","src/term_like.rs":"4605e937c63c5da9e0ab0afd49fd0466c21fdf76e99973139cec985ced25ed5d","tests/multi-autodrop.rs":"c453259d8b84e48b504b27ad0c729aa09a90acc9bfe35814f8216efbc3a98b1c","tests/render.rs":"ae56b948b9aa69d57afb6789ee26393932f4735f870c36e54f89f79d7554c96a"},"package":"fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"}
\ No newline at end of file diff --git a/vendor/indicatif/Cargo.lock b/vendor/indicatif/Cargo.lock deleted file mode 100644 index 33cbf79..0000000 --- a/vendor/indicatif/Cargo.lock +++ /dev/null @@ -1,872 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "anstyle-wincon" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" -dependencies = [ - "anstyle", - "windows-sys 0.48.0", -] - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "4.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" -dependencies = [ - "clap_builder", - "clap_derive", - "once_cell", -] - -[[package]] -name = "clap_builder" -version = "4.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "console" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.45.0", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "errno" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "futures" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "indicatif" -version = "0.17.7" -dependencies = [ - "clap", - "console", - "futures", - "futures-core", - "instant", - "number_prefix", - "once_cell", - "portable-atomic", - "pretty_assertions", - "rand", - "rayon", - "tokio", - "unicode-segmentation", - "unicode-width", - "vt100", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - -[[package]] -name = "log" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] -name = "object" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "pin-project-lite" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "portable-atomic" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "pretty_assertions" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" -dependencies = [ - "diff", - "yansi", -] - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustix" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "2.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tokio" -version = "1.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" -dependencies = [ - "autocfg", - "backtrace", - "bytes", - "pin-project-lite", -] - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "vt100" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84cd863bf0db7e392ba3bd04994be3473491b31e66340672af5d11943c6274de" -dependencies = [ - "itoa", - "log", - "unicode-width", - "vte", -] - -[[package]] -name = "vte" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" -dependencies = [ - "arrayvec", - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.1", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/vendor/indicatif/Cargo.toml b/vendor/indicatif/Cargo.toml deleted file mode 100644 index 5d5c266..0000000 --- a/vendor/indicatif/Cargo.toml +++ /dev/null @@ -1,117 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -rust-version = "1.63" -name = "indicatif" -version = "0.17.7" -exclude = ["screenshots/*"] -description = "A progress bar and cli reporting library for Rust" -documentation = "https://docs.rs/indicatif" -readme = "README.md" -keywords = [ - "cli", - "progress", - "pb", - "colors", - "progressbar", -] -categories = ["command-line-interface"] -license = "MIT" -repository = "https://github.com/console-rs/indicatif" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", -] - -[dependencies.console] -version = "0.15" -features = ["ansi-parsing"] -default-features = false - -[dependencies.futures-core] -version = "0.3" -optional = true -default-features = false - -[dependencies.number_prefix] -version = "0.4" - -[dependencies.portable-atomic] -version = "1.0.0" - -[dependencies.rayon] -version = "1.1" -optional = true - -[dependencies.tokio] -version = "1" -features = ["io-util"] -optional = true - -[dependencies.unicode-segmentation] -version = "1" -optional = true - -[dependencies.unicode-width] -version = "0.1" -optional = true - -[dependencies.vt100] -version = "0.15.1" -optional = true - -[dev-dependencies.clap] -version = "4" -features = [ - "color", - "derive", -] - -[dev-dependencies.futures] -version = "0.3" - -[dev-dependencies.once_cell] -version = "1" - -[dev-dependencies.pretty_assertions] -version = "1.4.0" - -[dev-dependencies.rand] -version = "0.8" - -[dev-dependencies.tokio] -version = "1" -features = [ - "fs", - "time", - "rt", -] - -[features] -default = [ - "unicode-width", - "console/unicode-width", -] -futures = ["dep:futures-core"] -improved_unicode = [ - "unicode-segmentation", - "unicode-width", - "console/unicode-width", -] -in_memory = ["vt100"] - -[target."cfg(target_arch = \"wasm32\")".dependencies.instant] -version = "0.1" diff --git a/vendor/indicatif/LICENSE b/vendor/indicatif/LICENSE deleted file mode 100644 index dc9a85c..0000000 --- a/vendor/indicatif/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Armin Ronacher <armin.ronacher@active-4.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/vendor/indicatif/README.md b/vendor/indicatif/README.md deleted file mode 100644 index 3fde30b..0000000 --- a/vendor/indicatif/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# indicatif - -[![Documentation](https://docs.rs/indicatif/badge.svg)](https://docs.rs/indicatif/) -[![Crates.io](https://img.shields.io/crates/v/indicatif.svg)](https://crates.io/crates/indicatif) -[![Build status](https://github.com/console-rs/indicatif/workflows/CI/badge.svg)](https://github.com/console-rs/indicatif/actions/workflows/rust.yml) -[![Chat](https://img.shields.io/discord/976380008299917365?logo=discord)](https://discord.gg/YHmNA3De4W) - -A Rust library for indicating progress in command line applications to users. - -This currently primarily provides progress bars and spinners as well as basic -color support, but there are bigger plans for the future of this! - -## Examples - -[examples/yarnish.rs](examples/yarnish.rs) -<img src="https://github.com/console-rs/indicatif/blob/main/screenshots/yarn.gif?raw=true"> - -[examples/download.rs](examples/download.rs) -<img src="https://github.com/console-rs/indicatif/blob/main/screenshots/download.gif?raw=true"> - -[examples/multi.rs](examples/multi.rs) -<img src="https://github.com/console-rs/indicatif/blob/main/screenshots/multi-progress.gif?raw=true"> - -[examples/single.rs](examples/single.rs) -<img src="https://github.com/console-rs/indicatif/blob/main/screenshots/single.gif?raw=true"> - -## Integrations - -You can use [indicatif-log-bridge](https://crates.io/crates/indicatif-log-bridge) to integrate with the -[log crate](https://crates.io/crates/log) and avoid having both fight for your terminal. diff --git a/vendor/indicatif/deny.toml b/vendor/indicatif/deny.toml deleted file mode 100644 index 38c47a8..0000000 --- a/vendor/indicatif/deny.toml +++ /dev/null @@ -1,3 +0,0 @@ -[licenses] -allow-osi-fsf-free = "either" -copyleft = "deny" diff --git a/vendor/indicatif/examples/cargo.rs b/vendor/indicatif/examples/cargo.rs deleted file mode 100644 index 1e2ff2e..0000000 --- a/vendor/indicatif/examples/cargo.rs +++ /dev/null @@ -1,122 +0,0 @@ -use std::sync::{mpsc, Arc, Mutex}; -use std::thread; -use std::time::{Duration, Instant}; - -use console::{Style, Term}; -use indicatif::{HumanDuration, ProgressBar, ProgressStyle}; -use rand::Rng; - -static CRATES: &[(&str, &str)] = &[ - ("console", "v0.14.1"), - ("lazy_static", "v1.4.0"), - ("libc", "v0.2.93"), - ("regex", "v1.4.6"), - ("regex-syntax", "v0.6.23"), - ("terminal_size", "v0.1.16"), - ("libc", "v0.2.93"), - ("unicode-width", "v0.1.8"), - ("lazy_static", "v1.4.0"), - ("number_prefix", "v0.4.0"), - ("regex", "v1.4.6"), - ("rand", "v0.8.3"), - ("getrandom", "v0.2.2"), - ("cfg-if", "v1.0.0"), - ("libc", "v0.2.93"), - ("rand_chacha", "v0.3.0"), - ("ppv-lite86", "v0.2.10"), - ("rand_core", "v0.6.2"), - ("getrandom", "v0.2.2"), - ("rand_core", "v0.6.2"), - ("tokio", "v1.5.0"), - ("bytes", "v1.0.1"), - ("pin-project-lite", "v0.2.6"), - ("slab", "v0.4.3"), - ("indicatif", "v0.15.0"), -]; - -fn main() { - // number of cpus - const NUM_CPUS: usize = 4; - let start = Instant::now(); - - // mimic cargo progress bar although it behaves a bit different - let pb = ProgressBar::new(CRATES.len() as u64); - pb.set_style( - ProgressStyle::with_template( - // note that bar size is fixed unlike cargo which is dynamic - // and also the truncation in cargo uses trailers (`...`) - if Term::stdout().size().1 > 80 { - "{prefix:>12.cyan.bold} [{bar:57}] {pos}/{len} {wide_msg}" - } else { - "{prefix:>12.cyan.bold} [{bar:57}] {pos}/{len}" - }, - ) - .unwrap() - .progress_chars("=> "), - ); - pb.set_prefix("Building"); - - // process in another thread - // crates to be iterated but not exactly a tree - let crates = Arc::new(Mutex::new(CRATES.iter())); - let (tx, rx) = mpsc::channel(); - for n in 0..NUM_CPUS { - let tx = tx.clone(); - let crates = crates.clone(); - thread::spawn(move || { - let mut rng = rand::thread_rng(); - loop { - let krate = crates.lock().unwrap().next(); - // notify main thread if n thread is processing a crate - tx.send((n, krate)).unwrap(); - if let Some(krate) = krate { - thread::sleep(Duration::from_millis( - // last compile and linking is always slow, let's mimic that - if CRATES.last() == Some(krate) { - rng.gen_range(1_000..2_000) - } else { - rng.gen_range(250..1_000) - }, - )); - } else { - break; - } - } - }); - } - // drop tx to stop waiting - drop(tx); - - let green_bold = Style::new().green().bold(); - - // do progress drawing in main thread - let mut processing = [None; NUM_CPUS]; - while let Ok((n, krate)) = rx.recv() { - processing[n] = krate; - let crates: Vec<&str> = processing - .iter() - .filter_map(|t| t.copied().map(|(name, _)| name)) - .collect(); - pb.set_message(crates.join(", ")); - if let Some((name, version)) = krate { - // crate is being built - let line = format!( - "{:>12} {} {}", - green_bold.apply_to("Compiling"), - name, - version - ); - pb.println(line); - - pb.inc(1); - } - } - pb.finish_and_clear(); - - // compilation is finished - println!( - "{:>12} dev [unoptimized + debuginfo] target(s) in {}", - green_bold.apply_to("Finished"), - HumanDuration(start.elapsed()) - ); -} diff --git a/vendor/indicatif/examples/cargowrap.rs b/vendor/indicatif/examples/cargowrap.rs deleted file mode 100644 index 354b6e0..0000000 --- a/vendor/indicatif/examples/cargowrap.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::io::{BufRead, BufReader}; -use std::process; -use std::time::{Duration, Instant}; - -use indicatif::{HumanDuration, ProgressBar, ProgressStyle}; - -pub fn main() { - let started = Instant::now(); - - println!("Compiling package in release mode..."); - - let pb = ProgressBar::new_spinner(); - pb.enable_steady_tick(Duration::from_millis(200)); - pb.set_style( - ProgressStyle::with_template("{spinner:.dim.bold} cargo: {wide_msg}") - .unwrap() - .tick_chars("/|\\- "), - ); - - let mut p = process::Command::new("cargo") - .arg("build") - .arg("--release") - .stderr(process::Stdio::piped()) - .spawn() - .unwrap(); - - for line in BufReader::new(p.stderr.take().unwrap()).lines() { - let line = line.unwrap(); - let stripped_line = line.trim(); - if !stripped_line.is_empty() { - pb.set_message(stripped_line.to_owned()); - } - pb.tick(); - } - - p.wait().unwrap(); - - pb.finish_and_clear(); - - println!("Done in {}", HumanDuration(started.elapsed())); -} diff --git a/vendor/indicatif/examples/download-continued.rs b/vendor/indicatif/examples/download-continued.rs deleted file mode 100644 index c9a76b6..0000000 --- a/vendor/indicatif/examples/download-continued.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::cmp::min; -use std::thread; -use std::time::Duration; - -use indicatif::{ProgressBar, ProgressStyle}; - -fn main() { - let mut downloaded = 69369369; - let total_size = 231231231; - - let pb = ProgressBar::new(total_size); - pb.set_style( - ProgressStyle::with_template( - "{spinner:.green} [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})", - ) - .unwrap() - .progress_chars("#>-"), - ); - pb.set_position(downloaded); - pb.reset_eta(); - - while downloaded < total_size { - downloaded = min(downloaded + 123211, total_size); - pb.set_position(downloaded); - thread::sleep(Duration::from_millis(12)); - } - - pb.finish_with_message("downloaded"); -} diff --git a/vendor/indicatif/examples/download-speed.rs b/vendor/indicatif/examples/download-speed.rs deleted file mode 100644 index da5a80f..0000000 --- a/vendor/indicatif/examples/download-speed.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::cmp::min; -use std::thread; -use std::time::Duration; - -use indicatif::{ProgressBar, ProgressStyle}; - -fn main() { - let mut downloaded = 0; - let total_size = 231231231; - - let pb = ProgressBar::new(total_size); - pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})") - .unwrap() - .progress_chars("#>-")); - - while downloaded < total_size { - let new = min(downloaded + 223211, total_size); - downloaded = new; - pb.set_position(new); - thread::sleep(Duration::from_millis(12)); - } - - pb.finish_with_message("downloaded"); -} diff --git a/vendor/indicatif/examples/download.rs b/vendor/indicatif/examples/download.rs deleted file mode 100644 index c3f9202..0000000 --- a/vendor/indicatif/examples/download.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::thread; -use std::time::Duration; -use std::{cmp::min, fmt::Write}; - -use indicatif::{ProgressBar, ProgressState, ProgressStyle}; - -fn main() { - let mut downloaded = 0; - let total_size = 231231231; - - let pb = ProgressBar::new(total_size); - pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})") - .unwrap() - .with_key("eta", |state: &ProgressState, w: &mut dyn Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap()) - .progress_chars("#>-")); - - while downloaded < total_size { - let new = min(downloaded + 223211, total_size); - downloaded = new; - pb.set_position(new); - thread::sleep(Duration::from_millis(12)); - } - - pb.finish_with_message("downloaded"); -} diff --git a/vendor/indicatif/examples/fastbar.rs b/vendor/indicatif/examples/fastbar.rs deleted file mode 100644 index 1b71f0c..0000000 --- a/vendor/indicatif/examples/fastbar.rs +++ /dev/null @@ -1,23 +0,0 @@ -use indicatif::ProgressBar; - -fn many_units_of_easy_work(n: u64, label: &str) { - let pb = ProgressBar::new(n); - - let mut sum = 0; - for i in 0..n { - // Any quick computation, followed by an update to the progress bar. - sum += 2 * i + 3; - pb.inc(1); - } - pb.finish(); - - println!("[{}] Sum ({}) calculated in {:?}", label, sum, pb.elapsed()); -} - -fn main() { - const N: u64 = 1 << 20; - - // Perform a long sequence of many simple computations monitored by a - // default progress bar. - many_units_of_easy_work(N, "Default progress bar "); -} diff --git a/vendor/indicatif/examples/finebars.rs b/vendor/indicatif/examples/finebars.rs deleted file mode 100644 index dffb967..0000000 --- a/vendor/indicatif/examples/finebars.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; -use rand::{thread_rng, Rng}; - -fn main() { - let styles = [ - ("Rough bar:", "β ", "red"), - ("Fine bar: ", "ββββββββ ", "yellow"), - ("Vertical: ", "ββββ
ββββ ", "green"), - ("Fade in: ", "ββββ ", "blue"), - ("Blocky: ", "ββββ ", "magenta"), - ]; - - let m = MultiProgress::new(); - - let handles: Vec<_> = styles - .iter() - .map(|s| { - let pb = m.add(ProgressBar::new(512)); - pb.set_style( - ProgressStyle::with_template(&format!("{{prefix:.bold}}β{{bar:.{}}}β{{msg}}", s.2)) - .unwrap() - .progress_chars(s.1), - ); - pb.set_prefix(s.0); - let wait = Duration::from_millis(thread_rng().gen_range(10..30)); - thread::spawn(move || { - for i in 0..512 { - thread::sleep(wait); - pb.inc(1); - pb.set_message(format!("{:3}%", 100 * i / 512)); - } - pb.finish_with_message("100%"); - }) - }) - .collect(); - - for h in handles { - let _ = h.join(); - } -} diff --git a/vendor/indicatif/examples/iterator.rs b/vendor/indicatif/examples/iterator.rs deleted file mode 100644 index 8f40047..0000000 --- a/vendor/indicatif/examples/iterator.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::{ProgressBar, ProgressIterator, ProgressStyle}; - -fn main() { - // Default styling, attempt to use Iterator::size_hint to count input size - for _ in (0..1000).progress() { - // ... - thread::sleep(Duration::from_millis(5)); - } - - // Provide explicit number of elements in iterator - for _ in (0..1000).progress_count(1000) { - // ... - thread::sleep(Duration::from_millis(5)); - } - - // Provide a custom bar style - let pb = ProgressBar::new(1000); - pb.set_style( - ProgressStyle::with_template( - "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] ({pos}/{len}, ETA {eta})", - ) - .unwrap(), - ); - for _ in (0..1000).progress_with(pb) { - // ... - thread::sleep(Duration::from_millis(5)); - } -} diff --git a/vendor/indicatif/examples/log.rs b/vendor/indicatif/examples/log.rs deleted file mode 100644 index 26d506c..0000000 --- a/vendor/indicatif/examples/log.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::ProgressBar; - -fn main() { - let pb = ProgressBar::new(100); - for i in 0..100 { - thread::sleep(Duration::from_millis(25)); - pb.println(format!("[+] finished #{i}")); - pb.inc(1); - } - pb.finish_with_message("done"); -} diff --git a/vendor/indicatif/examples/long-spinner.rs b/vendor/indicatif/examples/long-spinner.rs deleted file mode 100644 index 6b14548..0000000 --- a/vendor/indicatif/examples/long-spinner.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::{ProgressBar, ProgressStyle}; - -fn main() { - let pb = ProgressBar::new_spinner(); - pb.enable_steady_tick(Duration::from_millis(120)); - pb.set_style( - ProgressStyle::with_template("{spinner:.blue} {msg}") - .unwrap() - // For more spinners check out the cli-spinners project: - // https://github.com/sindresorhus/cli-spinners/blob/master/spinners.json - .tick_strings(&[ - "βΉβΉβΉβΉβΉ", - "βΈβΉβΉβΉβΉ", - "βΉβΈβΉβΉβΉ", - "βΉβΉβΈβΉβΉ", - "βΉβΉβΉβΈβΉ", - "βΉβΉβΉβΉβΈ", - "βͺβͺβͺβͺβͺ", - ]), - ); - pb.set_message("Calculating..."); - thread::sleep(Duration::from_secs(5)); - pb.finish_with_message("Done"); -} diff --git a/vendor/indicatif/examples/message.rs b/vendor/indicatif/examples/message.rs deleted file mode 100644 index d15781a..0000000 --- a/vendor/indicatif/examples/message.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::{thread, time::Duration}; - -use indicatif::ProgressBar; - -fn main() { - let pb = ProgressBar::new(100).with_message("Frobbing the widget"); - for _ in 0..100 { - thread::sleep(Duration::from_millis(30)); - pb.inc(1); - } -} diff --git a/vendor/indicatif/examples/morebars.rs b/vendor/indicatif/examples/morebars.rs deleted file mode 100644 index 30b664f..0000000 --- a/vendor/indicatif/examples/morebars.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; - -fn main() { - let m = Arc::new(MultiProgress::new()); - let sty = ProgressStyle::with_template("{bar:40.green/yellow} {pos:>7}/{len:7}").unwrap(); - - let pb = m.add(ProgressBar::new(5)); - pb.set_style(sty.clone()); - - // make sure we show up at all. otherwise no rendering - // event. - pb.tick(); - for _ in 0..5 { - let pb2 = m.add(ProgressBar::new(128)); - pb2.set_style(sty.clone()); - for _ in 0..128 { - thread::sleep(Duration::from_millis(5)); - pb2.inc(1); - } - pb2.finish(); - pb.inc(1); - } - pb.finish_with_message("done"); -} diff --git a/vendor/indicatif/examples/multi-tree-ext.rs b/vendor/indicatif/examples/multi-tree-ext.rs deleted file mode 100644 index 0651548..0000000 --- a/vendor/indicatif/examples/multi-tree-ext.rs +++ /dev/null @@ -1,280 +0,0 @@ -use clap::Parser; -use std::fmt::Debug; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use console::style; -use indicatif::{MultiProgress, MultiProgressAlignment, ProgressBar, ProgressStyle}; -use once_cell::sync::Lazy; -use rand::rngs::ThreadRng; -use rand::{Rng, RngCore}; - -#[derive(Debug, Clone)] -enum Action { - ModifyTree(usize), - IncProgressBar(usize), - Stop, -} - -#[derive(Clone, Debug)] -enum Elem { - AddItem(Item), - RemoveItem(Index), -} - -#[derive(Clone, Debug)] -struct Item { - key: String, - index: usize, - indent: usize, - progress_bar: ProgressBar, -} - -#[derive(Clone, Debug)] -struct Index(usize); - -const PB_LEN: u64 = 32; -static ELEM_IDX: AtomicUsize = AtomicUsize::new(0); - -static ELEMENTS: Lazy<[Elem; 27]> = Lazy::new(|| { - [ - Elem::AddItem(Item { - indent: 9, - index: 0, - progress_bar: ProgressBar::new(PB_LEN), - key: "dog".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 0, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_1".to_string(), - }), - Elem::AddItem(Item { - indent: 8, - index: 1, - progress_bar: ProgressBar::new(PB_LEN), - key: "lazy".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 1, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_2".to_string(), - }), - Elem::AddItem(Item { - indent: 1, - index: 0, - progress_bar: ProgressBar::new(PB_LEN), - key: "the".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 0, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_3".to_string(), - }), - Elem::AddItem(Item { - indent: 7, - index: 3, - progress_bar: ProgressBar::new(PB_LEN), - key: "a".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 3, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_4".to_string(), - }), - Elem::AddItem(Item { - indent: 6, - index: 2, - progress_bar: ProgressBar::new(PB_LEN), - key: "over".to_string(), - }), - Elem::RemoveItem(Index(6)), - Elem::RemoveItem(Index(4)), - Elem::RemoveItem(Index(3)), - Elem::RemoveItem(Index(0)), - Elem::AddItem(Item { - indent: 0, - index: 2, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_5".to_string(), - }), - Elem::AddItem(Item { - indent: 4, - index: 1, - progress_bar: ProgressBar::new(PB_LEN), - key: "fox".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 1, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_6".to_string(), - }), - Elem::AddItem(Item { - indent: 2, - index: 1, - progress_bar: ProgressBar::new(PB_LEN), - key: "quick".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 1, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_7".to_string(), - }), - Elem::AddItem(Item { - indent: 5, - index: 5, - progress_bar: ProgressBar::new(PB_LEN), - key: "jumps".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 5, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_8".to_string(), - }), - Elem::AddItem(Item { - indent: 3, - index: 4, - progress_bar: ProgressBar::new(PB_LEN), - key: "brown".to_string(), - }), - Elem::AddItem(Item { - indent: 0, - index: 3, - progress_bar: ProgressBar::new(PB_LEN), - key: "temp_9".to_string(), - }), - Elem::RemoveItem(Index(10)), - Elem::RemoveItem(Index(7)), - Elem::RemoveItem(Index(4)), - Elem::RemoveItem(Index(3)), - Elem::RemoveItem(Index(1)), - ] -}); - -#[derive(Debug, Parser)] -pub struct Config { - #[clap(long)] - bottom_alignment: bool, -} - -/// The example demonstrates the usage of `MultiProgress` and further extends `multi-tree` example. -/// Now the example has 3 different actions implemented, and the item tree can be modified -/// by inserting or removing progress bars. The progress bars to be removed eventually -/// have messages with pattern `"temp_*"`. -/// -/// Also the command option `--bottom-alignment` is used to control the vertical alignment of the -/// `MultiProgress`. To enable this run it with -/// ```ignore -/// cargo run --example multi-tree-ext -- --bottom-alignment -/// ``` -pub fn main() { - let conf: Config = Config::parse(); - let mp = Arc::new(MultiProgress::new()); - let alignment = if conf.bottom_alignment { - MultiProgressAlignment::Bottom - } else { - MultiProgressAlignment::Top - }; - mp.set_alignment(alignment); - let sty_main = ProgressStyle::with_template("{bar:40.green/yellow} {pos:>4}/{len:4}").unwrap(); - let sty_aux = - ProgressStyle::with_template("[{pos:>2}/{len:2}] {prefix}{spinner:.green} {msg}").unwrap(); - let sty_fin = ProgressStyle::with_template("[{pos:>2}/{len:2}] {prefix}{msg}").unwrap(); - - let pb_main = mp.add(ProgressBar::new( - ELEMENTS - .iter() - .map(|e| match e { - Elem::AddItem(item) => item.progress_bar.length().unwrap(), - Elem::RemoveItem(_) => 1, - }) - .sum(), - )); - - pb_main.set_style(sty_main); - for e in ELEMENTS.iter() { - match e { - Elem::AddItem(item) => item.progress_bar.set_style(sty_aux.clone()), - Elem::RemoveItem(_) => {} - } - } - - let mut items: Vec<&Item> = Vec::with_capacity(ELEMENTS.len()); - - let mp2 = Arc::clone(&mp); - let mut rng = ThreadRng::default(); - pb_main.tick(); - loop { - match get_action(&mut rng, &items) { - Action::Stop => { - // all elements were exhausted - pb_main.finish(); - return; - } - Action::ModifyTree(elem_idx) => match &ELEMENTS[elem_idx] { - Elem::AddItem(item) => { - let pb = mp2.insert(item.index, item.progress_bar.clone()); - pb.set_prefix(" ".repeat(item.indent)); - pb.set_message(&item.key); - items.insert(item.index, item); - } - Elem::RemoveItem(Index(index)) => { - let item = items.remove(*index); - let pb = &item.progress_bar; - mp2.remove(pb); - pb_main.inc(pb.length().unwrap() - pb.position()); - } - }, - Action::IncProgressBar(item_idx) => { - let item = &items[item_idx]; - item.progress_bar.inc(1); - let pos = item.progress_bar.position(); - if pos >= item.progress_bar.length().unwrap() { - item.progress_bar.set_style(sty_fin.clone()); - item.progress_bar.finish_with_message(format!( - "{} {}", - style("β").green(), - item.key - )); - } - pb_main.inc(1); - } - } - thread::sleep(Duration::from_millis(20)); - } -} - -/// The function guarantees to return the action, that is valid for the current tree. -fn get_action(rng: &mut dyn RngCore, items: &[&Item]) -> Action { - let elem_idx = ELEM_IDX.load(Ordering::SeqCst); - // the indices of those items, that not completed yet - let uncompleted = items - .iter() - .enumerate() - .filter(|(_, item)| { - let pos = item.progress_bar.position(); - pos < item.progress_bar.length().unwrap() - }) - .map(|(idx, _)| idx) - .collect::<Vec<usize>>(); - let k = rng.gen_range(0..16); - if (k > 0 || k == 0 && elem_idx == ELEMENTS.len()) && !uncompleted.is_empty() { - let idx = rng.gen_range(0..uncompleted.len() as u64) as usize; - Action::IncProgressBar(uncompleted[idx]) - } else if elem_idx < ELEMENTS.len() { - ELEM_IDX.fetch_add(1, Ordering::SeqCst); - Action::ModifyTree(elem_idx) - } else { - // nothing to do more - Action::Stop - } -} diff --git a/vendor/indicatif/examples/multi-tree.rs b/vendor/indicatif/examples/multi-tree.rs deleted file mode 100644 index 3435424..0000000 --- a/vendor/indicatif/examples/multi-tree.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::fmt::Debug; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; - -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; -use once_cell::sync::Lazy; -use rand::rngs::ThreadRng; -use rand::{Rng, RngCore}; - -#[derive(Debug, Clone)] -enum Action { - AddProgressBar(usize), - IncProgressBar(usize), -} - -#[derive(Clone, Debug)] -struct Elem { - key: String, - index: usize, - indent: usize, - progress_bar: ProgressBar, -} - -static ELEMENTS: Lazy<[Elem; 9]> = Lazy::new(|| { - [ - Elem { - indent: 1, - index: 0, - progress_bar: ProgressBar::new(32), - key: "jumps".to_string(), - }, - Elem { - indent: 2, - index: 1, - progress_bar: ProgressBar::new(32), - key: "lazy".to_string(), - }, - Elem { - indent: 0, - index: 0, - progress_bar: ProgressBar::new(32), - key: "the".to_string(), - }, - Elem { - indent: 3, - index: 3, - progress_bar: ProgressBar::new(32), - key: "dog".to_string(), - }, - Elem { - indent: 2, - index: 2, - progress_bar: ProgressBar::new(32), - key: "over".to_string(), - }, - Elem { - indent: 2, - index: 1, - progress_bar: ProgressBar::new(32), - key: "brown".to_string(), - }, - Elem { - indent: 1, - index: 1, - progress_bar: ProgressBar::new(32), - key: "quick".to_string(), - }, - Elem { - indent: 3, - index: 5, - progress_bar: ProgressBar::new(32), - key: "a".to_string(), - }, - Elem { - indent: 3, - index: 3, - progress_bar: ProgressBar::new(32), - key: "fox".to_string(), - }, - ] -}); - -/// The example implements the tree-like collection of progress bars, where elements are -/// added on the fly and progress bars get incremented until all elements is added and -/// all progress bars finished. -/// On each iteration `get_action` function returns some action, and when the tree gets -/// complete, the function returns `None`, which finishes the loop. -fn main() { - let mp = Arc::new(MultiProgress::new()); - let sty_main = ProgressStyle::with_template("{bar:40.green/yellow} {pos:>4}/{len:4}").unwrap(); - let sty_aux = ProgressStyle::with_template("{spinner:.green} {msg} {pos:>4}/{len:4}").unwrap(); - - let pb_main = mp.add(ProgressBar::new( - ELEMENTS - .iter() - .map(|e| e.progress_bar.length().unwrap()) - .sum(), - )); - pb_main.set_style(sty_main); - for elem in ELEMENTS.iter() { - elem.progress_bar.set_style(sty_aux.clone()); - } - - let tree: Arc<Mutex<Vec<&Elem>>> = Arc::new(Mutex::new(Vec::with_capacity(ELEMENTS.len()))); - let tree2 = Arc::clone(&tree); - - let mp2 = Arc::clone(&mp); - let _ = thread::spawn(move || { - let mut rng = ThreadRng::default(); - pb_main.tick(); - loop { - thread::sleep(Duration::from_millis(15)); - match get_action(&mut rng, &tree) { - None => { - // all elements were exhausted - pb_main.finish(); - return; - } - Some(Action::AddProgressBar(el_idx)) => { - let elem = &ELEMENTS[el_idx]; - let pb = mp2.insert(elem.index + 1, elem.progress_bar.clone()); - pb.set_message(format!("{} {}", " ".repeat(elem.indent), elem.key)); - tree.lock().unwrap().insert(elem.index, elem); - } - Some(Action::IncProgressBar(el_idx)) => { - let elem = &tree.lock().unwrap()[el_idx]; - elem.progress_bar.inc(1); - let pos = elem.progress_bar.position(); - if pos >= elem.progress_bar.length().unwrap() { - elem.progress_bar.finish_with_message(format!( - "{}{} {}", - " ".repeat(elem.indent), - "β", - elem.key - )); - } - pb_main.inc(1); - } - } - } - }) - .join(); - - println!("==============================="); - println!("the tree should be the same as:"); - for elem in tree2.lock().unwrap().iter() { - println!("{} {}", " ".repeat(elem.indent), elem.key); - } -} - -/// The function guarantees to return the action, that is valid for the current tree. -fn get_action(rng: &mut dyn RngCore, tree: &Mutex<Vec<&Elem>>) -> Option<Action> { - let elem_len = ELEMENTS.len() as u64; - let list_len = tree.lock().unwrap().len() as u64; - let sum_free = tree - .lock() - .unwrap() - .iter() - .map(|e| { - let pos = e.progress_bar.position(); - let len = e.progress_bar.length().unwrap(); - len - pos - }) - .sum::<u64>(); - - if sum_free == 0 && list_len == elem_len { - // nothing to do more - None - } else if sum_free == 0 && list_len < elem_len { - // there is no place to make an increment - Some(Action::AddProgressBar(tree.lock().unwrap().len())) - } else { - loop { - let list = tree.lock().unwrap(); - let k = rng.gen_range(0..17); - if k == 0 && list_len < elem_len { - return Some(Action::AddProgressBar(list.len())); - } else { - let l = (k % list_len) as usize; - let pos = list[l].progress_bar.position(); - let len = list[l].progress_bar.length(); - if pos < len.unwrap() { - return Some(Action::IncProgressBar(l)); - } - } - } - } -} diff --git a/vendor/indicatif/examples/multi.rs b/vendor/indicatif/examples/multi.rs deleted file mode 100644 index 5ec6c5c..0000000 --- a/vendor/indicatif/examples/multi.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; - -use rand::Rng; - -fn main() { - let m = MultiProgress::new(); - let sty = ProgressStyle::with_template( - "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", - ) - .unwrap() - .progress_chars("##-"); - - let n = 200; - let pb = m.add(ProgressBar::new(n)); - pb.set_style(sty.clone()); - pb.set_message("todo"); - let pb2 = m.add(ProgressBar::new(n)); - pb2.set_style(sty.clone()); - pb2.set_message("finished"); - - let pb3 = m.insert_after(&pb2, ProgressBar::new(1024)); - pb3.set_style(sty); - - m.println("starting!").unwrap(); - - let mut threads = vec![]; - - let m_clone = m.clone(); - let h3 = thread::spawn(move || { - for i in 0..1024 { - thread::sleep(Duration::from_millis(2)); - pb3.set_message(format!("item #{}", i + 1)); - pb3.inc(1); - } - m_clone.println("pb3 is done!").unwrap(); - pb3.finish_with_message("done"); - }); - - for i in 0..n { - thread::sleep(Duration::from_millis(15)); - if i == n / 3 { - thread::sleep(Duration::from_secs(2)); - } - pb.inc(1); - let m = m.clone(); - let pb2 = pb2.clone(); - threads.push(thread::spawn(move || { - let spinner = m.add(ProgressBar::new_spinner().with_message(i.to_string())); - spinner.enable_steady_tick(Duration::from_millis(100)); - thread::sleep( - rand::thread_rng().gen_range(Duration::from_secs(1)..Duration::from_secs(5)), - ); - pb2.inc(1); - })); - } - pb.finish_with_message("all jobs started"); - - for thread in threads { - let _ = thread.join(); - } - let _ = h3.join(); - pb2.finish_with_message("all jobs done"); - m.clear().unwrap(); -} diff --git a/vendor/indicatif/examples/single.rs b/vendor/indicatif/examples/single.rs deleted file mode 100644 index 6e921e5..0000000 --- a/vendor/indicatif/examples/single.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::ProgressBar; - -fn main() { - let pb = ProgressBar::new(1024); - for _ in 0..1024 { - thread::sleep(Duration::from_millis(5)); - pb.inc(1); - } - pb.finish_with_message("done"); -} diff --git a/vendor/indicatif/examples/slow.rs b/vendor/indicatif/examples/slow.rs deleted file mode 100644 index 91a8e7e..0000000 --- a/vendor/indicatif/examples/slow.rs +++ /dev/null @@ -1,12 +0,0 @@ -use indicatif::{ProgressBar, ProgressStyle}; -use std::time::Duration; - -fn main() { - let progress = - ProgressBar::new(10).with_style(ProgressStyle::default_bar().progress_chars("πππ")); - for _ in 0..10 { - progress.inc(1); - std::thread::sleep(Duration::from_secs(1)); - } - progress.finish(); -} diff --git a/vendor/indicatif/examples/spinner-loop.rs b/vendor/indicatif/examples/spinner-loop.rs deleted file mode 100644 index 14d698b..0000000 --- a/vendor/indicatif/examples/spinner-loop.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::{ProgressBar, ProgressFinish}; - -fn main() { - let mut spinner: Option<ProgressBar> = None; - - for i in 0..3 { - let new_spinner = ProgressBar::new_spinner() - .with_message(format!("doing stuff {}", i)) - .with_finish(ProgressFinish::AndLeave); - new_spinner.enable_steady_tick(Duration::from_millis(10)); - thread::sleep(Duration::from_millis(500)); - println!("\n\nreplace {}\n\n", i); - spinner.replace(new_spinner).map(|t| t.finish()); - } -} diff --git a/vendor/indicatif/examples/steady.rs b/vendor/indicatif/examples/steady.rs deleted file mode 100644 index 4515ce9..0000000 --- a/vendor/indicatif/examples/steady.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::{ - thread::sleep, - time::{Duration, Instant}, -}; - -use indicatif::{ProgressBar, ProgressIterator, ProgressStyle}; - -fn main() { - let iterations = 1000; - // Set the array with all the blocksizes to test - let blocksizes: [usize; 7] = [16, 64, 256, 1024, 4096, 16384, 65536]; - - // Set the array with all the durations to save - let mut elapsed: [Duration; 7] = [Duration::ZERO; 7]; - - for (pos, blocksize) in blocksizes.iter().enumerate() { - // Set up the style for the progressbar - let sty = ProgressStyle::default_spinner() - .tick_strings(&[ - "βΉβΉβΉβΉβΉ", - "βΈβΉβΉβΉβΉ", - "βΉβΈβΉβΉβΉ", - "βΉβΉβΈβΉβΉ", - "βΉβΉβΉβΈβΉ", - "βΉβΉβΉβΉβΈ", - "βͺβͺβͺβͺβͺ", - ]) - .template("{prefix} {pos:>4}/{len:4} Iterations per second: {per_sec} {spinner} {msg}") - .unwrap(); - - // Set up the progress bar and apply the style - let pb = ProgressBar::new(iterations); - pb.set_style(sty); - pb.enable_steady_tick(Duration::from_millis(120)); - pb.set_prefix(format!("Doing test with Blocksize {:5?}:", blocksize)); - - // Iterate for the given number of iterations - // for _ in (0..iterations) { - for _ in (0..iterations).progress_with(pb) { - // pb.inc(1); - // Take a timestamp for timemeasurement later on - let now = Instant::now(); - sleep(Duration::from_millis(1)); - // Save the elapsed time for later evaluation - elapsed[pos] += now.elapsed(); - } - - // pb.finish_using_style(); - } -} diff --git a/vendor/indicatif/examples/tokio.rs b/vendor/indicatif/examples/tokio.rs deleted file mode 100644 index 17ac2b1..0000000 --- a/vendor/indicatif/examples/tokio.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::time::Duration; - -use indicatif::ProgressBar; -use tokio::runtime; -use tokio::time::interval; - -fn main() { - // Plain progress bar, totaling 1024 steps. - let steps = 1024; - let pb = ProgressBar::new(steps); - - // Stream of events, triggering every 5ms. - let rt = runtime::Builder::new_current_thread() - .enable_time() - .build() - .expect("failed to create runtime"); - - // Future computation which runs for `steps` interval events, - // incrementing one step of the progress bar each time. - let future = async { - let mut intv = interval(Duration::from_millis(5)); - - for _ in 0..steps { - intv.tick().await; - pb.inc(1); - } - }; - - // Drive the future to completion, blocking until done. - rt.block_on(future); - - // Mark the progress bar as finished. - pb.finish(); -} diff --git a/vendor/indicatif/examples/yarnish.rs b/vendor/indicatif/examples/yarnish.rs deleted file mode 100644 index 6b7c29b..0000000 --- a/vendor/indicatif/examples/yarnish.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::thread; -use std::time::{Duration, Instant}; - -use console::{style, Emoji}; -use indicatif::{HumanDuration, MultiProgress, ProgressBar, ProgressStyle}; -use rand::seq::SliceRandom; -use rand::Rng; - -static PACKAGES: &[&str] = &[ - "fs-events", - "my-awesome-module", - "emoji-speaker", - "wrap-ansi", - "stream-browserify", - "acorn-dynamic-import", -]; - -static COMMANDS: &[&str] = &[ - "cmake .", - "make", - "make clean", - "gcc foo.c -o foo", - "gcc bar.c -o bar", - "./helper.sh rebuild-cache", - "make all-clean", - "make test", -]; - -static LOOKING_GLASS: Emoji<'_, '_> = Emoji("π ", ""); -static TRUCK: Emoji<'_, '_> = Emoji("π ", ""); -static CLIP: Emoji<'_, '_> = Emoji("π ", ""); -static PAPER: Emoji<'_, '_> = Emoji("π ", ""); -static SPARKLE: Emoji<'_, '_> = Emoji("β¨ ", ":-)"); - -pub fn main() { - let mut rng = rand::thread_rng(); - let started = Instant::now(); - let spinner_style = ProgressStyle::with_template("{prefix:.bold.dim} {spinner} {wide_msg}") - .unwrap() - .tick_chars("β β β β‘β’β β β "); - - println!( - "{} {}Resolving packages...", - style("[1/4]").bold().dim(), - LOOKING_GLASS - ); - println!( - "{} {}Fetching packages...", - style("[2/4]").bold().dim(), - TRUCK - ); - - println!( - "{} {}Linking dependencies...", - style("[3/4]").bold().dim(), - CLIP - ); - let deps = 1232; - let pb = ProgressBar::new(deps); - for _ in 0..deps { - thread::sleep(Duration::from_millis(3)); - pb.inc(1); - } - pb.finish_and_clear(); - - println!( - "{} {}Building fresh packages...", - style("[4/4]").bold().dim(), - PAPER - ); - let m = MultiProgress::new(); - let handles: Vec<_> = (0..4u32) - .map(|i| { - let count = rng.gen_range(30..80); - let pb = m.add(ProgressBar::new(count)); - pb.set_style(spinner_style.clone()); - pb.set_prefix(format!("[{}/?]", i + 1)); - thread::spawn(move || { - let mut rng = rand::thread_rng(); - let pkg = PACKAGES.choose(&mut rng).unwrap(); - for _ in 0..count { - let cmd = COMMANDS.choose(&mut rng).unwrap(); - thread::sleep(Duration::from_millis(rng.gen_range(25..200))); - pb.set_message(format!("{pkg}: {cmd}")); - pb.inc(1); - } - pb.finish_with_message("waiting..."); - }) - }) - .collect(); - for h in handles { - let _ = h.join(); - } - m.clear().unwrap(); - - println!("{} Done in {}", SPARKLE, HumanDuration(started.elapsed())); -} diff --git a/vendor/indicatif/src/draw_target.rs b/vendor/indicatif/src/draw_target.rs deleted file mode 100644 index a2c055f..0000000 --- a/vendor/indicatif/src/draw_target.rs +++ /dev/null @@ -1,561 +0,0 @@ -use std::io; -use std::sync::{Arc, RwLock, RwLockWriteGuard}; -use std::thread::panicking; -use std::time::Duration; -#[cfg(not(target_arch = "wasm32"))] -use std::time::Instant; - -use console::Term; -#[cfg(target_arch = "wasm32")] -use instant::Instant; - -use crate::multi::{MultiProgressAlignment, MultiState}; -use crate::TermLike; - -/// Target for draw operations -/// -/// This tells a progress bar or a multi progress object where to paint to. -/// The draw target is a stateful wrapper over a drawing destination and -/// internally optimizes how often the state is painted to the output -/// device. -#[derive(Debug)] -pub struct ProgressDrawTarget { - kind: TargetKind, -} - -impl ProgressDrawTarget { - /// Draw to a buffered stdout terminal at a max of 20 times a second. - /// - /// For more information see [`ProgressDrawTarget::term`]. - pub fn stdout() -> Self { - Self::term(Term::buffered_stdout(), 20) - } - - /// Draw to a buffered stderr terminal at a max of 20 times a second. - /// - /// This is the default draw target for progress bars. For more - /// information see [`ProgressDrawTarget::term`]. - pub fn stderr() -> Self { - Self::term(Term::buffered_stderr(), 20) - } - - /// Draw to a buffered stdout terminal at a max of `refresh_rate` times a second. - /// - /// For more information see [`ProgressDrawTarget::term`]. - pub fn stdout_with_hz(refresh_rate: u8) -> Self { - Self::term(Term::buffered_stdout(), refresh_rate) - } - - /// Draw to a buffered stderr terminal at a max of `refresh_rate` times a second. - /// - /// For more information see [`ProgressDrawTarget::term`]. - pub fn stderr_with_hz(refresh_rate: u8) -> Self { - Self::term(Term::buffered_stderr(), refresh_rate) - } - - pub(crate) fn new_remote(state: Arc<RwLock<MultiState>>, idx: usize) -> Self { - Self { - kind: TargetKind::Multi { state, idx }, - } - } - - /// Draw to a terminal, with a specific refresh rate. - /// - /// Progress bars are by default drawn to terminals however if the - /// terminal is not user attended the entire progress bar will be - /// hidden. This is done so that piping to a file will not produce - /// useless escape codes in that file. - /// - /// Will panic if refresh_rate is `0`. - pub fn term(term: Term, refresh_rate: u8) -> Self { - Self { - kind: TargetKind::Term { - term, - last_line_count: 0, - rate_limiter: RateLimiter::new(refresh_rate), - draw_state: DrawState::default(), - }, - } - } - - /// Draw to a boxed object that implements the [`TermLike`] trait. - pub fn term_like(term_like: Box<dyn TermLike>) -> Self { - Self { - kind: TargetKind::TermLike { - inner: term_like, - last_line_count: 0, - rate_limiter: None, - draw_state: DrawState::default(), - }, - } - } - - /// Draw to a boxed object that implements the [`TermLike`] trait, - /// with a specific refresh rate. - pub fn term_like_with_hz(term_like: Box<dyn TermLike>, refresh_rate: u8) -> Self { - Self { - kind: TargetKind::TermLike { - inner: term_like, - last_line_count: 0, - rate_limiter: Option::from(RateLimiter::new(refresh_rate)), - draw_state: DrawState::default(), - }, - } - } - - /// A hidden draw target. - /// - /// This forces a progress bar to be not rendered at all. - pub fn hidden() -> Self { - Self { - kind: TargetKind::Hidden, - } - } - - /// Returns true if the draw target is hidden. - /// - /// This is internally used in progress bars to figure out if overhead - /// from drawing can be prevented. - pub fn is_hidden(&self) -> bool { - match self.kind { - TargetKind::Hidden => true, - TargetKind::Term { ref term, .. } => !term.is_term(), - TargetKind::Multi { ref state, .. } => state.read().unwrap().is_hidden(), - _ => false, - } - } - - /// Returns the current width of the draw target. - pub(crate) fn width(&self) -> u16 { - match self.kind { - TargetKind::Term { ref term, .. } => term.size().1, - TargetKind::Multi { ref state, .. } => state.read().unwrap().width(), - TargetKind::Hidden => 0, - TargetKind::TermLike { ref inner, .. } => inner.width(), - } - } - - /// Notifies the backing `MultiProgress` (if applicable) that the associated progress bar should - /// be marked a zombie. - pub(crate) fn mark_zombie(&self) { - if let TargetKind::Multi { idx, state } = &self.kind { - state.write().unwrap().mark_zombie(*idx); - } - } - - /// Apply the given draw state (draws it). - pub(crate) fn drawable(&mut self, force_draw: bool, now: Instant) -> Option<Drawable<'_>> { - match &mut self.kind { - TargetKind::Term { - term, - last_line_count, - rate_limiter, - draw_state, - } => { - if !term.is_term() { - return None; - } - - match force_draw || rate_limiter.allow(now) { - true => Some(Drawable::Term { - term, - last_line_count, - draw_state, - }), - false => None, // rate limited - } - } - TargetKind::Multi { idx, state, .. } => { - let state = state.write().unwrap(); - Some(Drawable::Multi { - idx: *idx, - state, - force_draw, - now, - }) - } - TargetKind::TermLike { - inner, - last_line_count, - rate_limiter, - draw_state, - } => match force_draw || rate_limiter.as_mut().map_or(true, |r| r.allow(now)) { - true => Some(Drawable::TermLike { - term_like: &**inner, - last_line_count, - draw_state, - }), - false => None, // rate limited - }, - // Hidden, finished, or no need to refresh yet - _ => None, - } - } - - /// Properly disconnects from the draw target - pub(crate) fn disconnect(&self, now: Instant) { - match self.kind { - TargetKind::Term { .. } => {} - TargetKind::Multi { idx, ref state, .. } => { - let state = state.write().unwrap(); - let _ = Drawable::Multi { - state, - idx, - force_draw: true, - now, - } - .clear(); - } - TargetKind::Hidden => {} - TargetKind::TermLike { .. } => {} - }; - } - - pub(crate) fn remote(&self) -> Option<(&Arc<RwLock<MultiState>>, usize)> { - match &self.kind { - TargetKind::Multi { state, idx } => Some((state, *idx)), - _ => None, - } - } - - pub(crate) fn adjust_last_line_count(&mut self, adjust: LineAdjust) { - self.kind.adjust_last_line_count(adjust); - } -} - -#[derive(Debug)] -enum TargetKind { - Term { - term: Term, - last_line_count: usize, - rate_limiter: RateLimiter, - draw_state: DrawState, - }, - Multi { - state: Arc<RwLock<MultiState>>, - idx: usize, - }, - Hidden, - TermLike { - inner: Box<dyn TermLike>, - last_line_count: usize, - rate_limiter: Option<RateLimiter>, - draw_state: DrawState, - }, -} - -impl TargetKind { - /// Adjust `last_line_count` such that the next draw operation keeps/clears additional lines - fn adjust_last_line_count(&mut self, adjust: LineAdjust) { - let last_line_count: &mut usize = match self { - Self::Term { - last_line_count, .. - } => last_line_count, - Self::TermLike { - last_line_count, .. - } => last_line_count, - _ => return, - }; - - match adjust { - LineAdjust::Clear(count) => *last_line_count = last_line_count.saturating_add(count), - LineAdjust::Keep(count) => *last_line_count = last_line_count.saturating_sub(count), - } - } -} - -pub(crate) enum Drawable<'a> { - Term { - term: &'a Term, - last_line_count: &'a mut usize, - draw_state: &'a mut DrawState, - }, - Multi { - state: RwLockWriteGuard<'a, MultiState>, - idx: usize, - force_draw: bool, - now: Instant, - }, - TermLike { - term_like: &'a dyn TermLike, - last_line_count: &'a mut usize, - draw_state: &'a mut DrawState, - }, -} - -impl<'a> Drawable<'a> { - /// Adjust `last_line_count` such that the next draw operation keeps/clears additional lines - pub(crate) fn adjust_last_line_count(&mut self, adjust: LineAdjust) { - let last_line_count: &mut usize = match self { - Drawable::Term { - last_line_count, .. - } => last_line_count, - Drawable::TermLike { - last_line_count, .. - } => last_line_count, - _ => return, - }; - - match adjust { - LineAdjust::Clear(count) => *last_line_count = last_line_count.saturating_add(count), - LineAdjust::Keep(count) => *last_line_count = last_line_count.saturating_sub(count), - } - } - - pub(crate) fn state(&mut self) -> DrawStateWrapper<'_> { - let mut state = match self { - Drawable::Term { draw_state, .. } => DrawStateWrapper::for_term(draw_state), - Drawable::Multi { state, idx, .. } => state.draw_state(*idx), - Drawable::TermLike { draw_state, .. } => DrawStateWrapper::for_term(draw_state), - }; - - state.reset(); - state - } - - pub(crate) fn clear(mut self) -> io::Result<()> { - let state = self.state(); - drop(state); - self.draw() - } - - pub(crate) fn draw(self) -> io::Result<()> { - match self { - Drawable::Term { - term, - last_line_count, - draw_state, - } => draw_state.draw_to_term(term, last_line_count), - Drawable::Multi { - mut state, - force_draw, - now, - .. - } => state.draw(force_draw, None, now), - Drawable::TermLike { - term_like, - last_line_count, - draw_state, - } => draw_state.draw_to_term(term_like, last_line_count), - } - } -} - -pub(crate) enum LineAdjust { - /// Adds to `last_line_count` so that the next draw also clears those lines - Clear(usize), - /// Subtracts from `last_line_count` so that the next draw retains those lines - Keep(usize), -} - -pub(crate) struct DrawStateWrapper<'a> { - state: &'a mut DrawState, - orphan_lines: Option<&'a mut Vec<String>>, -} - -impl<'a> DrawStateWrapper<'a> { - pub(crate) fn for_term(state: &'a mut DrawState) -> Self { - Self { - state, - orphan_lines: None, - } - } - - pub(crate) fn for_multi(state: &'a mut DrawState, orphan_lines: &'a mut Vec<String>) -> Self { - Self { - state, - orphan_lines: Some(orphan_lines), - } - } -} - -impl std::ops::Deref for DrawStateWrapper<'_> { - type Target = DrawState; - - fn deref(&self) -> &Self::Target { - self.state - } -} - -impl std::ops::DerefMut for DrawStateWrapper<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.state - } -} - -impl Drop for DrawStateWrapper<'_> { - fn drop(&mut self) { - if let Some(orphaned) = &mut self.orphan_lines { - orphaned.extend(self.state.lines.drain(..self.state.orphan_lines_count)); - self.state.orphan_lines_count = 0; - } - } -} - -#[derive(Debug)] -struct RateLimiter { - interval: u16, // in milliseconds - capacity: u8, - prev: Instant, -} - -/// Rate limit but allow occasional bursts above desired rate -impl RateLimiter { - fn new(rate: u8) -> Self { - Self { - interval: 1000 / (rate as u16), // between 3 and 1000 milliseconds - capacity: MAX_BURST, - prev: Instant::now(), - } - } - - fn allow(&mut self, now: Instant) -> bool { - if now < self.prev { - return false; - } - - let elapsed = now - self.prev; - // If `capacity` is 0 and not enough time (`self.interval` ms) has passed since - // `self.prev` to add new capacity, return `false`. The goal of this method is to - // make this decision as efficient as possible. - if self.capacity == 0 && elapsed < Duration::from_millis(self.interval as u64) { - return false; - } - - // We now calculate `new`, the number of ms, since we last returned `true`, - // and `remainder`, which represents a number of ns less than 1ms which we cannot - // convert into capacity now, so we're saving it for later. - let (new, remainder) = ( - elapsed.as_millis() / self.interval as u128, - elapsed.as_nanos() % (self.interval as u128 * 1_000_000), - ); - - // We add `new` to `capacity`, subtract one for returning `true` from here, - // then make sure it does not exceed a maximum of `MAX_BURST`, then store it. - self.capacity = Ord::min(MAX_BURST as u128, (self.capacity as u128) + new - 1) as u8; - // Store `prev` for the next iteration after subtracting the `remainder`. - // Just use `unwrap` here because it shouldn't be possible for this to underflow. - self.prev = now - .checked_sub(Duration::from_nanos(remainder as u64)) - .unwrap(); - true - } -} - -const MAX_BURST: u8 = 20; - -/// The drawn state of an element. -#[derive(Clone, Debug, Default)] -pub(crate) struct DrawState { - /// The lines to print (can contain ANSI codes) - pub(crate) lines: Vec<String>, - /// The number of lines that shouldn't be reaped by the next tick. - pub(crate) orphan_lines_count: usize, - /// True if we should move the cursor up when possible instead of clearing lines. - pub(crate) move_cursor: bool, - /// Controls how the multi progress is aligned if some of its progress bars get removed, default is `Top` - pub(crate) alignment: MultiProgressAlignment, -} - -impl DrawState { - fn draw_to_term( - &mut self, - term: &(impl TermLike + ?Sized), - last_line_count: &mut usize, - ) -> io::Result<()> { - if panicking() { - return Ok(()); - } - - if !self.lines.is_empty() && self.move_cursor { - term.move_cursor_up(*last_line_count)?; - } else { - // Fork of console::clear_last_lines that assumes that the last line doesn't contain a '\n' - let n = *last_line_count; - term.move_cursor_up(n.saturating_sub(1))?; - for i in 0..n { - term.clear_line()?; - if i + 1 != n { - term.move_cursor_down(1)?; - } - } - term.move_cursor_up(n.saturating_sub(1))?; - } - - let shift = match self.alignment { - MultiProgressAlignment::Bottom if self.lines.len() < *last_line_count => { - let shift = *last_line_count - self.lines.len(); - for _ in 0..shift { - term.write_line("")?; - } - shift - } - _ => 0, - }; - - let term_height = term.height() as usize; - let term_width = term.width() as usize; - let len = self.lines.len(); - let mut real_len = 0; - let mut last_line_filler = 0; - debug_assert!(self.orphan_lines_count <= self.lines.len()); - for (idx, line) in self.lines.iter().enumerate() { - let line_width = console::measure_text_width(line); - let diff = if line.is_empty() { - // Empty line are new line - 1 - } else { - // Calculate real length based on terminal width - // This take in account linewrap from terminal - let terminal_len = (line_width as f64 / term_width as f64).ceil() as usize; - - // If the line is effectively empty (for example when it consists - // solely of ANSI color code sequences, count it the same as a - // new line. If the line is measured to be len = 0, we will - // subtract with overflow later. - usize::max(terminal_len, 1) - }; - // Don't consider orphan lines when comparing to terminal height. - debug_assert!(idx <= real_len); - if self.orphan_lines_count <= idx - && real_len - self.orphan_lines_count + diff > term_height - { - break; - } - real_len += diff; - if idx != 0 { - term.write_line("")?; - } - term.write_str(line)?; - if idx + 1 == len { - // Keep the cursor on the right terminal side - // So that next user writes/prints will happen on the next line - last_line_filler = term_width.saturating_sub(line_width); - } - } - term.write_str(&" ".repeat(last_line_filler))?; - - term.flush()?; - *last_line_count = real_len - self.orphan_lines_count + shift; - Ok(()) - } - - fn reset(&mut self) { - self.lines.clear(); - self.orphan_lines_count = 0; - } -} - -#[cfg(test)] -mod tests { - use crate::{MultiProgress, ProgressBar, ProgressDrawTarget}; - - #[test] - fn multi_is_hidden() { - let mp = MultiProgress::with_draw_target(ProgressDrawTarget::hidden()); - - let pb = mp.add(ProgressBar::new(100)); - assert!(mp.is_hidden()); - assert!(pb.is_hidden()); - } -} diff --git a/vendor/indicatif/src/format.rs b/vendor/indicatif/src/format.rs deleted file mode 100644 index 7475a25..0000000 --- a/vendor/indicatif/src/format.rs +++ /dev/null @@ -1,337 +0,0 @@ -use std::fmt; -use std::time::Duration; - -use number_prefix::NumberPrefix; - -const SECOND: Duration = Duration::from_secs(1); -const MINUTE: Duration = Duration::from_secs(60); -const HOUR: Duration = Duration::from_secs(60 * 60); -const DAY: Duration = Duration::from_secs(24 * 60 * 60); -const WEEK: Duration = Duration::from_secs(7 * 24 * 60 * 60); -const YEAR: Duration = Duration::from_secs(365 * 24 * 60 * 60); - -/// Wraps an std duration for human basic formatting. -#[derive(Debug)] -pub struct FormattedDuration(pub Duration); - -/// Wraps an std duration for human readable formatting. -#[derive(Debug)] -pub struct HumanDuration(pub Duration); - -/// Formats bytes for human readability -#[derive(Debug)] -pub struct HumanBytes(pub u64); - -/// Formats bytes for human readability using SI prefixes -#[derive(Debug)] -pub struct DecimalBytes(pub u64); - -/// Formats bytes for human readability using ISO/IEC prefixes -#[derive(Debug)] -pub struct BinaryBytes(pub u64); - -/// Formats counts for human readability using commas -#[derive(Debug)] -pub struct HumanCount(pub u64); - -/// Formats counts for human readability using commas for floats -#[derive(Debug)] -pub struct HumanFloatCount(pub f64); - -impl fmt::Display for FormattedDuration { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut t = self.0.as_secs(); - let seconds = t % 60; - t /= 60; - let minutes = t % 60; - t /= 60; - let hours = t % 24; - t /= 24; - if t > 0 { - let days = t; - write!(f, "{days}d {hours:02}:{minutes:02}:{seconds:02}") - } else { - write!(f, "{hours:02}:{minutes:02}:{seconds:02}") - } - } -} - -// `HumanDuration` should be as intuitively understandable as possible. -// So we want to round, not truncate: otherwise 1 hour and 59 minutes -// would display an ETA of "1 hour" which underestimates the time -// remaining by a factor 2. -// -// To make the precision more uniform, we avoid displaying "1 unit" -// (except for seconds), because it would be displayed for a relatively -// long duration compared to the unit itself. Instead, when we arrive -// around 1.5 unit, we change from "2 units" to the next smaller unit -// (e.g. "89 seconds"). -// -// Formally: -// * for n >= 2, we go from "n+1 units" to "n units" exactly at (n + 1/2) units -// * we switch from "2 units" to the next smaller unit at (1.5 unit minus half of the next smaller unit) - -impl fmt::Display for HumanDuration { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut idx = 0; - for (i, &(cur, _, _)) in UNITS.iter().enumerate() { - idx = i; - match UNITS.get(i + 1) { - Some(&next) if self.0.saturating_add(next.0 / 2) >= cur + cur / 2 => break, - _ => continue, - } - } - - let (unit, name, alt) = UNITS[idx]; - // FIXME when `div_duration_f64` is stable - let mut t = (self.0.as_secs_f64() / unit.as_secs_f64()).round() as usize; - if idx < UNITS.len() - 1 { - t = Ord::max(t, 2); - } - - match (f.alternate(), t) { - (true, _) => write!(f, "{t}{alt}"), - (false, 1) => write!(f, "{t} {name}"), - (false, _) => write!(f, "{t} {name}s"), - } - } -} - -const UNITS: &[(Duration, &str, &str)] = &[ - (YEAR, "year", "y"), - (WEEK, "week", "w"), - (DAY, "day", "d"), - (HOUR, "hour", "h"), - (MINUTE, "minute", "m"), - (SECOND, "second", "s"), -]; - -impl fmt::Display for HumanBytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match NumberPrefix::binary(self.0 as f64) { - NumberPrefix::Standalone(number) => write!(f, "{number:.0} B"), - NumberPrefix::Prefixed(prefix, number) => write!(f, "{number:.2} {prefix}B"), - } - } -} - -impl fmt::Display for DecimalBytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match NumberPrefix::decimal(self.0 as f64) { - NumberPrefix::Standalone(number) => write!(f, "{number:.0} B"), - NumberPrefix::Prefixed(prefix, number) => write!(f, "{number:.2} {prefix}B"), - } - } -} - -impl fmt::Display for BinaryBytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match NumberPrefix::binary(self.0 as f64) { - NumberPrefix::Standalone(number) => write!(f, "{number:.0} B"), - NumberPrefix::Prefixed(prefix, number) => write!(f, "{number:.2} {prefix}B"), - } - } -} - -impl fmt::Display for HumanCount { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use fmt::Write; - - let num = self.0.to_string(); - let len = num.len(); - for (idx, c) in num.chars().enumerate() { - let pos = len - idx - 1; - f.write_char(c)?; - if pos > 0 && pos % 3 == 0 { - f.write_char(',')?; - } - } - Ok(()) - } -} - -impl fmt::Display for HumanFloatCount { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use fmt::Write; - - let num = format!("{:.4}", self.0); - let (int_part, frac_part) = match num.split_once('.') { - Some((int_str, fract_str)) => (int_str.to_string(), fract_str), - None => (self.0.trunc().to_string(), ""), - }; - let len = int_part.len(); - for (idx, c) in int_part.chars().enumerate() { - let pos = len - idx - 1; - f.write_char(c)?; - if pos > 0 && pos % 3 == 0 { - f.write_char(',')?; - } - } - let frac_trimmed = frac_part.trim_end_matches('0'); - if !frac_trimmed.is_empty() { - f.write_char('.')?; - f.write_str(frac_trimmed)?; - } - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - const MILLI: Duration = Duration::from_millis(1); - - #[test] - fn human_duration_alternate() { - for (unit, _, alt) in UNITS { - assert_eq!(format!("2{alt}"), format!("{:#}", HumanDuration(2 * *unit))); - } - } - - #[test] - fn human_duration_less_than_one_second() { - assert_eq!( - "0 seconds", - format!("{}", HumanDuration(Duration::from_secs(0))) - ); - assert_eq!("0 seconds", format!("{}", HumanDuration(MILLI))); - assert_eq!("0 seconds", format!("{}", HumanDuration(499 * MILLI))); - assert_eq!("1 second", format!("{}", HumanDuration(500 * MILLI))); - assert_eq!("1 second", format!("{}", HumanDuration(999 * MILLI))); - } - - #[test] - fn human_duration_less_than_two_seconds() { - assert_eq!("1 second", format!("{}", HumanDuration(1499 * MILLI))); - assert_eq!("2 seconds", format!("{}", HumanDuration(1500 * MILLI))); - assert_eq!("2 seconds", format!("{}", HumanDuration(1999 * MILLI))); - } - - #[test] - fn human_duration_one_unit() { - assert_eq!("1 second", format!("{}", HumanDuration(SECOND))); - assert_eq!("60 seconds", format!("{}", HumanDuration(MINUTE))); - assert_eq!("60 minutes", format!("{}", HumanDuration(HOUR))); - assert_eq!("24 hours", format!("{}", HumanDuration(DAY))); - assert_eq!("7 days", format!("{}", HumanDuration(WEEK))); - assert_eq!("52 weeks", format!("{}", HumanDuration(YEAR))); - } - - #[test] - fn human_duration_less_than_one_and_a_half_unit() { - // this one is actually done at 1.5 unit - half of the next smaller unit - epsilon - // and should display the next smaller unit - let d = HumanDuration(MINUTE + MINUTE / 2 - SECOND / 2 - MILLI); - assert_eq!("89 seconds", format!("{d}")); - let d = HumanDuration(HOUR + HOUR / 2 - MINUTE / 2 - MILLI); - assert_eq!("89 minutes", format!("{d}")); - let d = HumanDuration(DAY + DAY / 2 - HOUR / 2 - MILLI); - assert_eq!("35 hours", format!("{d}")); - let d = HumanDuration(WEEK + WEEK / 2 - DAY / 2 - MILLI); - assert_eq!("10 days", format!("{d}")); - let d = HumanDuration(YEAR + YEAR / 2 - WEEK / 2 - MILLI); - assert_eq!("78 weeks", format!("{d}")); - } - - #[test] - fn human_duration_one_and_a_half_unit() { - // this one is actually done at 1.5 unit - half of the next smaller unit - // and should still display "2 units" - let d = HumanDuration(MINUTE + MINUTE / 2 - SECOND / 2); - assert_eq!("2 minutes", format!("{d}")); - let d = HumanDuration(HOUR + HOUR / 2 - MINUTE / 2); - assert_eq!("2 hours", format!("{d}")); - let d = HumanDuration(DAY + DAY / 2 - HOUR / 2); - assert_eq!("2 days", format!("{d}")); - let d = HumanDuration(WEEK + WEEK / 2 - DAY / 2); - assert_eq!("2 weeks", format!("{d}")); - let d = HumanDuration(YEAR + YEAR / 2 - WEEK / 2); - assert_eq!("2 years", format!("{d}")); - } - - #[test] - fn human_duration_two_units() { - assert_eq!("2 seconds", format!("{}", HumanDuration(2 * SECOND))); - assert_eq!("2 minutes", format!("{}", HumanDuration(2 * MINUTE))); - assert_eq!("2 hours", format!("{}", HumanDuration(2 * HOUR))); - assert_eq!("2 days", format!("{}", HumanDuration(2 * DAY))); - assert_eq!("2 weeks", format!("{}", HumanDuration(2 * WEEK))); - assert_eq!("2 years", format!("{}", HumanDuration(2 * YEAR))); - } - - #[test] - fn human_duration_less_than_two_and_a_half_units() { - let d = HumanDuration(2 * SECOND + SECOND / 2 - MILLI); - assert_eq!("2 seconds", format!("{d}")); - let d = HumanDuration(2 * MINUTE + MINUTE / 2 - MILLI); - assert_eq!("2 minutes", format!("{d}")); - let d = HumanDuration(2 * HOUR + HOUR / 2 - MILLI); - assert_eq!("2 hours", format!("{d}")); - let d = HumanDuration(2 * DAY + DAY / 2 - MILLI); - assert_eq!("2 days", format!("{d}")); - let d = HumanDuration(2 * WEEK + WEEK / 2 - MILLI); - assert_eq!("2 weeks", format!("{d}")); - let d = HumanDuration(2 * YEAR + YEAR / 2 - MILLI); - assert_eq!("2 years", format!("{d}")); - } - - #[test] - fn human_duration_two_and_a_half_units() { - let d = HumanDuration(2 * SECOND + SECOND / 2); - assert_eq!("3 seconds", format!("{d}")); - let d = HumanDuration(2 * MINUTE + MINUTE / 2); - assert_eq!("3 minutes", format!("{d}")); - let d = HumanDuration(2 * HOUR + HOUR / 2); - assert_eq!("3 hours", format!("{d}")); - let d = HumanDuration(2 * DAY + DAY / 2); - assert_eq!("3 days", format!("{d}")); - let d = HumanDuration(2 * WEEK + WEEK / 2); - assert_eq!("3 weeks", format!("{d}")); - let d = HumanDuration(2 * YEAR + YEAR / 2); - assert_eq!("3 years", format!("{d}")); - } - - #[test] - fn human_duration_three_units() { - assert_eq!("3 seconds", format!("{}", HumanDuration(3 * SECOND))); - assert_eq!("3 minutes", format!("{}", HumanDuration(3 * MINUTE))); - assert_eq!("3 hours", format!("{}", HumanDuration(3 * HOUR))); - assert_eq!("3 days", format!("{}", HumanDuration(3 * DAY))); - assert_eq!("3 weeks", format!("{}", HumanDuration(3 * WEEK))); - assert_eq!("3 years", format!("{}", HumanDuration(3 * YEAR))); - } - - #[test] - fn human_count() { - assert_eq!("42", format!("{}", HumanCount(42))); - assert_eq!("7,654", format!("{}", HumanCount(7654))); - assert_eq!("12,345", format!("{}", HumanCount(12345))); - assert_eq!("1,234,567,890", format!("{}", HumanCount(1234567890))); - } - - #[test] - fn human_float_count() { - assert_eq!("42", format!("{}", HumanFloatCount(42.0))); - assert_eq!("7,654", format!("{}", HumanFloatCount(7654.0))); - assert_eq!("12,345", format!("{}", HumanFloatCount(12345.0))); - assert_eq!( - "1,234,567,890", - format!("{}", HumanFloatCount(1234567890.0)) - ); - assert_eq!("42.5", format!("{}", HumanFloatCount(42.5))); - assert_eq!("42.5", format!("{}", HumanFloatCount(42.500012345))); - assert_eq!("42.502", format!("{}", HumanFloatCount(42.502012345))); - assert_eq!("7,654.321", format!("{}", HumanFloatCount(7654.321))); - assert_eq!("7,654.321", format!("{}", HumanFloatCount(7654.3210123456))); - assert_eq!("12,345.6789", format!("{}", HumanFloatCount(12345.6789))); - assert_eq!( - "1,234,567,890.1235", - format!("{}", HumanFloatCount(1234567890.1234567)) - ); - assert_eq!( - "1,234,567,890.1234", - format!("{}", HumanFloatCount(1234567890.1234321)) - ); - } -} diff --git a/vendor/indicatif/src/in_memory.rs b/vendor/indicatif/src/in_memory.rs deleted file mode 100644 index 046ae14..0000000 --- a/vendor/indicatif/src/in_memory.rs +++ /dev/null @@ -1,399 +0,0 @@ -use std::fmt::{Debug, Formatter, Write as _}; -use std::io::Write as _; -use std::sync::{Arc, Mutex}; - -use vt100::Parser; - -use crate::TermLike; - -/// A thin wrapper around [`vt100::Parser`]. -/// -/// This is just an [`Arc`] around its internal state, so it can be freely cloned. -#[cfg_attr(docsrs, doc(cfg(feature = "in_memory")))] -#[derive(Debug, Clone)] -pub struct InMemoryTerm { - state: Arc<Mutex<InMemoryTermState>>, -} - -impl InMemoryTerm { - pub fn new(rows: u16, cols: u16) -> InMemoryTerm { - assert!(rows > 0, "rows must be > 0"); - assert!(cols > 0, "cols must be > 0"); - InMemoryTerm { - state: Arc::new(Mutex::new(InMemoryTermState::new(rows, cols))), - } - } - - pub fn reset(&self) { - let mut state = self.state.lock().unwrap(); - *state = InMemoryTermState::new(state.height, state.width); - } - - pub fn contents(&self) -> String { - let state = self.state.lock().unwrap(); - - // For some reason, the `Screen::contents` method doesn't include newlines in what it - // returns, making it useless for our purposes. So we need to manually reconstruct the - // contents by iterating over the rows in the terminal buffer. - let mut rows = state - .parser - .screen() - .rows(0, state.width) - .collect::<Vec<_>>(); - - // Reverse the rows and trim empty lines from the end - rows = rows - .into_iter() - .rev() - .skip_while(|line| line.is_empty()) - .map(|line| line.trim_end().to_string()) - .collect(); - - // Un-reverse the rows and join them up with newlines - rows.reverse(); - rows.join("\n") - } - - pub fn contents_formatted(&self) -> Vec<u8> { - let state = self.state.lock().unwrap(); - - // For some reason, the `Screen::contents` method doesn't include newlines in what it - // returns, making it useless for our purposes. So we need to manually reconstruct the - // contents by iterating over the rows in the terminal buffer. - let mut rows = state - .parser - .screen() - .rows_formatted(0, state.width) - .collect::<Vec<_>>(); - - // Reverse the rows and trim empty lines from the end - rows = rows - .into_iter() - .rev() - .skip_while(|line| line.is_empty()) - .collect(); - - // Un-reverse the rows - rows.reverse(); - - // Calculate buffer size - let reset = b"[m"; - let len = rows.iter().map(|line| line.len() + reset.len() + 1).sum(); - - // Join rows up with reset codes and newlines - let mut contents = rows.iter().fold(Vec::with_capacity(len), |mut acc, cur| { - acc.extend_from_slice(cur); - acc.extend_from_slice(reset); - acc.push(b'\n'); - acc - }); - - // Remove last newline again, but leave the reset code - contents.truncate(len.saturating_sub(1)); - contents - } - - pub fn moves_since_last_check(&self) -> String { - let mut s = String::new(); - for line in std::mem::take(&mut self.state.lock().unwrap().history) { - writeln!(s, "{line:?}").unwrap(); - } - s - } -} - -impl TermLike for InMemoryTerm { - fn width(&self) -> u16 { - self.state.lock().unwrap().width - } - - fn height(&self) -> u16 { - self.state.lock().unwrap().height - } - - fn move_cursor_up(&self, n: usize) -> std::io::Result<()> { - match n { - 0 => Ok(()), - _ => { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Up(n)); - state.write_str(&format!("\x1b[{n}A")) - } - } - } - - fn move_cursor_down(&self, n: usize) -> std::io::Result<()> { - match n { - 0 => Ok(()), - _ => { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Down(n)); - state.write_str(&format!("\x1b[{n}B")) - } - } - } - - fn move_cursor_right(&self, n: usize) -> std::io::Result<()> { - match n { - 0 => Ok(()), - _ => { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Right(n)); - state.write_str(&format!("\x1b[{n}C")) - } - } - } - - fn move_cursor_left(&self, n: usize) -> std::io::Result<()> { - match n { - 0 => Ok(()), - _ => { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Left(n)); - state.write_str(&format!("\x1b[{n}D")) - } - } - } - - fn write_line(&self, s: &str) -> std::io::Result<()> { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Str(s.into())); - state.history.push(Move::NewLine); - - // Don't try to handle writing lines with additional newlines embedded in them - it's not - // worth the extra code for something that indicatif doesn't even do. May revisit in future. - debug_assert!( - s.lines().count() <= 1, - "calling write_line with embedded newlines is not allowed" - ); - - // vte100 needs the full \r\n sequence to jump to the next line and reset the cursor to - // the beginning of the line. Be flexible and take either \n or \r\n - state.write_str(s)?; - state.write_str("\r\n") - } - - fn write_str(&self, s: &str) -> std::io::Result<()> { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Str(s.into())); - state.write_str(s) - } - - fn clear_line(&self) -> std::io::Result<()> { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Clear); - state.write_str("\r\x1b[2K") - } - - fn flush(&self) -> std::io::Result<()> { - let mut state = self.state.lock().unwrap(); - state.history.push(Move::Flush); - state.parser.flush() - } -} - -struct InMemoryTermState { - width: u16, - height: u16, - parser: vt100::Parser, - history: Vec<Move>, -} - -impl InMemoryTermState { - pub(crate) fn new(rows: u16, cols: u16) -> InMemoryTermState { - InMemoryTermState { - width: cols, - height: rows, - parser: Parser::new(rows, cols, 0), - history: vec![], - } - } - - pub(crate) fn write_str(&mut self, s: &str) -> std::io::Result<()> { - self.parser.write_all(s.as_bytes()) - } -} - -impl Debug for InMemoryTermState { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("InMemoryTermState").finish_non_exhaustive() - } -} - -#[derive(Debug, PartialEq, Clone)] -enum Move { - Up(usize), - Down(usize), - Left(usize), - Right(usize), - Str(String), - NewLine, - Clear, - Flush, -} - -#[cfg(test)] -mod test { - use super::*; - - fn cursor_pos(in_mem: &InMemoryTerm) -> (u16, u16) { - in_mem - .state - .lock() - .unwrap() - .parser - .screen() - .cursor_position() - } - - #[test] - fn line_wrapping() { - let in_mem = InMemoryTerm::new(10, 5); - assert_eq!(cursor_pos(&in_mem), (0, 0)); - - in_mem.write_str("ABCDE").unwrap(); - assert_eq!(in_mem.contents(), "ABCDE"); - assert_eq!(cursor_pos(&in_mem), (0, 5)); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("ABCDE") -"# - ); - - // Should wrap onto next line - in_mem.write_str("FG").unwrap(); - assert_eq!(in_mem.contents(), "ABCDE\nFG"); - assert_eq!(cursor_pos(&in_mem), (1, 2)); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("FG") -"# - ); - - in_mem.write_str("HIJ").unwrap(); - assert_eq!(in_mem.contents(), "ABCDE\nFGHIJ"); - assert_eq!(cursor_pos(&in_mem), (1, 5)); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("HIJ") -"# - ); - } - - #[test] - fn write_line() { - let in_mem = InMemoryTerm::new(10, 5); - assert_eq!(cursor_pos(&in_mem), (0, 0)); - - in_mem.write_line("A").unwrap(); - assert_eq!(in_mem.contents(), "A"); - assert_eq!(cursor_pos(&in_mem), (1, 0)); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("A") -NewLine -"# - ); - - in_mem.write_line("B").unwrap(); - assert_eq!(in_mem.contents(), "A\nB"); - assert_eq!(cursor_pos(&in_mem), (2, 0)); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("B") -NewLine -"# - ); - - in_mem.write_line("Longer than cols").unwrap(); - assert_eq!(in_mem.contents(), "A\nB\nLonge\nr tha\nn col\ns"); - assert_eq!(cursor_pos(&in_mem), (6, 0)); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("Longer than cols") -NewLine -"# - ); - } - - #[test] - fn basic_functionality() { - let in_mem = InMemoryTerm::new(10, 80); - - in_mem.write_line("This is a test line").unwrap(); - assert_eq!(in_mem.contents(), "This is a test line"); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("This is a test line") -NewLine -"# - ); - - in_mem.write_line("And another line!").unwrap(); - assert_eq!(in_mem.contents(), "This is a test line\nAnd another line!"); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("And another line!") -NewLine -"# - ); - - in_mem.move_cursor_up(1).unwrap(); - in_mem.write_str("TEST").unwrap(); - - assert_eq!(in_mem.contents(), "This is a test line\nTESTanother line!"); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Up(1) -Str("TEST") -"# - ); - } - - #[test] - fn newlines() { - let in_mem = InMemoryTerm::new(10, 10); - in_mem.write_line("LINE ONE").unwrap(); - in_mem.write_line("LINE TWO").unwrap(); - in_mem.write_line("").unwrap(); - in_mem.write_line("LINE FOUR").unwrap(); - - assert_eq!(in_mem.contents(), "LINE ONE\nLINE TWO\n\nLINE FOUR"); - - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("LINE ONE") -NewLine -Str("LINE TWO") -NewLine -Str("") -NewLine -Str("LINE FOUR") -NewLine -"# - ); - } - - #[test] - fn cursor_zero_movement() { - let in_mem = InMemoryTerm::new(10, 80); - in_mem.write_line("LINE ONE").unwrap(); - assert_eq!(cursor_pos(&in_mem), (1, 0)); - - // Check that moving zero rows/cols does not actually move cursor - in_mem.move_cursor_up(0).unwrap(); - assert_eq!(cursor_pos(&in_mem), (1, 0)); - - in_mem.move_cursor_down(0).unwrap(); - assert_eq!(cursor_pos(&in_mem), (1, 0)); - - in_mem.move_cursor_right(1).unwrap(); - assert_eq!(cursor_pos(&in_mem), (1, 1)); - - in_mem.move_cursor_left(0).unwrap(); - assert_eq!(cursor_pos(&in_mem), (1, 1)); - - in_mem.move_cursor_right(0).unwrap(); - assert_eq!(cursor_pos(&in_mem), (1, 1)); - } -} diff --git a/vendor/indicatif/src/iter.rs b/vendor/indicatif/src/iter.rs deleted file mode 100644 index 3e73660..0000000 --- a/vendor/indicatif/src/iter.rs +++ /dev/null @@ -1,355 +0,0 @@ -use std::borrow::Cow; -use std::io::{self, IoSliceMut}; -use std::iter::FusedIterator; -#[cfg(feature = "tokio")] -use std::pin::Pin; -#[cfg(feature = "tokio")] -use std::task::{Context, Poll}; -use std::time::Duration; - -#[cfg(feature = "tokio")] -use tokio::io::{ReadBuf, SeekFrom}; - -use crate::progress_bar::ProgressBar; -use crate::state::ProgressFinish; -use crate::style::ProgressStyle; - -/// Wraps an iterator to display its progress. -pub trait ProgressIterator -where - Self: Sized + Iterator, -{ - /// Wrap an iterator with default styling. Uses `Iterator::size_hint` to get length. - /// Returns `Some(..)` only if `size_hint.1` is `Some`. If you want to create a progress bar - /// even if `size_hint.1` returns `None` use `progress_count` or `progress_with` instead. - fn try_progress(self) -> Option<ProgressBarIter<Self>> { - self.size_hint() - .1 - .map(|len| self.progress_count(u64::try_from(len).unwrap())) - } - - /// Wrap an iterator with default styling. - fn progress(self) -> ProgressBarIter<Self> - where - Self: ExactSizeIterator, - { - let len = u64::try_from(self.len()).unwrap(); - self.progress_count(len) - } - - /// Wrap an iterator with an explicit element count. - fn progress_count(self, len: u64) -> ProgressBarIter<Self> { - self.progress_with(ProgressBar::new(len)) - } - - /// Wrap an iterator with a custom progress bar. - fn progress_with(self, progress: ProgressBar) -> ProgressBarIter<Self>; - - /// Wrap an iterator with a progress bar and style it. - fn progress_with_style(self, style: crate::ProgressStyle) -> ProgressBarIter<Self> - where - Self: ExactSizeIterator, - { - let len = u64::try_from(self.len()).unwrap(); - let bar = ProgressBar::new(len).with_style(style); - self.progress_with(bar) - } -} - -/// Wraps an iterator to display its progress. -#[derive(Debug)] -pub struct ProgressBarIter<T> { - pub(crate) it: T, - pub progress: ProgressBar, -} - -impl<T> ProgressBarIter<T> { - /// Builder-like function for setting underlying progress bar's style. - /// - /// See [ProgressBar::with_style]. - pub fn with_style(mut self, style: ProgressStyle) -> Self { - self.progress = self.progress.with_style(style); - self - } - - /// Builder-like function for setting underlying progress bar's prefix. - /// - /// See [ProgressBar::with_prefix]. - pub fn with_prefix(mut self, prefix: impl Into<Cow<'static, str>>) -> Self { - self.progress = self.progress.with_prefix(prefix); - self - } - - /// Builder-like function for setting underlying progress bar's message. - /// - /// See [ProgressBar::with_message]. - pub fn with_message(mut self, message: impl Into<Cow<'static, str>>) -> Self { - self.progress = self.progress.with_message(message); - self - } - - /// Builder-like function for setting underlying progress bar's position. - /// - /// See [ProgressBar::with_position]. - pub fn with_position(mut self, position: u64) -> Self { - self.progress = self.progress.with_position(position); - self - } - - /// Builder-like function for setting underlying progress bar's elapsed time. - /// - /// See [ProgressBar::with_elapsed]. - pub fn with_elapsed(mut self, elapsed: Duration) -> Self { - self.progress = self.progress.with_elapsed(elapsed); - self - } - - /// Builder-like function for setting underlying progress bar's finish behavior. - /// - /// See [ProgressBar::with_finish]. - pub fn with_finish(mut self, finish: ProgressFinish) -> Self { - self.progress = self.progress.with_finish(finish); - self - } -} - -impl<S, T: Iterator<Item = S>> Iterator for ProgressBarIter<T> { - type Item = S; - - fn next(&mut self) -> Option<Self::Item> { - let item = self.it.next(); - - if item.is_some() { - self.progress.inc(1); - } else if !self.progress.is_finished() { - self.progress.finish_using_style(); - } - - item - } -} - -impl<T: ExactSizeIterator> ExactSizeIterator for ProgressBarIter<T> { - fn len(&self) -> usize { - self.it.len() - } -} - -impl<T: DoubleEndedIterator> DoubleEndedIterator for ProgressBarIter<T> { - fn next_back(&mut self) -> Option<Self::Item> { - let item = self.it.next_back(); - - if item.is_some() { - self.progress.inc(1); - } else if !self.progress.is_finished() { - self.progress.finish_using_style(); - } - - item - } -} - -impl<T: FusedIterator> FusedIterator for ProgressBarIter<T> {} - -impl<R: io::Read> io::Read for ProgressBarIter<R> { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - let inc = self.it.read(buf)?; - self.progress.inc(inc as u64); - Ok(inc) - } - - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - let inc = self.it.read_vectored(bufs)?; - self.progress.inc(inc as u64); - Ok(inc) - } - - fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { - let inc = self.it.read_to_string(buf)?; - self.progress.inc(inc as u64); - Ok(inc) - } - - fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { - self.it.read_exact(buf)?; - self.progress.inc(buf.len() as u64); - Ok(()) - } -} - -impl<R: io::BufRead> io::BufRead for ProgressBarIter<R> { - fn fill_buf(&mut self) -> io::Result<&[u8]> { - self.it.fill_buf() - } - - fn consume(&mut self, amt: usize) { - self.it.consume(amt); - self.progress.inc(amt as u64); - } -} - -impl<S: io::Seek> io::Seek for ProgressBarIter<S> { - fn seek(&mut self, f: io::SeekFrom) -> io::Result<u64> { - self.it.seek(f).map(|pos| { - self.progress.set_position(pos); - pos - }) - } - // Pass this through to preserve optimizations that the inner I/O object may use here - // Also avoid sending a set_position update when the position hasn't changed - fn stream_position(&mut self) -> io::Result<u64> { - self.it.stream_position() - } -} - -#[cfg(feature = "tokio")] -#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] -impl<W: tokio::io::AsyncWrite + Unpin> tokio::io::AsyncWrite for ProgressBarIter<W> { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll<io::Result<usize>> { - Pin::new(&mut self.it).poll_write(cx, buf).map(|poll| { - poll.map(|inc| { - self.progress.inc(inc as u64); - inc - }) - }) - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { - Pin::new(&mut self.it).poll_flush(cx) - } - - fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { - Pin::new(&mut self.it).poll_shutdown(cx) - } -} - -#[cfg(feature = "tokio")] -#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] -impl<W: tokio::io::AsyncRead + Unpin> tokio::io::AsyncRead for ProgressBarIter<W> { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut ReadBuf<'_>, - ) -> Poll<io::Result<()>> { - let prev_len = buf.filled().len() as u64; - if let Poll::Ready(e) = Pin::new(&mut self.it).poll_read(cx, buf) { - self.progress.inc(buf.filled().len() as u64 - prev_len); - Poll::Ready(e) - } else { - Poll::Pending - } - } -} - -#[cfg(feature = "tokio")] -#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] -impl<W: tokio::io::AsyncSeek + Unpin> tokio::io::AsyncSeek for ProgressBarIter<W> { - fn start_seek(mut self: Pin<&mut Self>, position: SeekFrom) -> io::Result<()> { - Pin::new(&mut self.it).start_seek(position) - } - - fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> { - Pin::new(&mut self.it).poll_complete(cx) - } -} - -#[cfg(feature = "tokio")] -#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] -impl<W: tokio::io::AsyncBufRead + Unpin + tokio::io::AsyncRead> tokio::io::AsyncBufRead - for ProgressBarIter<W> -{ - fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> { - let this = self.get_mut(); - let result = Pin::new(&mut this.it).poll_fill_buf(cx); - if let Poll::Ready(Ok(buf)) = &result { - this.progress.inc(buf.len() as u64); - } - result - } - - fn consume(mut self: Pin<&mut Self>, amt: usize) { - Pin::new(&mut self.it).consume(amt); - } -} - -#[cfg(feature = "futures")] -#[cfg_attr(docsrs, doc(cfg(feature = "futures")))] -impl<S: futures_core::Stream + Unpin> futures_core::Stream for ProgressBarIter<S> { - type Item = S::Item; - - fn poll_next( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll<Option<Self::Item>> { - let this = self.get_mut(); - let item = std::pin::Pin::new(&mut this.it).poll_next(cx); - match &item { - std::task::Poll::Ready(Some(_)) => this.progress.inc(1), - std::task::Poll::Ready(None) => this.progress.finish_using_style(), - std::task::Poll::Pending => {} - } - item - } -} - -impl<W: io::Write> io::Write for ProgressBarIter<W> { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.it.write(buf).map(|inc| { - self.progress.inc(inc as u64); - inc - }) - } - - fn write_vectored(&mut self, bufs: &[io::IoSlice]) -> io::Result<usize> { - self.it.write_vectored(bufs).map(|inc| { - self.progress.inc(inc as u64); - inc - }) - } - - fn flush(&mut self) -> io::Result<()> { - self.it.flush() - } - - // write_fmt can not be captured with reasonable effort. - // as it uses write_all internally by default that should not be a problem. - // fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()>; -} - -impl<S, T: Iterator<Item = S>> ProgressIterator for T { - fn progress_with(self, progress: ProgressBar) -> ProgressBarIter<Self> { - ProgressBarIter { it: self, progress } - } -} - -#[cfg(test)] -mod test { - use crate::iter::{ProgressBarIter, ProgressIterator}; - use crate::progress_bar::ProgressBar; - use crate::ProgressStyle; - - #[test] - fn it_can_wrap_an_iterator() { - let v = [1, 2, 3]; - let wrap = |it: ProgressBarIter<_>| { - assert_eq!(it.map(|x| x * 2).collect::<Vec<_>>(), vec![2, 4, 6]); - }; - - wrap(v.iter().progress()); - wrap(v.iter().progress_count(3)); - wrap({ - let pb = ProgressBar::new(v.len() as u64); - v.iter().progress_with(pb) - }); - wrap({ - let style = ProgressStyle::default_bar() - .template("{wide_bar:.red} {percent}/100%") - .unwrap(); - v.iter().progress_with_style(style) - }); - } -} diff --git a/vendor/indicatif/src/lib.rs b/vendor/indicatif/src/lib.rs deleted file mode 100644 index 6902ef6..0000000 --- a/vendor/indicatif/src/lib.rs +++ /dev/null @@ -1,247 +0,0 @@ -//! indicatif is a library for Rust that helps you build command line -//! interfaces that report progress to users. It comes with various -//! tools and utilities for formatting anything that indicates progress. -//! -//! Platform support: -//! -//! * Linux -//! * macOS -//! * Windows (colors require Windows 10) -//! -//! Best paired with other libraries in the family: -//! -//! * [console](https://docs.rs/console) -//! * [dialoguer](https://docs.rs/dialoguer) -//! -//! # Crate Contents -//! -//! * **Progress bars** -//! * [`ProgressBar`](struct.ProgressBar.html) for bars and spinners -//! * [`MultiProgress`](struct.MultiProgress.html) for multiple bars -//! * **Data Formatting** -//! * [`HumanBytes`](struct.HumanBytes.html) for formatting bytes -//! * [`DecimalBytes`](struct.DecimalBytes.html) for formatting bytes using SI prefixes -//! * [`BinaryBytes`](struct.BinaryBytes.html) for formatting bytes using ISO/IEC prefixes -//! * [`HumanDuration`](struct.HumanDuration.html) for formatting durations -//! * [`HumanCount`](struct.HumanCount.html) for formatting large counts -//! * [`HumanFloatCount`](struct.HumanFloatCount.html) for formatting large float counts -//! -//! # Progress Bars and Spinners -//! -//! indicatif comes with a `ProgressBar` type that supports both bounded -//! progress bar uses as well as unbounded "spinner" type progress reports. -//! Progress bars are `Sync` and `Send` objects which means that they are -//! internally locked and can be passed from thread to thread. -//! -//! Additionally a `MultiProgress` utility is provided that can manage -//! rendering multiple progress bars at once (eg: from multiple threads). -//! -//! To whet your appetite, this is what this can look like: -//! -//! <img src="https://github.com/console-rs/indicatif/raw/main/screenshots/yarn.gif?raw=true" width="60%"> -//! -//! Progress bars are manually advanced and by default draw to stderr. -//! When you are done, the progress bar can be finished either visibly -//! (eg: the progress bar stays on the screen) or cleared (the progress -//! bar will be removed). -//! -//! ```rust -//! use indicatif::ProgressBar; -//! -//! let bar = ProgressBar::new(1000); -//! for _ in 0..1000 { -//! bar.inc(1); -//! // ... -//! } -//! bar.finish(); -//! ``` -//! -//! General progress bar behaviors: -//! -//! * if a non terminal is detected the progress bar will be completely -//! hidden. This makes piping programs to logfiles make sense out of -//! the box. -//! * a progress bar only starts drawing when `set_message`, `inc`, `set_position` -//! or `tick` are called. In some situations you might have to call `tick` -//! once to draw it. -//! * progress bars should be explicitly finished to reset the rendering -//! for others. Either by also clearing them or by replacing them with -//! a new message / retaining the current message. -//! * the default template renders neither message nor prefix. -//! -//! # Iterators -//! -//! Similar to [tqdm](https://github.com/tqdm/tqdm), progress bars can be -//! associated with an iterator. For example: -//! -//! ```rust -//! use indicatif::ProgressIterator; -//! -//! for _ in (0..1000).progress() { -//! // ... -//! } -//! ``` -//! -//! See the [`ProgressIterator`](trait.ProgressIterator.html) trait for more -//! methods to configure the number of elements in the iterator or change -//! the progress bar style. Indicatif also has optional support for parallel -//! iterators with [Rayon](https://github.com/rayon-rs/rayon). In your -//! `Cargo.toml`, use the "rayon" feature: -//! -//! ```toml -//! [dependencies] -//! indicatif = {version = "*", features = ["rayon"]} -//! ``` -//! -//! And then use it like this: -//! -//! ```rust,ignore -//! # extern crate rayon; -//! use indicatif::ParallelProgressIterator; -//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator}; -//! -//! let v: Vec<_> = (0..100000).collect(); -//! let v2: Vec<_> = v.par_iter().progress_count(v.len() as u64).map(|i| i + 1).collect(); -//! assert_eq!(v2[0], 1); -//! ``` -//! -//! Or if you'd like to customize the progress bar: -//! -//! ```rust,ignore -//! # extern crate rayon; -//! use indicatif::{ProgressBar, ParallelProgressIterator, ProgressStyle}; -//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator}; -//! -//! // Alternatively, use `ProgressBar::new().with_style()` -//! let style = ProgressStyle::default_bar(); -//! let v: Vec<_> = (0..100000).collect(); -//! let v2: Vec<_> = v.par_iter().progress_with_style(style).map(|i| i + 1).collect(); -//! assert_eq!(v2[0], 1); -//! ``` -//! -//! # Templates -//! -//! Progress bars can be styled with simple format strings similar to the -//! ones in Rust itself. The format for a placeholder is `{key:options}` -//! where the `options` part is optional. If provided the format is this: -//! -//! ```text -//! <^> for an optional alignment specification (left, center and right respectively) -//! WIDTH an optional width as positive integer -//! ! an optional exclamation mark to enable truncation -//! .STYLE an optional dot separated style string -//! /STYLE an optional dot separated alternative style string -//! ``` -//! -//! For the style component see [`Style::from_dotted_str`](https://docs.rs/console/0.7.5/console/struct.Style.html#method.from_dotted_str) -//! for more information. Indicatif uses the `console` base crate for all -//! colorization and formatting options. -//! -//! Some examples for templates: -//! -//! ```text -//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg} -//! ``` -//! -//! This sets a progress bar that is 40 characters wide and has cyan -//! as primary style color and blue as alternative style color. -//! Alternative styles are currently only used for progress bars. -//! -//! Example configuration: -//! -//! ```rust -//! # use indicatif::{ProgressBar, ProgressStyle}; -//! # let bar = ProgressBar::new(0); -//! bar.set_style(ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}") -//! .unwrap() -//! .progress_chars("##-")); -//! ``` -//! -//! The following keys exist: -//! -//! * `bar`: renders a progress bar. By default 20 characters wide. The -//! style string is used to color the elapsed part, the alternative -//! style is used for the bar that is yet to render. -//! * `wide_bar`: like `bar` but always fills the remaining space. It should not be used with -//! `wide_msg`. -//! * `spinner`: renders the spinner (current tick string). -//! * `prefix`: renders the prefix set on the progress bar. -//! * `msg`: renders the currently set message on the progress bar. -//! * `wide_msg`: like `msg` but always fills the remaining space and truncates. It should not be used -//! with `wide_bar`. -//! * `pos`: renders the current position of the bar as integer -//! * `human_pos`: renders the current position of the bar as an integer, with commas as the -//! thousands separator. -//! * `len`: renders the amount of work to be done as an integer -//! * `human_len`: renders the total length of the bar as an integer, with commas as the thousands -//! separator. -//! * `bytes`: renders the current position of the bar as bytes. -//! * `percent`: renders the current position of the bar as a percentage of the total length. -//! * `total_bytes`: renders the total length of the bar as bytes. -//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`. -//! * `elapsed`: renders the elapsed time as `42s`, `1m` etc. -//! * `per_sec`: renders the speed in steps per second. -//! * `bytes_per_sec`: renders the speed in bytes per second. -//! * `binary_bytes_per_sec`: renders the speed in bytes per second using -//! power-of-two units, i.e. `MiB`, `KiB`, etc. -//! * `eta_precise`: the remaining time (like `elapsed_precise`). -//! * `eta`: the remaining time (like `elapsed`). -//! * `duration_precise`: the extrapolated total duration (like `elapsed_precise`). -//! * `duration`: the extrapolated total duration time (like `elapsed`). - -//! -//! The design of the progress bar can be altered with the integrated -//! template functionality. The template can be set by changing a -//! `ProgressStyle` and attaching it to the progress bar. -//! -//! # Human Readable Formatting -//! -//! There are some formatting wrappers for showing elapsed time and -//! file sizes for human users: -//! -//! ```rust -//! # use std::time::Duration; -//! use indicatif::{HumanBytes, HumanCount, HumanDuration, HumanFloatCount}; -//! -//! assert_eq!("3.00 MiB", HumanBytes(3*1024*1024).to_string()); -//! assert_eq!("8 seconds", HumanDuration(Duration::from_secs(8)).to_string()); -//! assert_eq!("33,857,009", HumanCount(33857009).to_string()); -//! assert_eq!("33,857,009.1235", HumanFloatCount(33857009.123456).to_string()); -//! ``` -//! -//! # Feature Flags -//! -//! * `rayon`: adds rayon support -//! * `improved_unicode`: adds improved unicode support (graphemes, better width calculation) - -#![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(unreachable_pub)] - -mod draw_target; -mod format; -#[cfg(feature = "in_memory")] -mod in_memory; -mod iter; -mod multi; -mod progress_bar; -#[cfg(feature = "rayon")] -mod rayon; -mod state; -pub mod style; -mod term_like; - -pub use crate::draw_target::ProgressDrawTarget; -pub use crate::format::{ - BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanCount, HumanDuration, - HumanFloatCount, -}; -#[cfg(feature = "in_memory")] -pub use crate::in_memory::InMemoryTerm; -pub use crate::iter::{ProgressBarIter, ProgressIterator}; -pub use crate::multi::{MultiProgress, MultiProgressAlignment}; -pub use crate::progress_bar::{ProgressBar, WeakProgressBar}; -#[cfg(feature = "rayon")] -pub use crate::rayon::ParallelProgressIterator; -pub use crate::state::{ProgressFinish, ProgressState}; -pub use crate::style::ProgressStyle; -pub use crate::term_like::TermLike; diff --git a/vendor/indicatif/src/multi.rs b/vendor/indicatif/src/multi.rs deleted file mode 100644 index 4409309..0000000 --- a/vendor/indicatif/src/multi.rs +++ /dev/null @@ -1,688 +0,0 @@ -use std::fmt::{Debug, Formatter}; -use std::io; -use std::sync::{Arc, RwLock}; -use std::thread::panicking; -#[cfg(not(target_arch = "wasm32"))] -use std::time::Instant; - -use crate::draw_target::{DrawState, DrawStateWrapper, LineAdjust, ProgressDrawTarget}; -use crate::progress_bar::ProgressBar; -#[cfg(target_arch = "wasm32")] -use instant::Instant; - -/// Manages multiple progress bars from different threads -#[derive(Debug, Clone)] -pub struct MultiProgress { - pub(crate) state: Arc<RwLock<MultiState>>, -} - -impl Default for MultiProgress { - fn default() -> Self { - Self::with_draw_target(ProgressDrawTarget::stderr()) - } -} - -impl MultiProgress { - /// Creates a new multi progress object. - /// - /// Progress bars added to this object by default draw directly to stderr, and refresh - /// a maximum of 15 times a second. To change the refresh rate set the draw target to - /// one with a different refresh rate. - pub fn new() -> Self { - Self::default() - } - - /// Creates a new multi progress object with the given draw target. - pub fn with_draw_target(draw_target: ProgressDrawTarget) -> Self { - Self { - state: Arc::new(RwLock::new(MultiState::new(draw_target))), - } - } - - /// Sets a different draw target for the multiprogress bar. - pub fn set_draw_target(&self, target: ProgressDrawTarget) { - let mut state = self.state.write().unwrap(); - state.draw_target.disconnect(Instant::now()); - state.draw_target = target; - } - - /// Set whether we should try to move the cursor when possible instead of clearing lines. - /// - /// This can reduce flickering, but do not enable it if you intend to change the number of - /// progress bars. - pub fn set_move_cursor(&self, move_cursor: bool) { - self.state.write().unwrap().move_cursor = move_cursor; - } - - /// Set alignment flag - pub fn set_alignment(&self, alignment: MultiProgressAlignment) { - self.state.write().unwrap().alignment = alignment; - } - - /// Adds a progress bar. - /// - /// The progress bar added will have the draw target changed to a - /// remote draw target that is intercepted by the multi progress - /// object overriding custom `ProgressDrawTarget` settings. - /// - /// Adding a progress bar that is already a member of the `MultiProgress` - /// will have no effect. - pub fn add(&self, pb: ProgressBar) -> ProgressBar { - self.internalize(InsertLocation::End, pb) - } - - /// Inserts a progress bar. - /// - /// The progress bar inserted at position `index` will have the draw - /// target changed to a remote draw target that is intercepted by the - /// multi progress object overriding custom `ProgressDrawTarget` settings. - /// - /// If `index >= MultiProgressState::objects.len()`, the progress bar - /// is added to the end of the list. - /// - /// Inserting a progress bar that is already a member of the `MultiProgress` - /// will have no effect. - pub fn insert(&self, index: usize, pb: ProgressBar) -> ProgressBar { - self.internalize(InsertLocation::Index(index), pb) - } - - /// Inserts a progress bar from the back. - /// - /// The progress bar inserted at position `MultiProgressState::objects.len() - index` - /// will have the draw target changed to a remote draw target that is - /// intercepted by the multi progress object overriding custom - /// `ProgressDrawTarget` settings. - /// - /// If `index >= MultiProgressState::objects.len()`, the progress bar - /// is added to the start of the list. - /// - /// Inserting a progress bar that is already a member of the `MultiProgress` - /// will have no effect. - pub fn insert_from_back(&self, index: usize, pb: ProgressBar) -> ProgressBar { - self.internalize(InsertLocation::IndexFromBack(index), pb) - } - - /// Inserts a progress bar before an existing one. - /// - /// The progress bar added will have the draw target changed to a - /// remote draw target that is intercepted by the multi progress - /// object overriding custom `ProgressDrawTarget` settings. - /// - /// Inserting a progress bar that is already a member of the `MultiProgress` - /// will have no effect. - pub fn insert_before(&self, before: &ProgressBar, pb: ProgressBar) -> ProgressBar { - self.internalize(InsertLocation::Before(before.index().unwrap()), pb) - } - - /// Inserts a progress bar after an existing one. - /// - /// The progress bar added will have the draw target changed to a - /// remote draw target that is intercepted by the multi progress - /// object overriding custom `ProgressDrawTarget` settings. - /// - /// Inserting a progress bar that is already a member of the `MultiProgress` - /// will have no effect. - pub fn insert_after(&self, after: &ProgressBar, pb: ProgressBar) -> ProgressBar { - self.internalize(InsertLocation::After(after.index().unwrap()), pb) - } - - /// Removes a progress bar. - /// - /// The progress bar is removed only if it was previously inserted or added - /// by the methods `MultiProgress::insert` or `MultiProgress::add`. - /// If the passed progress bar does not satisfy the condition above, - /// the `remove` method does nothing. - pub fn remove(&self, pb: &ProgressBar) { - let mut state = pb.state(); - let idx = match &state.draw_target.remote() { - Some((state, idx)) => { - // Check that this progress bar is owned by the current MultiProgress. - assert!(Arc::ptr_eq(&self.state, state)); - *idx - } - _ => return, - }; - - state.draw_target = ProgressDrawTarget::hidden(); - self.state.write().unwrap().remove_idx(idx); - } - - fn internalize(&self, location: InsertLocation, pb: ProgressBar) -> ProgressBar { - let mut state = self.state.write().unwrap(); - let idx = state.insert(location); - drop(state); - - pb.set_draw_target(ProgressDrawTarget::new_remote(self.state.clone(), idx)); - pb - } - - /// Print a log line above all progress bars in the [`MultiProgress`] - /// - /// If the draw target is hidden (e.g. when standard output is not a terminal), `println()` - /// will not do anything. - pub fn println<I: AsRef<str>>(&self, msg: I) -> io::Result<()> { - let mut state = self.state.write().unwrap(); - state.println(msg, Instant::now()) - } - - /// Hide all progress bars temporarily, execute `f`, then redraw the [`MultiProgress`] - /// - /// Executes 'f' even if the draw target is hidden. - /// - /// Useful for external code that writes to the standard output. - /// - /// **Note:** The internal lock is held while `f` is executed. Other threads trying to print - /// anything on the progress bar will be blocked until `f` finishes. - /// Therefore, it is recommended to avoid long-running operations in `f`. - pub fn suspend<F: FnOnce() -> R, R>(&self, f: F) -> R { - let mut state = self.state.write().unwrap(); - state.suspend(f, Instant::now()) - } - - pub fn clear(&self) -> io::Result<()> { - self.state.write().unwrap().clear(Instant::now()) - } - - pub fn is_hidden(&self) -> bool { - self.state.read().unwrap().is_hidden() - } -} - -#[derive(Debug)] -pub(crate) struct MultiState { - /// The collection of states corresponding to progress bars - members: Vec<MultiStateMember>, - /// Set of removed bars, should have corresponding members in the `members` vector with a - /// `draw_state` of `None`. - free_set: Vec<usize>, - /// Indices to the `draw_states` to maintain correct visual order - ordering: Vec<usize>, - /// Target for draw operation for MultiProgress - draw_target: ProgressDrawTarget, - /// Whether or not to just move cursor instead of clearing lines - move_cursor: bool, - /// Controls how the multi progress is aligned if some of its progress bars get removed, default is `Top` - alignment: MultiProgressAlignment, - /// Lines to be drawn above everything else in the MultiProgress. These specifically come from - /// calling `ProgressBar::println` on a pb that is connected to a `MultiProgress`. - orphan_lines: Vec<String>, - /// The count of currently visible zombie lines. - zombie_lines_count: usize, -} - -impl MultiState { - fn new(draw_target: ProgressDrawTarget) -> Self { - Self { - members: vec![], - free_set: vec![], - ordering: vec![], - draw_target, - move_cursor: false, - alignment: MultiProgressAlignment::default(), - orphan_lines: Vec::new(), - zombie_lines_count: 0, - } - } - - pub(crate) fn mark_zombie(&mut self, index: usize) { - let member = &mut self.members[index]; - - // If the zombie is the first visual bar then we can reap it right now instead of - // deferring it to the next draw. - if index != self.ordering.first().copied().unwrap() { - member.is_zombie = true; - return; - } - - let line_count = member - .draw_state - .as_ref() - .map(|d| d.lines.len()) - .unwrap_or_default(); - - // Track the total number of zombie lines on the screen - self.zombie_lines_count = self.zombie_lines_count.saturating_add(line_count); - - // Make `DrawTarget` forget about the zombie lines so that they aren't cleared on next draw. - self.draw_target - .adjust_last_line_count(LineAdjust::Keep(line_count)); - - self.remove_idx(index); - } - - pub(crate) fn draw( - &mut self, - mut force_draw: bool, - extra_lines: Option<Vec<String>>, - now: Instant, - ) -> io::Result<()> { - if panicking() { - return Ok(()); - } - let width = self.width() as f64; - // Calculate real length based on terminal width - // This take in account linewrap from terminal - fn real_len(lines: &[String], width: f64) -> usize { - lines.iter().fold(0, |sum, val| { - sum + (console::measure_text_width(val) as f64 / width).ceil() as usize - }) - } - - // Assumption: if extra_lines is not None, then it has at least one line - debug_assert_eq!( - extra_lines.is_some(), - extra_lines.as_ref().map(Vec::len).unwrap_or_default() > 0 - ); - - let mut reap_indices = vec![]; - - // Reap all consecutive 'zombie' progress bars from head of the list. - let mut adjust = 0; - for &index in &self.ordering { - let member = &self.members[index]; - if !member.is_zombie { - break; - } - - let line_count = member - .draw_state - .as_ref() - .map(|d| real_len(&d.lines, width)) - .unwrap_or_default(); - // Track the total number of zombie lines on the screen. - self.zombie_lines_count += line_count; - - // Track the number of zombie lines that will be drawn by this call to draw. - adjust += line_count; - - reap_indices.push(index); - } - - // If this draw is due to a `println`, then we need to erase all the zombie lines. - // This is because `println` is supposed to appear above all other elements in the - // `MultiProgress`. - if extra_lines.is_some() { - self.draw_target - .adjust_last_line_count(LineAdjust::Clear(self.zombie_lines_count)); - self.zombie_lines_count = 0; - } - - let orphan_lines_count = real_len(&self.orphan_lines, width); - force_draw |= orphan_lines_count > 0; - let mut drawable = match self.draw_target.drawable(force_draw, now) { - Some(drawable) => drawable, - None => return Ok(()), - }; - - let mut draw_state = drawable.state(); - draw_state.orphan_lines_count = orphan_lines_count; - draw_state.alignment = self.alignment; - - if let Some(extra_lines) = &extra_lines { - draw_state.lines.extend_from_slice(extra_lines.as_slice()); - draw_state.orphan_lines_count += real_len(extra_lines, width); - } - - // Add lines from `ProgressBar::println` call. - draw_state.lines.append(&mut self.orphan_lines); - - for index in &self.ordering { - let member = &self.members[*index]; - if let Some(state) = &member.draw_state { - draw_state.lines.extend_from_slice(&state.lines[..]); - } - } - - drop(draw_state); - let drawable = drawable.draw(); - - for index in reap_indices { - self.remove_idx(index); - } - - // The zombie lines were drawn for the last time, so make `DrawTarget` forget about them - // so they aren't cleared on next draw. - if extra_lines.is_none() { - self.draw_target - .adjust_last_line_count(LineAdjust::Keep(adjust)); - } - - drawable - } - - pub(crate) fn println<I: AsRef<str>>(&mut self, msg: I, now: Instant) -> io::Result<()> { - let msg = msg.as_ref(); - - // If msg is "", make sure a line is still printed - let lines: Vec<String> = match msg.is_empty() { - false => msg.lines().map(Into::into).collect(), - true => vec![String::new()], - }; - - self.draw(true, Some(lines), now) - } - - pub(crate) fn draw_state(&mut self, idx: usize) -> DrawStateWrapper<'_> { - let member = self.members.get_mut(idx).unwrap(); - // alignment is handled by the `MultiProgress`'s underlying draw target, so there is no - // point in propagating it here. - let state = member.draw_state.get_or_insert(DrawState { - move_cursor: self.move_cursor, - ..Default::default() - }); - - DrawStateWrapper::for_multi(state, &mut self.orphan_lines) - } - - pub(crate) fn is_hidden(&self) -> bool { - self.draw_target.is_hidden() - } - - pub(crate) fn suspend<F: FnOnce() -> R, R>(&mut self, f: F, now: Instant) -> R { - self.clear(now).unwrap(); - let ret = f(); - self.draw(true, None, Instant::now()).unwrap(); - ret - } - - pub(crate) fn width(&self) -> u16 { - self.draw_target.width() - } - - fn insert(&mut self, location: InsertLocation) -> usize { - let idx = if let Some(idx) = self.free_set.pop() { - self.members[idx] = MultiStateMember::default(); - idx - } else { - self.members.push(MultiStateMember::default()); - self.members.len() - 1 - }; - - match location { - InsertLocation::End => self.ordering.push(idx), - InsertLocation::Index(pos) => { - let pos = Ord::min(pos, self.ordering.len()); - self.ordering.insert(pos, idx); - } - InsertLocation::IndexFromBack(pos) => { - let pos = self.ordering.len().saturating_sub(pos); - self.ordering.insert(pos, idx); - } - InsertLocation::After(after_idx) => { - let pos = self.ordering.iter().position(|i| *i == after_idx).unwrap(); - self.ordering.insert(pos + 1, idx); - } - InsertLocation::Before(before_idx) => { - let pos = self.ordering.iter().position(|i| *i == before_idx).unwrap(); - self.ordering.insert(pos, idx); - } - } - - assert_eq!( - self.len(), - self.ordering.len(), - "Draw state is inconsistent" - ); - - idx - } - - fn clear(&mut self, now: Instant) -> io::Result<()> { - match self.draw_target.drawable(true, now) { - Some(mut drawable) => { - // Make the clear operation also wipe out zombie lines - drawable.adjust_last_line_count(LineAdjust::Clear(self.zombie_lines_count)); - self.zombie_lines_count = 0; - drawable.clear() - } - None => Ok(()), - } - } - - fn remove_idx(&mut self, idx: usize) { - if self.free_set.contains(&idx) { - return; - } - - self.members[idx] = MultiStateMember::default(); - self.free_set.push(idx); - self.ordering.retain(|&x| x != idx); - - assert_eq!( - self.len(), - self.ordering.len(), - "Draw state is inconsistent" - ); - } - - fn len(&self) -> usize { - self.members.len() - self.free_set.len() - } -} - -#[derive(Default)] -struct MultiStateMember { - /// Draw state will be `None` for members that haven't been drawn before, or for entries that - /// correspond to something in the free set. - draw_state: Option<DrawState>, - /// Whether the corresponding progress bar (more precisely, `BarState`) has been dropped. - is_zombie: bool, -} - -impl Debug for MultiStateMember { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("MultiStateElement") - .field("draw_state", &self.draw_state) - .field("is_zombie", &self.is_zombie) - .finish_non_exhaustive() - } -} - -/// Vertical alignment of a multi progress. -/// -/// The alignment controls how the multi progress is aligned if some of its progress bars get removed. -/// E.g. `Top` alignment (default), when _progress bar 2_ is removed: -/// ```ignore -/// [0/100] progress bar 1 [0/100] progress bar 1 -/// [0/100] progress bar 2 => [0/100] progress bar 3 -/// [0/100] progress bar 3 -/// ``` -/// -/// `Bottom` alignment -/// ```ignore -/// [0/100] progress bar 1 -/// [0/100] progress bar 2 => [0/100] progress bar 1 -/// [0/100] progress bar 3 [0/100] progress bar 3 -/// ``` -#[derive(Debug, Copy, Clone)] -pub enum MultiProgressAlignment { - Top, - Bottom, -} - -impl Default for MultiProgressAlignment { - fn default() -> Self { - Self::Top - } -} - -enum InsertLocation { - End, - Index(usize), - IndexFromBack(usize), - After(usize), - Before(usize), -} - -#[cfg(test)] -mod tests { - use crate::{MultiProgress, ProgressBar, ProgressDrawTarget}; - - #[test] - fn late_pb_drop() { - let pb = ProgressBar::new(10); - let mpb = MultiProgress::new(); - // This clone call is required to trigger a now fixed bug. - // See <https://github.com/console-rs/indicatif/pull/141> for context - #[allow(clippy::redundant_clone)] - mpb.add(pb.clone()); - } - - #[test] - fn progress_bar_sync_send() { - let _: Box<dyn Sync> = Box::new(ProgressBar::new(1)); - let _: Box<dyn Send> = Box::new(ProgressBar::new(1)); - let _: Box<dyn Sync> = Box::new(MultiProgress::new()); - let _: Box<dyn Send> = Box::new(MultiProgress::new()); - } - - #[test] - fn multi_progress_hidden() { - let mpb = MultiProgress::with_draw_target(ProgressDrawTarget::hidden()); - let pb = mpb.add(ProgressBar::new(123)); - pb.finish(); - } - - #[test] - fn multi_progress_modifications() { - let mp = MultiProgress::new(); - let p0 = mp.add(ProgressBar::new(1)); - let p1 = mp.add(ProgressBar::new(1)); - let p2 = mp.add(ProgressBar::new(1)); - let p3 = mp.add(ProgressBar::new(1)); - mp.remove(&p2); - mp.remove(&p1); - let p4 = mp.insert(1, ProgressBar::new(1)); - - let state = mp.state.read().unwrap(); - // the removed place for p1 is reused - assert_eq!(state.members.len(), 4); - assert_eq!(state.len(), 3); - - // free_set may contain 1 or 2 - match state.free_set.last() { - Some(1) => { - assert_eq!(state.ordering, vec![0, 2, 3]); - assert!(state.members[1].draw_state.is_none()); - assert_eq!(p4.index().unwrap(), 2); - } - Some(2) => { - assert_eq!(state.ordering, vec![0, 1, 3]); - assert!(state.members[2].draw_state.is_none()); - assert_eq!(p4.index().unwrap(), 1); - } - _ => unreachable!(), - } - - assert_eq!(p0.index().unwrap(), 0); - assert_eq!(p1.index(), None); - assert_eq!(p2.index(), None); - assert_eq!(p3.index().unwrap(), 3); - } - - #[test] - fn multi_progress_insert_from_back() { - let mp = MultiProgress::new(); - let p0 = mp.add(ProgressBar::new(1)); - let p1 = mp.add(ProgressBar::new(1)); - let p2 = mp.add(ProgressBar::new(1)); - let p3 = mp.insert_from_back(1, ProgressBar::new(1)); - let p4 = mp.insert_from_back(10, ProgressBar::new(1)); - - let state = mp.state.read().unwrap(); - assert_eq!(state.ordering, vec![4, 0, 1, 3, 2]); - assert_eq!(p0.index().unwrap(), 0); - assert_eq!(p1.index().unwrap(), 1); - assert_eq!(p2.index().unwrap(), 2); - assert_eq!(p3.index().unwrap(), 3); - assert_eq!(p4.index().unwrap(), 4); - } - - #[test] - fn multi_progress_insert_after() { - let mp = MultiProgress::new(); - let p0 = mp.add(ProgressBar::new(1)); - let p1 = mp.add(ProgressBar::new(1)); - let p2 = mp.add(ProgressBar::new(1)); - let p3 = mp.insert_after(&p2, ProgressBar::new(1)); - let p4 = mp.insert_after(&p0, ProgressBar::new(1)); - - let state = mp.state.read().unwrap(); - assert_eq!(state.ordering, vec![0, 4, 1, 2, 3]); - assert_eq!(p0.index().unwrap(), 0); - assert_eq!(p1.index().unwrap(), 1); - assert_eq!(p2.index().unwrap(), 2); - assert_eq!(p3.index().unwrap(), 3); - assert_eq!(p4.index().unwrap(), 4); - } - - #[test] - fn multi_progress_insert_before() { - let mp = MultiProgress::new(); - let p0 = mp.add(ProgressBar::new(1)); - let p1 = mp.add(ProgressBar::new(1)); - let p2 = mp.add(ProgressBar::new(1)); - let p3 = mp.insert_before(&p0, ProgressBar::new(1)); - let p4 = mp.insert_before(&p2, ProgressBar::new(1)); - - let state = mp.state.read().unwrap(); - assert_eq!(state.ordering, vec![3, 0, 1, 4, 2]); - assert_eq!(p0.index().unwrap(), 0); - assert_eq!(p1.index().unwrap(), 1); - assert_eq!(p2.index().unwrap(), 2); - assert_eq!(p3.index().unwrap(), 3); - assert_eq!(p4.index().unwrap(), 4); - } - - #[test] - fn multi_progress_insert_before_and_after() { - let mp = MultiProgress::new(); - let p0 = mp.add(ProgressBar::new(1)); - let p1 = mp.add(ProgressBar::new(1)); - let p2 = mp.add(ProgressBar::new(1)); - let p3 = mp.insert_before(&p0, ProgressBar::new(1)); - let p4 = mp.insert_after(&p3, ProgressBar::new(1)); - let p5 = mp.insert_after(&p3, ProgressBar::new(1)); - let p6 = mp.insert_before(&p1, ProgressBar::new(1)); - - let state = mp.state.read().unwrap(); - assert_eq!(state.ordering, vec![3, 5, 4, 0, 6, 1, 2]); - assert_eq!(p0.index().unwrap(), 0); - assert_eq!(p1.index().unwrap(), 1); - assert_eq!(p2.index().unwrap(), 2); - assert_eq!(p3.index().unwrap(), 3); - assert_eq!(p4.index().unwrap(), 4); - assert_eq!(p5.index().unwrap(), 5); - assert_eq!(p6.index().unwrap(), 6); - } - - #[test] - fn multi_progress_multiple_remove() { - let mp = MultiProgress::new(); - let p0 = mp.add(ProgressBar::new(1)); - let p1 = mp.add(ProgressBar::new(1)); - // double remove beyond the first one have no effect - mp.remove(&p0); - mp.remove(&p0); - mp.remove(&p0); - - let state = mp.state.read().unwrap(); - // the removed place for p1 is reused - assert_eq!(state.members.len(), 2); - assert_eq!(state.free_set.len(), 1); - assert_eq!(state.len(), 1); - assert!(state.members[0].draw_state.is_none()); - assert_eq!(state.free_set.last(), Some(&0)); - - assert_eq!(state.ordering, vec![1]); - assert_eq!(p0.index(), None); - assert_eq!(p1.index().unwrap(), 1); - } - - #[test] - fn mp_no_crash_double_add() { - let mp = MultiProgress::new(); - let pb = mp.add(ProgressBar::new(10)); - mp.add(pb); - } -} diff --git a/vendor/indicatif/src/progress_bar.rs b/vendor/indicatif/src/progress_bar.rs deleted file mode 100644 index 938668e..0000000 --- a/vendor/indicatif/src/progress_bar.rs +++ /dev/null @@ -1,808 +0,0 @@ -#[cfg(test)] -use portable_atomic::{AtomicBool, Ordering}; -use std::borrow::Cow; -use std::sync::{Arc, Condvar, Mutex, MutexGuard, Weak}; -use std::time::Duration; -#[cfg(not(target_arch = "wasm32"))] -use std::time::Instant; -use std::{fmt, io, thread}; - -#[cfg(target_arch = "wasm32")] -use instant::Instant; -#[cfg(test)] -use once_cell::sync::Lazy; - -use crate::draw_target::ProgressDrawTarget; -use crate::state::{AtomicPosition, BarState, ProgressFinish, Reset, TabExpandedString}; -use crate::style::ProgressStyle; -use crate::{ProgressBarIter, ProgressIterator, ProgressState}; - -/// A progress bar or spinner -/// -/// The progress bar is an [`Arc`] around its internal state. When the progress bar is cloned it -/// just increments the refcount (so the original and its clone share the same state). -#[derive(Clone)] -pub struct ProgressBar { - state: Arc<Mutex<BarState>>, - pos: Arc<AtomicPosition>, - ticker: Arc<Mutex<Option<Ticker>>>, -} - -impl fmt::Debug for ProgressBar { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ProgressBar").finish() - } -} - -impl ProgressBar { - /// Creates a new progress bar with a given length - /// - /// This progress bar by default draws directly to stderr, and refreshes a maximum of 15 times - /// a second. To change the refresh rate, set the draw target to one with a different refresh - /// rate. - pub fn new(len: u64) -> Self { - Self::with_draw_target(Some(len), ProgressDrawTarget::stderr()) - } - - /// Creates a completely hidden progress bar - /// - /// This progress bar still responds to API changes but it does not have a length or render in - /// any way. - pub fn hidden() -> Self { - Self::with_draw_target(None, ProgressDrawTarget::hidden()) - } - - /// Creates a new progress bar with a given length and draw target - pub fn with_draw_target(len: Option<u64>, draw_target: ProgressDrawTarget) -> Self { - let pos = Arc::new(AtomicPosition::new()); - Self { - state: Arc::new(Mutex::new(BarState::new(len, draw_target, pos.clone()))), - pos, - ticker: Arc::new(Mutex::new(None)), - } - } - - /// Get a clone of the current progress bar style. - pub fn style(&self) -> ProgressStyle { - self.state().style.clone() - } - - /// A convenience builder-like function for a progress bar with a given style - pub fn with_style(self, style: ProgressStyle) -> Self { - self.set_style(style); - self - } - - /// A convenience builder-like function for a progress bar with a given tab width - pub fn with_tab_width(self, tab_width: usize) -> Self { - self.state().set_tab_width(tab_width); - self - } - - /// A convenience builder-like function for a progress bar with a given prefix - /// - /// For the prefix to be visible, the `{prefix}` placeholder must be present in the template - /// (see [`ProgressStyle`]). - pub fn with_prefix(self, prefix: impl Into<Cow<'static, str>>) -> Self { - let mut state = self.state(); - state.state.prefix = TabExpandedString::new(prefix.into(), state.tab_width); - drop(state); - self - } - - /// A convenience builder-like function for a progress bar with a given message - /// - /// For the message to be visible, the `{msg}` placeholder must be present in the template (see - /// [`ProgressStyle`]). - pub fn with_message(self, message: impl Into<Cow<'static, str>>) -> Self { - let mut state = self.state(); - state.state.message = TabExpandedString::new(message.into(), state.tab_width); - drop(state); - self - } - - /// A convenience builder-like function for a progress bar with a given position - pub fn with_position(self, pos: u64) -> Self { - self.state().state.set_pos(pos); - self - } - - /// A convenience builder-like function for a progress bar with a given elapsed time - pub fn with_elapsed(self, elapsed: Duration) -> Self { - self.state().state.started = Instant::now().checked_sub(elapsed).unwrap(); - self - } - - /// Sets the finish behavior for the progress bar - /// - /// This behavior is invoked when [`ProgressBar`] or - /// [`ProgressBarIter`] completes and - /// [`ProgressBar::is_finished()`] is false. - /// If you don't want the progress bar to be automatically finished then - /// call `on_finish(None)`. - /// - /// [`ProgressBar`]: crate::ProgressBar - /// [`ProgressBarIter`]: crate::ProgressBarIter - /// [`ProgressBar::is_finished()`]: crate::ProgressBar::is_finished - pub fn with_finish(self, finish: ProgressFinish) -> Self { - self.state().on_finish = finish; - self - } - - /// Creates a new spinner - /// - /// This spinner by default draws directly to stderr. This adds the default spinner style to it. - pub fn new_spinner() -> Self { - let rv = Self::with_draw_target(None, ProgressDrawTarget::stderr()); - rv.set_style(ProgressStyle::default_spinner()); - rv - } - - /// Overrides the stored style - /// - /// This does not redraw the bar. Call [`ProgressBar::tick()`] to force it. - pub fn set_style(&self, style: ProgressStyle) { - self.state().set_style(style); - } - - /// Sets the tab width (default: 8). All tabs will be expanded to this many spaces. - pub fn set_tab_width(&mut self, tab_width: usize) { - let mut state = self.state(); - state.set_tab_width(tab_width); - state.draw(true, Instant::now()).unwrap(); - } - - /// Spawns a background thread to tick the progress bar - /// - /// When this is enabled a background thread will regularly tick the progress bar in the given - /// interval. This is useful to advance progress bars that are very slow by themselves. - /// - /// When steady ticks are enabled, calling [`ProgressBar::tick()`] on a progress bar does not - /// have any effect. - pub fn enable_steady_tick(&self, interval: Duration) { - // The way we test for ticker termination is with a single static `AtomicBool`. Since cargo - // runs tests concurrently, we have a `TICKER_TEST` lock to make sure tests using ticker - // don't step on each other. This check catches attempts to use tickers in tests without - // acquiring the lock. - #[cfg(test)] - { - let guard = TICKER_TEST.try_lock(); - let lock_acquired = guard.is_ok(); - // Drop the guard before panicking to avoid poisoning the lock (which would cause other - // ticker tests to fail) - drop(guard); - if lock_acquired { - panic!("you must acquire the TICKER_TEST lock in your test to use this method"); - } - } - - if interval.is_zero() { - return; - } - - self.stop_and_replace_ticker(Some(interval)); - } - - /// Undoes [`ProgressBar::enable_steady_tick()`] - pub fn disable_steady_tick(&self) { - self.stop_and_replace_ticker(None); - } - - fn stop_and_replace_ticker(&self, interval: Option<Duration>) { - let mut ticker_state = self.ticker.lock().unwrap(); - if let Some(ticker) = ticker_state.take() { - ticker.stop(); - } - - *ticker_state = interval.map(|interval| Ticker::new(interval, &self.state)); - } - - /// Manually ticks the spinner or progress bar - /// - /// This automatically happens on any other change to a progress bar. - pub fn tick(&self) { - self.tick_inner(Instant::now()); - } - - fn tick_inner(&self, now: Instant) { - // Only tick if a `Ticker` isn't installed - if self.ticker.lock().unwrap().is_none() { - self.state().tick(now); - } - } - - /// Advances the position of the progress bar by `delta` - pub fn inc(&self, delta: u64) { - self.pos.inc(delta); - let now = Instant::now(); - if self.pos.allow(now) { - self.tick_inner(now); - } - } - - /// A quick convenience check if the progress bar is hidden - pub fn is_hidden(&self) -> bool { - self.state().draw_target.is_hidden() - } - - /// Indicates that the progress bar finished - pub fn is_finished(&self) -> bool { - self.state().state.is_finished() - } - - /// Print a log line above the progress bar - /// - /// If the progress bar is hidden (e.g. when standard output is not a terminal), `println()` - /// will not do anything. If you want to write to the standard output in such cases as well, use - /// [`suspend`] instead. - /// - /// If the progress bar was added to a [`MultiProgress`], the log line will be - /// printed above all other progress bars. - /// - /// [`suspend`]: ProgressBar::suspend - /// [`MultiProgress`]: crate::MultiProgress - pub fn println<I: AsRef<str>>(&self, msg: I) { - self.state().println(Instant::now(), msg.as_ref()); - } - - /// Update the `ProgressBar`'s inner [`ProgressState`] - pub fn update(&self, f: impl FnOnce(&mut ProgressState)) { - self.state() - .update(Instant::now(), f, self.ticker.lock().unwrap().is_none()); - } - - /// Sets the position of the progress bar - pub fn set_position(&self, pos: u64) { - self.pos.set(pos); - let now = Instant::now(); - if self.pos.allow(now) { - self.tick_inner(now); - } - } - - /// Sets the length of the progress bar - pub fn set_length(&self, len: u64) { - self.state().set_length(Instant::now(), len); - } - - /// Increase the length of the progress bar - pub fn inc_length(&self, delta: u64) { - self.state().inc_length(Instant::now(), delta); - } - - /// Sets the current prefix of the progress bar - /// - /// For the prefix to be visible, the `{prefix}` placeholder must be present in the template - /// (see [`ProgressStyle`]). - pub fn set_prefix(&self, prefix: impl Into<Cow<'static, str>>) { - let mut state = self.state(); - state.state.prefix = TabExpandedString::new(prefix.into(), state.tab_width); - state.update_estimate_and_draw(Instant::now()); - } - - /// Sets the current message of the progress bar - /// - /// For the message to be visible, the `{msg}` placeholder must be present in the template (see - /// [`ProgressStyle`]). - pub fn set_message(&self, msg: impl Into<Cow<'static, str>>) { - let mut state = self.state(); - state.state.message = TabExpandedString::new(msg.into(), state.tab_width); - state.update_estimate_and_draw(Instant::now()); - } - - /// Creates a new weak reference to this `ProgressBar` - pub fn downgrade(&self) -> WeakProgressBar { - WeakProgressBar { - state: Arc::downgrade(&self.state), - pos: Arc::downgrade(&self.pos), - ticker: Arc::downgrade(&self.ticker), - } - } - - /// Resets the ETA calculation - /// - /// This can be useful if the progress bars made a large jump or was paused for a prolonged - /// time. - pub fn reset_eta(&self) { - self.state().reset(Instant::now(), Reset::Eta); - } - - /// Resets elapsed time and the ETA calculation - pub fn reset_elapsed(&self) { - self.state().reset(Instant::now(), Reset::Elapsed); - } - - /// Resets all of the progress bar state - pub fn reset(&self) { - self.state().reset(Instant::now(), Reset::All); - } - - /// Finishes the progress bar and leaves the current message - pub fn finish(&self) { - self.state() - .finish_using_style(Instant::now(), ProgressFinish::AndLeave); - } - - /// Finishes the progress bar and sets a message - /// - /// For the message to be visible, the `{msg}` placeholder must be present in the template (see - /// [`ProgressStyle`]). - pub fn finish_with_message(&self, msg: impl Into<Cow<'static, str>>) { - self.state() - .finish_using_style(Instant::now(), ProgressFinish::WithMessage(msg.into())); - } - - /// Finishes the progress bar and completely clears it - pub fn finish_and_clear(&self) { - self.state() - .finish_using_style(Instant::now(), ProgressFinish::AndClear); - } - - /// Finishes the progress bar and leaves the current message and progress - pub fn abandon(&self) { - self.state() - .finish_using_style(Instant::now(), ProgressFinish::Abandon); - } - - /// Finishes the progress bar and sets a message, and leaves the current progress - /// - /// For the message to be visible, the `{msg}` placeholder must be present in the template (see - /// [`ProgressStyle`]). - pub fn abandon_with_message(&self, msg: impl Into<Cow<'static, str>>) { - self.state().finish_using_style( - Instant::now(), - ProgressFinish::AbandonWithMessage(msg.into()), - ); - } - - /// Finishes the progress bar using the behavior stored in the [`ProgressStyle`] - /// - /// See [`ProgressBar::with_finish()`]. - pub fn finish_using_style(&self) { - let mut state = self.state(); - let finish = state.on_finish.clone(); - state.finish_using_style(Instant::now(), finish); - } - - /// Sets a different draw target for the progress bar - /// - /// This can be used to draw the progress bar to stderr (this is the default): - /// - /// ```rust,no_run - /// # use indicatif::{ProgressBar, ProgressDrawTarget}; - /// let pb = ProgressBar::new(100); - /// pb.set_draw_target(ProgressDrawTarget::stderr()); - /// ``` - /// - /// **Note:** Calling this method on a [`ProgressBar`] linked with a [`MultiProgress`] (after - /// running [`MultiProgress::add`]) will unlink this progress bar. If you don't want this - /// behavior, call [`MultiProgress::set_draw_target`] instead. - /// - /// [`MultiProgress`]: crate::MultiProgress - /// [`MultiProgress::add`]: crate::MultiProgress::add - /// [`MultiProgress::set_draw_target`]: crate::MultiProgress::set_draw_target - pub fn set_draw_target(&self, target: ProgressDrawTarget) { - let mut state = self.state(); - state.draw_target.disconnect(Instant::now()); - state.draw_target = target; - } - - /// Hide the progress bar temporarily, execute `f`, then redraw the progress bar - /// - /// Useful for external code that writes to the standard output. - /// - /// If the progress bar was added to a MultiProgress, it will suspend the entire MultiProgress - /// - /// **Note:** The internal lock is held while `f` is executed. Other threads trying to print - /// anything on the progress bar will be blocked until `f` finishes. - /// Therefore, it is recommended to avoid long-running operations in `f`. - /// - /// ```rust,no_run - /// # use indicatif::ProgressBar; - /// let mut pb = ProgressBar::new(3); - /// pb.suspend(|| { - /// println!("Log message"); - /// }) - /// ``` - pub fn suspend<F: FnOnce() -> R, R>(&self, f: F) -> R { - self.state().suspend(Instant::now(), f) - } - - /// Wraps an [`Iterator`] with the progress bar - /// - /// ```rust,no_run - /// # use indicatif::ProgressBar; - /// let v = vec![1, 2, 3]; - /// let pb = ProgressBar::new(3); - /// for item in pb.wrap_iter(v.iter()) { - /// // ... - /// } - /// ``` - pub fn wrap_iter<It: Iterator>(&self, it: It) -> ProgressBarIter<It> { - it.progress_with(self.clone()) - } - - /// Wraps an [`io::Read`] with the progress bar - /// - /// ```rust,no_run - /// # use std::fs::File; - /// # use std::io; - /// # use indicatif::ProgressBar; - /// # fn test () -> io::Result<()> { - /// let source = File::open("work.txt")?; - /// let mut target = File::create("done.txt")?; - /// let pb = ProgressBar::new(source.metadata()?.len()); - /// io::copy(&mut pb.wrap_read(source), &mut target); - /// # Ok(()) - /// # } - /// ``` - pub fn wrap_read<R: io::Read>(&self, read: R) -> ProgressBarIter<R> { - ProgressBarIter { - progress: self.clone(), - it: read, - } - } - - /// Wraps an [`io::Write`] with the progress bar - /// - /// ```rust,no_run - /// # use std::fs::File; - /// # use std::io; - /// # use indicatif::ProgressBar; - /// # fn test () -> io::Result<()> { - /// let mut source = File::open("work.txt")?; - /// let target = File::create("done.txt")?; - /// let pb = ProgressBar::new(source.metadata()?.len()); - /// io::copy(&mut source, &mut pb.wrap_write(target)); - /// # Ok(()) - /// # } - /// ``` - pub fn wrap_write<W: io::Write>(&self, write: W) -> ProgressBarIter<W> { - ProgressBarIter { - progress: self.clone(), - it: write, - } - } - - #[cfg(feature = "tokio")] - #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] - /// Wraps an [`tokio::io::AsyncWrite`] with the progress bar - /// - /// ```rust,no_run - /// # use tokio::fs::File; - /// # use tokio::io; - /// # use indicatif::ProgressBar; - /// # async fn test() -> io::Result<()> { - /// let mut source = File::open("work.txt").await?; - /// let mut target = File::open("done.txt").await?; - /// let pb = ProgressBar::new(source.metadata().await?.len()); - /// io::copy(&mut source, &mut pb.wrap_async_write(target)).await?; - /// # Ok(()) - /// # } - /// ``` - pub fn wrap_async_write<W: tokio::io::AsyncWrite + Unpin>( - &self, - write: W, - ) -> ProgressBarIter<W> { - ProgressBarIter { - progress: self.clone(), - it: write, - } - } - - #[cfg(feature = "tokio")] - #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] - /// Wraps an [`tokio::io::AsyncRead`] with the progress bar - /// - /// ```rust,no_run - /// # use tokio::fs::File; - /// # use tokio::io; - /// # use indicatif::ProgressBar; - /// # async fn test() -> io::Result<()> { - /// let mut source = File::open("work.txt").await?; - /// let mut target = File::open("done.txt").await?; - /// let pb = ProgressBar::new(source.metadata().await?.len()); - /// io::copy(&mut pb.wrap_async_read(source), &mut target).await?; - /// # Ok(()) - /// # } - /// ``` - pub fn wrap_async_read<R: tokio::io::AsyncRead + Unpin>(&self, read: R) -> ProgressBarIter<R> { - ProgressBarIter { - progress: self.clone(), - it: read, - } - } - - /// Wraps a [`futures::Stream`](https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html) with the progress bar - /// - /// ``` - /// # use indicatif::ProgressBar; - /// # futures::executor::block_on(async { - /// use futures::stream::{self, StreamExt}; - /// let pb = ProgressBar::new(10); - /// let mut stream = pb.wrap_stream(stream::iter('a'..='z')); - /// - /// assert_eq!(stream.next().await, Some('a')); - /// assert_eq!(stream.count().await, 25); - /// # }); // block_on - /// ``` - #[cfg(feature = "futures")] - #[cfg_attr(docsrs, doc(cfg(feature = "futures")))] - pub fn wrap_stream<S: futures_core::Stream>(&self, stream: S) -> ProgressBarIter<S> { - ProgressBarIter { - progress: self.clone(), - it: stream, - } - } - - /// Returns the current position - pub fn position(&self) -> u64 { - self.state().state.pos() - } - - /// Returns the current length - pub fn length(&self) -> Option<u64> { - self.state().state.len() - } - - /// Returns the current ETA - pub fn eta(&self) -> Duration { - self.state().state.eta() - } - - /// Returns the current rate of progress - pub fn per_sec(&self) -> f64 { - self.state().state.per_sec() - } - - /// Returns the current expected duration - pub fn duration(&self) -> Duration { - self.state().state.duration() - } - - /// Returns the current elapsed time - pub fn elapsed(&self) -> Duration { - self.state().state.elapsed() - } - - /// Index in the `MultiState` - pub(crate) fn index(&self) -> Option<usize> { - self.state().draw_target.remote().map(|(_, idx)| idx) - } - - /// Current message - pub fn message(&self) -> String { - self.state().state.message.expanded().to_string() - } - - /// Current prefix - pub fn prefix(&self) -> String { - self.state().state.prefix.expanded().to_string() - } - - #[inline] - pub(crate) fn state(&self) -> MutexGuard<'_, BarState> { - self.state.lock().unwrap() - } -} - -/// A weak reference to a `ProgressBar`. -/// -/// Useful for creating custom steady tick implementations -#[derive(Clone, Default)] -pub struct WeakProgressBar { - state: Weak<Mutex<BarState>>, - pos: Weak<AtomicPosition>, - ticker: Weak<Mutex<Option<Ticker>>>, -} - -impl WeakProgressBar { - /// Create a new `WeakProgressBar` that returns `None` when [`upgrade`] is called. - /// - /// [`upgrade`]: WeakProgressBar::upgrade - pub fn new() -> Self { - Self::default() - } - - /// Attempts to upgrade the Weak pointer to a [`ProgressBar`], delaying dropping of the inner - /// value if successful. Returns `None` if the inner value has since been dropped. - /// - /// [`ProgressBar`]: struct.ProgressBar.html - pub fn upgrade(&self) -> Option<ProgressBar> { - let state = self.state.upgrade()?; - let pos = self.pos.upgrade()?; - let ticker = self.ticker.upgrade()?; - Some(ProgressBar { state, pos, ticker }) - } -} - -pub(crate) struct Ticker { - stopping: Arc<(Mutex<bool>, Condvar)>, - join_handle: Option<thread::JoinHandle<()>>, -} - -impl Drop for Ticker { - fn drop(&mut self) { - self.stop(); - self.join_handle.take().map(|handle| handle.join()); - } -} - -#[cfg(test)] -static TICKER_RUNNING: AtomicBool = AtomicBool::new(false); - -impl Ticker { - pub(crate) fn new(interval: Duration, bar_state: &Arc<Mutex<BarState>>) -> Self { - debug_assert!(!interval.is_zero()); - - // A `Mutex<bool>` is used as a flag to indicate whether the ticker was requested to stop. - // The `Condvar` is used a notification mechanism: when the ticker is dropped, we notify - // the thread and interrupt the ticker wait. - #[allow(clippy::mutex_atomic)] - let stopping = Arc::new((Mutex::new(false), Condvar::new())); - let control = TickerControl { - stopping: stopping.clone(), - state: Arc::downgrade(bar_state), - }; - - let join_handle = thread::spawn(move || control.run(interval)); - Self { - stopping, - join_handle: Some(join_handle), - } - } - - pub(crate) fn stop(&self) { - *self.stopping.0.lock().unwrap() = true; - self.stopping.1.notify_one(); - } -} - -struct TickerControl { - stopping: Arc<(Mutex<bool>, Condvar)>, - state: Weak<Mutex<BarState>>, -} - -impl TickerControl { - fn run(&self, interval: Duration) { - #[cfg(test)] - TICKER_RUNNING.store(true, Ordering::SeqCst); - - while let Some(arc) = self.state.upgrade() { - let mut state = arc.lock().unwrap(); - if state.state.is_finished() { - break; - } - - state.tick(Instant::now()); - - drop(state); // Don't forget to drop the lock before sleeping - drop(arc); // Also need to drop Arc otherwise BarState won't be dropped - - // Wait for `interval` but return early if we are notified to stop - let (_, result) = self - .stopping - .1 - .wait_timeout_while(self.stopping.0.lock().unwrap(), interval, |stopped| { - !*stopped - }) - .unwrap(); - - // If the wait didn't time out, it means we were notified to stop - if !result.timed_out() { - break; - } - } - - #[cfg(test)] - TICKER_RUNNING.store(false, Ordering::SeqCst); - } -} - -// Tests using the global TICKER_RUNNING flag need to be serialized -#[cfg(test)] -pub(crate) static TICKER_TEST: Lazy<Mutex<()>> = Lazy::new(Mutex::default); - -#[cfg(test)] -mod tests { - use super::*; - - #[allow(clippy::float_cmp)] - #[test] - fn test_pbar_zero() { - let pb = ProgressBar::new(0); - assert_eq!(pb.state().state.fraction(), 1.0); - } - - #[allow(clippy::float_cmp)] - #[test] - fn test_pbar_maxu64() { - let pb = ProgressBar::new(!0); - assert_eq!(pb.state().state.fraction(), 0.0); - } - - #[test] - fn test_pbar_overflow() { - let pb = ProgressBar::new(1); - pb.set_draw_target(ProgressDrawTarget::hidden()); - pb.inc(2); - pb.finish(); - } - - #[test] - fn test_get_position() { - let pb = ProgressBar::new(1); - pb.set_draw_target(ProgressDrawTarget::hidden()); - pb.inc(2); - let pos = pb.position(); - assert_eq!(pos, 2); - } - - #[test] - fn test_weak_pb() { - let pb = ProgressBar::new(0); - let weak = pb.downgrade(); - assert!(weak.upgrade().is_some()); - ::std::mem::drop(pb); - assert!(weak.upgrade().is_none()); - } - - #[test] - fn it_can_wrap_a_reader() { - let bytes = &b"I am an implementation of io::Read"[..]; - let pb = ProgressBar::new(bytes.len() as u64); - let mut reader = pb.wrap_read(bytes); - let mut writer = Vec::new(); - io::copy(&mut reader, &mut writer).unwrap(); - assert_eq!(writer, bytes); - } - - #[test] - fn it_can_wrap_a_writer() { - let bytes = b"implementation of io::Read"; - let mut reader = &bytes[..]; - let pb = ProgressBar::new(bytes.len() as u64); - let writer = Vec::new(); - let mut writer = pb.wrap_write(writer); - io::copy(&mut reader, &mut writer).unwrap(); - assert_eq!(writer.it, bytes); - } - - #[test] - fn ticker_thread_terminates_on_drop() { - let _guard = TICKER_TEST.lock().unwrap(); - assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); - - let pb = ProgressBar::new_spinner(); - pb.enable_steady_tick(Duration::from_millis(50)); - - // Give the thread time to start up - thread::sleep(Duration::from_millis(250)); - - assert!(TICKER_RUNNING.load(Ordering::SeqCst)); - - drop(pb); - assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); - } - - #[test] - fn ticker_thread_terminates_on_drop_2() { - let _guard = TICKER_TEST.lock().unwrap(); - assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); - - let pb = ProgressBar::new_spinner(); - pb.enable_steady_tick(Duration::from_millis(50)); - let pb2 = pb.clone(); - - // Give the thread time to start up - thread::sleep(Duration::from_millis(250)); - - assert!(TICKER_RUNNING.load(Ordering::SeqCst)); - - drop(pb); - assert!(TICKER_RUNNING.load(Ordering::SeqCst)); - - drop(pb2); - assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); - } -} diff --git a/vendor/indicatif/src/rayon.rs b/vendor/indicatif/src/rayon.rs deleted file mode 100644 index 1c8e844..0000000 --- a/vendor/indicatif/src/rayon.rs +++ /dev/null @@ -1,235 +0,0 @@ -use rayon::iter::plumbing::{Consumer, Folder, Producer, ProducerCallback, UnindexedConsumer}; -use rayon::iter::{IndexedParallelIterator, ParallelIterator}; - -use crate::{ProgressBar, ProgressBarIter}; - -/// Wraps a Rayon parallel iterator. -/// -/// See [`ProgressIterator`](trait.ProgressIterator.html) for method -/// documentation. -#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))] -pub trait ParallelProgressIterator -where - Self: Sized + ParallelIterator, -{ - /// Wrap an iterator with a custom progress bar. - fn progress_with(self, progress: ProgressBar) -> ProgressBarIter<Self>; - - /// Wrap an iterator with an explicit element count. - fn progress_count(self, len: u64) -> ProgressBarIter<Self> { - self.progress_with(ProgressBar::new(len)) - } - - fn progress(self) -> ProgressBarIter<Self> - where - Self: IndexedParallelIterator, - { - let len = u64::try_from(self.len()).unwrap(); - self.progress_count(len) - } - - /// Wrap an iterator with a progress bar and style it. - fn progress_with_style(self, style: crate::ProgressStyle) -> ProgressBarIter<Self> - where - Self: IndexedParallelIterator, - { - let len = u64::try_from(self.len()).unwrap(); - let bar = ProgressBar::new(len).with_style(style); - self.progress_with(bar) - } -} - -impl<S: Send, T: ParallelIterator<Item = S>> ParallelProgressIterator for T { - fn progress_with(self, progress: ProgressBar) -> ProgressBarIter<Self> { - ProgressBarIter { it: self, progress } - } -} - -impl<S: Send, T: IndexedParallelIterator<Item = S>> IndexedParallelIterator for ProgressBarIter<T> { - fn len(&self) -> usize { - self.it.len() - } - - fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> <C as Consumer<Self::Item>>::Result { - let consumer = ProgressConsumer::new(consumer, self.progress); - self.it.drive(consumer) - } - - fn with_producer<CB: ProducerCallback<Self::Item>>( - self, - callback: CB, - ) -> <CB as ProducerCallback<Self::Item>>::Output { - return self.it.with_producer(Callback { - callback, - progress: self.progress, - }); - - struct Callback<CB> { - callback: CB, - progress: ProgressBar, - } - - impl<T, CB: ProducerCallback<T>> ProducerCallback<T> for Callback<CB> { - type Output = CB::Output; - - fn callback<P>(self, base: P) -> CB::Output - where - P: Producer<Item = T>, - { - let producer = ProgressProducer { - base, - progress: self.progress, - }; - self.callback.callback(producer) - } - } - } -} - -struct ProgressProducer<T> { - base: T, - progress: ProgressBar, -} - -impl<T, P: Producer<Item = T>> Producer for ProgressProducer<P> { - type Item = T; - type IntoIter = ProgressBarIter<P::IntoIter>; - - fn into_iter(self) -> Self::IntoIter { - ProgressBarIter { - it: self.base.into_iter(), - progress: self.progress, - } - } - - fn min_len(&self) -> usize { - self.base.min_len() - } - - fn max_len(&self) -> usize { - self.base.max_len() - } - - fn split_at(self, index: usize) -> (Self, Self) { - let (left, right) = self.base.split_at(index); - ( - ProgressProducer { - base: left, - progress: self.progress.clone(), - }, - ProgressProducer { - base: right, - progress: self.progress, - }, - ) - } -} - -struct ProgressConsumer<C> { - base: C, - progress: ProgressBar, -} - -impl<C> ProgressConsumer<C> { - fn new(base: C, progress: ProgressBar) -> Self { - ProgressConsumer { base, progress } - } -} - -impl<T, C: Consumer<T>> Consumer<T> for ProgressConsumer<C> { - type Folder = ProgressFolder<C::Folder>; - type Reducer = C::Reducer; - type Result = C::Result; - - fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { - let (left, right, reducer) = self.base.split_at(index); - ( - ProgressConsumer::new(left, self.progress.clone()), - ProgressConsumer::new(right, self.progress), - reducer, - ) - } - - fn into_folder(self) -> Self::Folder { - ProgressFolder { - base: self.base.into_folder(), - progress: self.progress, - } - } - - fn full(&self) -> bool { - self.base.full() - } -} - -impl<T, C: UnindexedConsumer<T>> UnindexedConsumer<T> for ProgressConsumer<C> { - fn split_off_left(&self) -> Self { - ProgressConsumer::new(self.base.split_off_left(), self.progress.clone()) - } - - fn to_reducer(&self) -> Self::Reducer { - self.base.to_reducer() - } -} - -struct ProgressFolder<C> { - base: C, - progress: ProgressBar, -} - -impl<T, C: Folder<T>> Folder<T> for ProgressFolder<C> { - type Result = C::Result; - - fn consume(self, item: T) -> Self { - self.progress.inc(1); - ProgressFolder { - base: self.base.consume(item), - progress: self.progress, - } - } - - fn complete(self) -> C::Result { - self.base.complete() - } - - fn full(&self) -> bool { - self.base.full() - } -} - -impl<S: Send, T: ParallelIterator<Item = S>> ParallelIterator for ProgressBarIter<T> { - type Item = S; - - fn drive_unindexed<C: UnindexedConsumer<Self::Item>>(self, consumer: C) -> C::Result { - let consumer1 = ProgressConsumer::new(consumer, self.progress.clone()); - self.it.drive_unindexed(consumer1) - } -} - -#[cfg(test)] -mod test { - use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; - - use crate::{ParallelProgressIterator, ProgressBar, ProgressBarIter, ProgressStyle}; - - #[test] - fn it_can_wrap_a_parallel_iterator() { - let v = vec![1, 2, 3]; - fn wrap<'a, T: ParallelIterator<Item = &'a i32>>(it: ProgressBarIter<T>) { - assert_eq!(it.map(|x| x * 2).collect::<Vec<_>>(), vec![2, 4, 6]); - } - - wrap(v.par_iter().progress_count(3)); - wrap({ - let pb = ProgressBar::new(v.len() as u64); - v.par_iter().progress_with(pb) - }); - - wrap({ - let style = ProgressStyle::default_bar() - .template("{wide_bar:.red} {percent}/100%") - .unwrap(); - v.par_iter().progress_with_style(style) - }); - } -} diff --git a/vendor/indicatif/src/state.rs b/vendor/indicatif/src/state.rs deleted file mode 100644 index 3bcdc44..0000000 --- a/vendor/indicatif/src/state.rs +++ /dev/null @@ -1,798 +0,0 @@ -use std::borrow::Cow; -use std::io; -use std::sync::Arc; -use std::time::Duration; -#[cfg(not(target_arch = "wasm32"))] -use std::time::Instant; - -#[cfg(target_arch = "wasm32")] -use instant::Instant; -use portable_atomic::{AtomicU64, AtomicU8, Ordering}; - -use crate::draw_target::ProgressDrawTarget; -use crate::style::ProgressStyle; - -pub(crate) struct BarState { - pub(crate) draw_target: ProgressDrawTarget, - pub(crate) on_finish: ProgressFinish, - pub(crate) style: ProgressStyle, - pub(crate) state: ProgressState, - pub(crate) tab_width: usize, -} - -impl BarState { - pub(crate) fn new( - len: Option<u64>, - draw_target: ProgressDrawTarget, - pos: Arc<AtomicPosition>, - ) -> Self { - Self { - draw_target, - on_finish: ProgressFinish::default(), - style: ProgressStyle::default_bar(), - state: ProgressState::new(len, pos), - tab_width: DEFAULT_TAB_WIDTH, - } - } - - /// Finishes the progress bar using the [`ProgressFinish`] behavior stored - /// in the [`ProgressStyle`]. - pub(crate) fn finish_using_style(&mut self, now: Instant, finish: ProgressFinish) { - self.state.status = Status::DoneVisible; - match finish { - ProgressFinish::AndLeave => { - if let Some(len) = self.state.len { - self.state.pos.set(len); - } - } - ProgressFinish::WithMessage(msg) => { - if let Some(len) = self.state.len { - self.state.pos.set(len); - } - self.state.message = TabExpandedString::new(msg, self.tab_width); - } - ProgressFinish::AndClear => { - if let Some(len) = self.state.len { - self.state.pos.set(len); - } - self.state.status = Status::DoneHidden; - } - ProgressFinish::Abandon => {} - ProgressFinish::AbandonWithMessage(msg) => { - self.state.message = TabExpandedString::new(msg, self.tab_width); - } - } - - // There's no need to update the estimate here; once the `status` is no longer - // `InProgress`, we will use the length and elapsed time to estimate. - let _ = self.draw(true, now); - } - - pub(crate) fn reset(&mut self, now: Instant, mode: Reset) { - // Always reset the estimator; this is the only reset that will occur if mode is - // `Reset::Eta`. - self.state.est.reset(now); - - if let Reset::Elapsed | Reset::All = mode { - self.state.started = now; - } - - if let Reset::All = mode { - self.state.pos.reset(now); - self.state.status = Status::InProgress; - - for tracker in self.style.format_map.values_mut() { - tracker.reset(&self.state, now); - } - - let _ = self.draw(false, now); - } - } - - pub(crate) fn update(&mut self, now: Instant, f: impl FnOnce(&mut ProgressState), tick: bool) { - f(&mut self.state); - if tick { - self.tick(now); - } - } - - pub(crate) fn set_length(&mut self, now: Instant, len: u64) { - self.state.len = Some(len); - self.update_estimate_and_draw(now); - } - - pub(crate) fn inc_length(&mut self, now: Instant, delta: u64) { - if let Some(len) = self.state.len { - self.state.len = Some(len.saturating_add(delta)); - } - self.update_estimate_and_draw(now); - } - - pub(crate) fn set_tab_width(&mut self, tab_width: usize) { - self.tab_width = tab_width; - self.state.message.set_tab_width(tab_width); - self.state.prefix.set_tab_width(tab_width); - self.style.set_tab_width(tab_width); - } - - pub(crate) fn set_style(&mut self, style: ProgressStyle) { - self.style = style; - self.style.set_tab_width(self.tab_width); - } - - pub(crate) fn tick(&mut self, now: Instant) { - self.state.tick = self.state.tick.saturating_add(1); - self.update_estimate_and_draw(now); - } - - pub(crate) fn update_estimate_and_draw(&mut self, now: Instant) { - let pos = self.state.pos.pos.load(Ordering::Relaxed); - self.state.est.record(pos, now); - - for tracker in self.style.format_map.values_mut() { - tracker.tick(&self.state, now); - } - - let _ = self.draw(false, now); - } - - pub(crate) fn println(&mut self, now: Instant, msg: &str) { - let width = self.draw_target.width(); - let mut drawable = match self.draw_target.drawable(true, now) { - Some(drawable) => drawable, - None => return, - }; - - let mut draw_state = drawable.state(); - let lines: Vec<String> = msg.lines().map(Into::into).collect(); - // Empty msg should trigger newline as we are in println - if lines.is_empty() { - draw_state.lines.push(String::new()); - } else { - draw_state.lines.extend(lines); - } - draw_state.orphan_lines_count = draw_state.lines.len(); - if !matches!(self.state.status, Status::DoneHidden) { - self.style - .format_state(&self.state, &mut draw_state.lines, width); - } - - drop(draw_state); - let _ = drawable.draw(); - } - - pub(crate) fn suspend<F: FnOnce() -> R, R>(&mut self, now: Instant, f: F) -> R { - if let Some((state, _)) = self.draw_target.remote() { - return state.write().unwrap().suspend(f, now); - } - - if let Some(drawable) = self.draw_target.drawable(true, now) { - let _ = drawable.clear(); - } - - let ret = f(); - let _ = self.draw(true, Instant::now()); - ret - } - - pub(crate) fn draw(&mut self, mut force_draw: bool, now: Instant) -> io::Result<()> { - let width = self.draw_target.width(); - - // `|= self.is_finished()` should not be needed here, but we used to always draw for - // finished progress bars, so it's kept as to not cause compatibility issues in weird cases. - force_draw |= self.state.is_finished(); - let mut drawable = match self.draw_target.drawable(force_draw, now) { - Some(drawable) => drawable, - None => return Ok(()), - }; - - let mut draw_state = drawable.state(); - - if !matches!(self.state.status, Status::DoneHidden) { - self.style - .format_state(&self.state, &mut draw_state.lines, width); - } - - drop(draw_state); - drawable.draw() - } -} - -impl Drop for BarState { - fn drop(&mut self) { - // Progress bar is already finished. Do not need to do anything other than notify - // the `MultiProgress` that we're now a zombie. - if self.state.is_finished() { - self.draw_target.mark_zombie(); - return; - } - - self.finish_using_style(Instant::now(), self.on_finish.clone()); - - // Notify the `MultiProgress` that we're now a zombie. - self.draw_target.mark_zombie(); - } -} - -pub(crate) enum Reset { - Eta, - Elapsed, - All, -} - -/// The state of a progress bar at a moment in time. -#[non_exhaustive] -pub struct ProgressState { - pos: Arc<AtomicPosition>, - len: Option<u64>, - pub(crate) tick: u64, - pub(crate) started: Instant, - status: Status, - est: Estimator, - pub(crate) message: TabExpandedString, - pub(crate) prefix: TabExpandedString, -} - -impl ProgressState { - pub(crate) fn new(len: Option<u64>, pos: Arc<AtomicPosition>) -> Self { - let now = Instant::now(); - Self { - pos, - len, - tick: 0, - status: Status::InProgress, - started: now, - est: Estimator::new(now), - message: TabExpandedString::NoTabs("".into()), - prefix: TabExpandedString::NoTabs("".into()), - } - } - - /// Indicates that the progress bar finished. - pub fn is_finished(&self) -> bool { - match self.status { - Status::InProgress => false, - Status::DoneVisible => true, - Status::DoneHidden => true, - } - } - - /// Returns the completion as a floating-point number between 0 and 1 - pub fn fraction(&self) -> f32 { - let pos = self.pos.pos.load(Ordering::Relaxed); - let pct = match (pos, self.len) { - (_, None) => 0.0, - (_, Some(0)) => 1.0, - (0, _) => 0.0, - (pos, Some(len)) => pos as f32 / len as f32, - }; - pct.clamp(0.0, 1.0) - } - - /// The expected ETA - pub fn eta(&self) -> Duration { - if self.is_finished() { - return Duration::new(0, 0); - } - - let len = match self.len { - Some(len) => len, - None => return Duration::new(0, 0), - }; - - let pos = self.pos.pos.load(Ordering::Relaxed); - - let sps = self.est.steps_per_second(Instant::now()); - - // Infinite duration should only ever happen at the beginning, so in this case it's okay to - // just show an ETA of 0 until progress starts to occur. - if sps == 0.0 { - return Duration::new(0, 0); - } - - secs_to_duration(len.saturating_sub(pos) as f64 / sps) - } - - /// The expected total duration (that is, elapsed time + expected ETA) - pub fn duration(&self) -> Duration { - if self.len.is_none() || self.is_finished() { - return Duration::new(0, 0); - } - self.started.elapsed().saturating_add(self.eta()) - } - - /// The number of steps per second - pub fn per_sec(&self) -> f64 { - if let Status::InProgress = self.status { - self.est.steps_per_second(Instant::now()) - } else { - let len = self.len.unwrap_or_else(|| self.pos()); - len as f64 / self.started.elapsed().as_secs_f64() - } - } - - pub fn elapsed(&self) -> Duration { - self.started.elapsed() - } - - pub fn pos(&self) -> u64 { - self.pos.pos.load(Ordering::Relaxed) - } - - pub fn set_pos(&mut self, pos: u64) { - self.pos.set(pos); - } - - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> Option<u64> { - self.len - } - - pub fn set_len(&mut self, len: u64) { - self.len = Some(len); - } -} - -#[derive(Debug, PartialEq, Eq, Clone)] -pub(crate) enum TabExpandedString { - NoTabs(Cow<'static, str>), - WithTabs { - original: Cow<'static, str>, - expanded: String, - tab_width: usize, - }, -} - -impl TabExpandedString { - pub(crate) fn new(s: Cow<'static, str>, tab_width: usize) -> Self { - let expanded = s.replace('\t', &" ".repeat(tab_width)); - if s == expanded { - Self::NoTabs(s) - } else { - Self::WithTabs { - original: s, - expanded, - tab_width, - } - } - } - - pub(crate) fn expanded(&self) -> &str { - match &self { - Self::NoTabs(s) => { - debug_assert!(!s.contains('\t')); - s - } - Self::WithTabs { expanded, .. } => expanded, - } - } - - pub(crate) fn set_tab_width(&mut self, new_tab_width: usize) { - if let Self::WithTabs { - original, - expanded, - tab_width, - } = self - { - if *tab_width != new_tab_width { - *tab_width = new_tab_width; - *expanded = original.replace('\t', &" ".repeat(new_tab_width)); - } - } - } -} - -/// Double-smoothed exponentially weighted estimator -/// -/// This uses an exponentially weighted *time-based* estimator, meaning that it exponentially -/// downweights old data based on its age. The rate at which this occurs is currently a constant -/// value of 15 seconds for 90% weighting. This means that all data older than 15 seconds has a -/// collective weight of 0.1 in the estimate, and all data older than 30 seconds has a collective -/// weight of 0.01, and so on. -/// -/// The primary value exposed by `Estimator` is `steps_per_second`. This value is doubly-smoothed, -/// meaning that is the result of using an exponentially weighted estimator (as described above) to -/// estimate the value of another exponentially weighted estimator, which estimates the value of -/// the raw data. -/// -/// The purpose of this extra smoothing step is to reduce instantaneous fluctations in the estimate -/// when large updates are received. Without this, estimates might have a large spike followed by a -/// slow asymptotic approach to zero (until the next spike). -#[derive(Debug)] -pub(crate) struct Estimator { - smoothed_steps_per_sec: f64, - double_smoothed_steps_per_sec: f64, - prev_steps: u64, - prev_time: Instant, - start_time: Instant, -} - -impl Estimator { - fn new(now: Instant) -> Self { - Self { - smoothed_steps_per_sec: 0.0, - double_smoothed_steps_per_sec: 0.0, - prev_steps: 0, - prev_time: now, - start_time: now, - } - } - - fn record(&mut self, new_steps: u64, now: Instant) { - // sanity check: don't record data if time or steps have not advanced - if new_steps <= self.prev_steps || now <= self.prev_time { - // Reset on backwards seek to prevent breakage from seeking to the end for length determination - // See https://github.com/console-rs/indicatif/issues/480 - if new_steps < self.prev_steps { - self.prev_steps = new_steps; - self.reset(now); - } - return; - } - - let delta_steps = new_steps - self.prev_steps; - let delta_t = duration_to_secs(now - self.prev_time); - - // the rate of steps we saw in this update - let new_steps_per_second = delta_steps as f64 / delta_t; - - // update the estimate: a weighted average of the old estimate and new data - let weight = estimator_weight(delta_t); - self.smoothed_steps_per_sec = - self.smoothed_steps_per_sec * weight + new_steps_per_second * (1.0 - weight); - - // An iterative estimate like `smoothed_steps_per_sec` is supposed to be an exponentially - // weighted average from t=0 back to t=-inf; Since we initialize it to 0, we neglect the - // (non-existent) samples in the weighted average prior to the first one, so the resulting - // average must be normalized. We normalize the single estimate here in order to use it as - // a source for the double smoothed estimate. See comment on normalization in - // `steps_per_second` for details. - let delta_t_start = duration_to_secs(now - self.start_time); - let total_weight = 1.0 - estimator_weight(delta_t_start); - let normalized_smoothed_steps_per_sec = self.smoothed_steps_per_sec / total_weight; - - // determine the double smoothed value (EWA smoothing of the single EWA) - self.double_smoothed_steps_per_sec = self.double_smoothed_steps_per_sec * weight - + normalized_smoothed_steps_per_sec * (1.0 - weight); - - self.prev_steps = new_steps; - self.prev_time = now; - } - - /// Reset the state of the estimator. Once reset, estimates will not depend on any data prior - /// to `now`. This does not reset the stored position of the progress bar. - pub(crate) fn reset(&mut self, now: Instant) { - self.smoothed_steps_per_sec = 0.0; - self.double_smoothed_steps_per_sec = 0.0; - - // only reset prev_time, not prev_steps - self.prev_time = now; - self.start_time = now; - } - - /// Average time per step in seconds, using double exponential smoothing - fn steps_per_second(&self, now: Instant) -> f64 { - // Because the value stored in the Estimator is only updated when the Estimator receives an - // update, this value will become stuck if progress stalls. To return an accurate estimate, - // we determine how much time has passed since the last update, and treat this as a - // pseudo-update with 0 steps. - let delta_t = duration_to_secs(now - self.prev_time); - let reweight = estimator_weight(delta_t); - - // Normalization of estimates: - // - // The raw estimate is a single value (smoothed_steps_per_second) that is iteratively - // updated. At each update, the previous value of the estimate is downweighted according to - // its age, receiving the iterative weight W(t) = 0.1 ^ (t/15). - // - // Since W(Sum(t_n)) = Prod(W(t_n)), the total weight of a sample after a series of - // iterative steps is simply W(t_e) - W(t_b), where t_e is the time since the end of the - // sample, and t_b is the time since the beginning. The resulting estimate is therefore a - // weighted average with sample weights W(t_e) - W(t_b). - // - // Notice that the weighting function generates sample weights that sum to 1 only when the - // sample times span from t=0 to t=inf; but this is not the case. We have a first sample - // with finite, positive t_b = t_f. In the raw estimate, we handle times prior to t_f by - // setting an initial value of 0, meaning that these (non-existent) samples have no weight. - // - // Therefore, the raw estimate must be normalized by dividing it by the sum of the weights - // in the weighted average. This sum is just W(0) - W(t_f), where t_f is the time since the - // first sample, and W(0) = 1. - let delta_t_start = duration_to_secs(now - self.start_time); - let total_weight = 1.0 - estimator_weight(delta_t_start); - - // Generate updated values for `smoothed_steps_per_sec` and `double_smoothed_steps_per_sec` - // (sps and dsps) without storing them. Note that we normalize sps when using it as a - // source to update dsps, and then normalize dsps itself before returning it. - let sps = self.smoothed_steps_per_sec * reweight / total_weight; - let dsps = self.double_smoothed_steps_per_sec * reweight + sps * (1.0 - reweight); - dsps / total_weight - } -} - -pub(crate) struct AtomicPosition { - pub(crate) pos: AtomicU64, - capacity: AtomicU8, - prev: AtomicU64, - start: Instant, -} - -impl AtomicPosition { - pub(crate) fn new() -> Self { - Self { - pos: AtomicU64::new(0), - capacity: AtomicU8::new(MAX_BURST), - prev: AtomicU64::new(0), - start: Instant::now(), - } - } - - pub(crate) fn allow(&self, now: Instant) -> bool { - if now < self.start { - return false; - } - - let mut capacity = self.capacity.load(Ordering::Acquire); - // `prev` is the number of ms after `self.started` we last returned `true`, in ns - let prev = self.prev.load(Ordering::Acquire); - // `elapsed` is the number of ns since `self.started` - let elapsed = (now - self.start).as_nanos() as u64; - // `diff` is the number of ns since we last returned `true` - let diff = elapsed.saturating_sub(prev); - - // If `capacity` is 0 and not enough time (1ms) has passed since `prev` - // to add new capacity, return `false`. The goal of this method is to - // make this decision as efficient as possible. - if capacity == 0 && diff < INTERVAL { - return false; - } - - // We now calculate `new`, the number of ms, in ns, since we last returned `true`, - // and `remainder`, which represents a number of ns less than 1ms which we cannot - // convert into capacity now, so we're saving it for later. We do this by - // substracting this from `elapsed` before storing it into `self.prev`. - let (new, remainder) = ((diff / INTERVAL), (diff % INTERVAL)); - // We add `new` to `capacity`, subtract one for returning `true` from here, - // then make sure it does not exceed a maximum of `MAX_BURST`. - capacity = Ord::min(MAX_BURST as u128, (capacity as u128) + (new as u128) - 1) as u8; - - // Then, we just store `capacity` and `prev` atomically for the next iteration - self.capacity.store(capacity, Ordering::Release); - self.prev.store(elapsed - remainder, Ordering::Release); - true - } - - fn reset(&self, now: Instant) { - self.set(0); - let elapsed = (now.saturating_duration_since(self.start)).as_millis() as u64; - self.prev.store(elapsed, Ordering::Release); - } - - pub(crate) fn inc(&self, delta: u64) { - self.pos.fetch_add(delta, Ordering::SeqCst); - } - - pub(crate) fn set(&self, pos: u64) { - self.pos.store(pos, Ordering::Release); - } -} - -const INTERVAL: u64 = 1_000_000; -const MAX_BURST: u8 = 10; - -/// Behavior of a progress bar when it is finished -/// -/// This is invoked when a [`ProgressBar`] or [`ProgressBarIter`] completes and -/// [`ProgressBar::is_finished`] is false. -/// -/// [`ProgressBar`]: crate::ProgressBar -/// [`ProgressBarIter`]: crate::ProgressBarIter -/// [`ProgressBar::is_finished`]: crate::ProgressBar::is_finished -#[derive(Clone, Debug)] -pub enum ProgressFinish { - /// Finishes the progress bar and leaves the current message - /// - /// Same behavior as calling [`ProgressBar::finish()`](crate::ProgressBar::finish). - AndLeave, - /// Finishes the progress bar and sets a message - /// - /// Same behavior as calling [`ProgressBar::finish_with_message()`](crate::ProgressBar::finish_with_message). - WithMessage(Cow<'static, str>), - /// Finishes the progress bar and completely clears it (this is the default) - /// - /// Same behavior as calling [`ProgressBar::finish_and_clear()`](crate::ProgressBar::finish_and_clear). - AndClear, - /// Finishes the progress bar and leaves the current message and progress - /// - /// Same behavior as calling [`ProgressBar::abandon()`](crate::ProgressBar::abandon). - Abandon, - /// Finishes the progress bar and sets a message, and leaves the current progress - /// - /// Same behavior as calling [`ProgressBar::abandon_with_message()`](crate::ProgressBar::abandon_with_message). - AbandonWithMessage(Cow<'static, str>), -} - -impl Default for ProgressFinish { - fn default() -> Self { - Self::AndClear - } -} - -/// Get the appropriate dilution weight for Estimator data given the data's age (in seconds) -/// -/// Whenever an update occurs, we will create a new estimate using a weight `w_i` like so: -/// -/// ```math -/// <new estimate> = <previous estimate> * w_i + <new data> * (1 - w_i) -/// ``` -/// -/// In other words, the new estimate is a weighted average of the previous estimate and the new -/// data. We want to choose weights such that for any set of samples where `t_0, t_1, ...` are -/// the durations of the samples: -/// -/// ```math -/// Sum(t_i) = ews ==> Prod(w_i) = 0.1 -/// ``` -/// -/// With this constraint it is easy to show that -/// -/// ```math -/// w_i = 0.1 ^ (t_i / ews) -/// ``` -/// -/// Notice that the constraint implies that estimates are independent of the durations of the -/// samples, a very useful feature. -fn estimator_weight(age: f64) -> f64 { - const EXPONENTIAL_WEIGHTING_SECONDS: f64 = 15.0; - 0.1_f64.powf(age / EXPONENTIAL_WEIGHTING_SECONDS) -} - -fn duration_to_secs(d: Duration) -> f64 { - d.as_secs() as f64 + f64::from(d.subsec_nanos()) / 1_000_000_000f64 -} - -fn secs_to_duration(s: f64) -> Duration { - let secs = s.trunc() as u64; - let nanos = (s.fract() * 1_000_000_000f64) as u32; - Duration::new(secs, nanos) -} - -#[derive(Debug)] -pub(crate) enum Status { - InProgress, - DoneVisible, - DoneHidden, -} - -pub(crate) const DEFAULT_TAB_WIDTH: usize = 8; - -#[cfg(test)] -mod tests { - use super::*; - use crate::ProgressBar; - - // https://github.com/rust-lang/rust-clippy/issues/10281 - #[allow(clippy::uninlined_format_args)] - #[test] - fn test_steps_per_second() { - let test_rate = |items_per_second| { - let mut now = Instant::now(); - let mut est = Estimator::new(now); - let mut pos = 0; - - for _ in 0..20 { - pos += items_per_second; - now += Duration::from_secs(1); - est.record(pos, now); - } - let avg_steps_per_second = est.steps_per_second(now); - - assert!(avg_steps_per_second > 0.0); - assert!(avg_steps_per_second.is_finite()); - - let absolute_error = (avg_steps_per_second - items_per_second as f64).abs(); - let relative_error = absolute_error / items_per_second as f64; - assert!( - relative_error < 1.0 / 1e9, - "Expected rate: {}, actual: {}, relative error: {}", - items_per_second, - avg_steps_per_second, - relative_error - ); - }; - - test_rate(1); - test_rate(1_000); - test_rate(1_000_000); - test_rate(1_000_000_000); - test_rate(1_000_000_001); - test_rate(100_000_000_000); - test_rate(1_000_000_000_000); - test_rate(100_000_000_000_000); - test_rate(1_000_000_000_000_000); - } - - #[test] - fn test_double_exponential_ave() { - let mut now = Instant::now(); - let mut est = Estimator::new(now); - let mut pos = 0; - - // note: this is the default weight set in the Estimator - let weight = 15; - - for _ in 0..weight { - pos += 1; - now += Duration::from_secs(1); - est.record(pos, now); - } - now += Duration::from_secs(weight); - - // The first level EWA: - // -> 90% weight @ 0 eps, 9% weight @ 1 eps, 1% weight @ 0 eps - // -> then normalized by deweighting the 1% weight (before -30 seconds) - let single_target = 0.09 / 0.99; - - // The second level EWA: - // -> same logic as above, but using the first level EWA as the source - let double_target = (0.9 * single_target + 0.09) / 0.99; - assert_eq!(est.steps_per_second(now), double_target); - } - - #[test] - fn test_estimator_rewind_position() { - let mut now = Instant::now(); - let mut est = Estimator::new(now); - - now += Duration::from_secs(1); - est.record(1, now); - - // should not panic - now += Duration::from_secs(1); - est.record(0, now); - - // check that reset occurred (estimator at 1 event per sec) - now += Duration::from_secs(1); - est.record(1, now); - assert_eq!(est.steps_per_second(now), 1.0); - - // check that progress bar handles manual seeking - let pb = ProgressBar::hidden(); - pb.set_length(10); - pb.set_position(1); - pb.tick(); - // Should not panic. - pb.set_position(0); - } - - #[test] - fn test_reset_eta() { - let mut now = Instant::now(); - let mut est = Estimator::new(now); - - // two per second, then reset - now += Duration::from_secs(1); - est.record(2, now); - est.reset(now); - - // now one per second, and verify - now += Duration::from_secs(1); - est.record(3, now); - assert_eq!(est.steps_per_second(now), 1.0); - } - - #[test] - fn test_duration_stuff() { - let duration = Duration::new(42, 100_000_000); - let secs = duration_to_secs(duration); - assert_eq!(secs_to_duration(secs), duration); - } - - #[test] - fn test_atomic_position_large_time_difference() { - let atomic_position = AtomicPosition::new(); - let later = atomic_position.start + Duration::from_nanos(INTERVAL * u64::from(u8::MAX)); - // Should not panic. - atomic_position.allow(later); - } -} diff --git a/vendor/indicatif/src/style.rs b/vendor/indicatif/src/style.rs deleted file mode 100644 index 01b220f..0000000 --- a/vendor/indicatif/src/style.rs +++ /dev/null @@ -1,987 +0,0 @@ -use std::collections::HashMap; -use std::fmt::{self, Write}; -use std::mem; -#[cfg(not(target_arch = "wasm32"))] -use std::time::Instant; - -use console::{measure_text_width, Style}; -#[cfg(target_arch = "wasm32")] -use instant::Instant; -#[cfg(feature = "unicode-segmentation")] -use unicode_segmentation::UnicodeSegmentation; - -use crate::format::{ - BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanCount, HumanDuration, - HumanFloatCount, -}; -use crate::state::{ProgressState, TabExpandedString, DEFAULT_TAB_WIDTH}; - -#[derive(Clone)] -pub struct ProgressStyle { - tick_strings: Vec<Box<str>>, - progress_chars: Vec<Box<str>>, - template: Template, - // how unicode-big each char in progress_chars is - char_width: usize, - tab_width: usize, - pub(crate) format_map: HashMap<&'static str, Box<dyn ProgressTracker>>, -} - -#[cfg(feature = "unicode-segmentation")] -fn segment(s: &str) -> Vec<Box<str>> { - UnicodeSegmentation::graphemes(s, true) - .map(|s| s.into()) - .collect() -} - -#[cfg(not(feature = "unicode-segmentation"))] -fn segment(s: &str) -> Vec<Box<str>> { - s.chars().map(|x| x.to_string().into()).collect() -} - -#[cfg(feature = "unicode-width")] -fn measure(s: &str) -> usize { - unicode_width::UnicodeWidthStr::width(s) -} - -#[cfg(not(feature = "unicode-width"))] -fn measure(s: &str) -> usize { - s.chars().count() -} - -/// finds the unicode-aware width of the passed grapheme cluters -/// panics on an empty parameter, or if the characters are not equal-width -fn width(c: &[Box<str>]) -> usize { - c.iter() - .map(|s| measure(s.as_ref())) - .fold(None, |acc, new| { - match acc { - None => return Some(new), - Some(old) => assert_eq!(old, new, "got passed un-equal width progress characters"), - } - acc - }) - .unwrap() -} - -impl ProgressStyle { - /// Returns the default progress bar style for bars - pub fn default_bar() -> Self { - Self::new(Template::from_str("{wide_bar} {pos}/{len}").unwrap()) - } - - /// Returns the default progress bar style for spinners - pub fn default_spinner() -> Self { - Self::new(Template::from_str("{spinner} {msg}").unwrap()) - } - - /// Sets the template string for the progress bar - /// - /// Review the [list of template keys](../index.html#templates) for more information. - pub fn with_template(template: &str) -> Result<Self, TemplateError> { - Ok(Self::new(Template::from_str(template)?)) - } - - pub(crate) fn set_tab_width(&mut self, new_tab_width: usize) { - self.tab_width = new_tab_width; - self.template.set_tab_width(new_tab_width); - } - - fn new(template: Template) -> Self { - let progress_chars = segment("ββ"); - let char_width = width(&progress_chars); - Self { - tick_strings: "β β β β β β β β β β ²β ΄β €β β β €β β β €β ¦β β β β β β β β β β " - .chars() - .map(|c| c.to_string().into()) - .collect(), - progress_chars, - char_width, - template, - format_map: HashMap::default(), - tab_width: DEFAULT_TAB_WIDTH, - } - } - - /// Sets the tick character sequence for spinners - /// - /// Note that the last character is used as the [final tick string][Self::get_final_tick_str()]. - /// At least two characters are required to provide a non-final and final state. - pub fn tick_chars(mut self, s: &str) -> Self { - self.tick_strings = s.chars().map(|c| c.to_string().into()).collect(); - // Format bar will panic with some potentially confusing message, better to panic here - // with a message explicitly informing of the problem - assert!( - self.tick_strings.len() >= 2, - "at least 2 tick chars required" - ); - self - } - - /// Sets the tick string sequence for spinners - /// - /// Note that the last string is used as the [final tick string][Self::get_final_tick_str()]. - /// At least two strings are required to provide a non-final and final state. - pub fn tick_strings(mut self, s: &[&str]) -> Self { - self.tick_strings = s.iter().map(|s| s.to_string().into()).collect(); - // Format bar will panic with some potentially confusing message, better to panic here - // with a message explicitly informing of the problem - assert!( - self.progress_chars.len() >= 2, - "at least 2 tick strings required" - ); - self - } - - /// Sets the progress characters `(filled, current, to do)` - /// - /// You can pass more than three for a more detailed display. - /// All passed grapheme clusters need to be of equal width. - pub fn progress_chars(mut self, s: &str) -> Self { - self.progress_chars = segment(s); - // Format bar will panic with some potentially confusing message, better to panic here - // with a message explicitly informing of the problem - assert!( - self.progress_chars.len() >= 2, - "at least 2 progress chars required" - ); - self.char_width = width(&self.progress_chars); - self - } - - /// Adds a custom key that owns a [`ProgressTracker`] to the template - pub fn with_key<S: ProgressTracker + 'static>(mut self, key: &'static str, f: S) -> Self { - self.format_map.insert(key, Box::new(f)); - self - } - - /// Sets the template string for the progress bar - /// - /// Review the [list of template keys](../index.html#templates) for more information. - pub fn template(mut self, s: &str) -> Result<Self, TemplateError> { - self.template = Template::from_str(s)?; - Ok(self) - } - - fn current_tick_str(&self, state: &ProgressState) -> &str { - match state.is_finished() { - true => self.get_final_tick_str(), - false => self.get_tick_str(state.tick), - } - } - - /// Returns the tick string for a given number - pub fn get_tick_str(&self, idx: u64) -> &str { - &self.tick_strings[(idx as usize) % (self.tick_strings.len() - 1)] - } - - /// Returns the tick string for the finished state - pub fn get_final_tick_str(&self) -> &str { - &self.tick_strings[self.tick_strings.len() - 1] - } - - fn format_bar(&self, fract: f32, width: usize, alt_style: Option<&Style>) -> BarDisplay<'_> { - // The number of clusters from progress_chars to write (rounding down). - let width = width / self.char_width; - // The number of full clusters (including a fractional component for a partially-full one). - let fill = fract * width as f32; - // The number of entirely full clusters (by truncating `fill`). - let entirely_filled = fill as usize; - // 1 if the bar is not entirely empty or full (meaning we need to draw the "current" - // character between the filled and "to do" segment), 0 otherwise. - let head = usize::from(fill > 0.0 && entirely_filled < width); - - let cur = if head == 1 { - // Number of fine-grained progress entries in progress_chars. - let n = self.progress_chars.len().saturating_sub(2); - let cur_char = if n <= 1 { - // No fine-grained entries. 1 is the single "current" entry if we have one, the "to - // do" entry if not. - 1 - } else { - // Pick a fine-grained entry, ranging from the last one (n) if the fractional part - // of fill is 0 to the first one (1) if the fractional part of fill is almost 1. - n.saturating_sub((fill.fract() * n as f32) as usize) - }; - Some(cur_char) - } else { - None - }; - - // Number of entirely empty clusters needed to fill the bar up to `width`. - let bg = width.saturating_sub(entirely_filled).saturating_sub(head); - let rest = RepeatedStringDisplay { - str: &self.progress_chars[self.progress_chars.len() - 1], - num: bg, - }; - - BarDisplay { - chars: &self.progress_chars, - filled: entirely_filled, - cur, - rest: alt_style.unwrap_or(&Style::new()).apply_to(rest), - } - } - - pub(crate) fn format_state( - &self, - state: &ProgressState, - lines: &mut Vec<String>, - target_width: u16, - ) { - let mut cur = String::new(); - let mut buf = String::new(); - let mut wide = None; - - let pos = state.pos(); - let len = state.len().unwrap_or(pos); - for part in &self.template.parts { - match part { - TemplatePart::Placeholder { - key, - align, - width, - truncate, - style, - alt_style, - } => { - buf.clear(); - if let Some(tracker) = self.format_map.get(key.as_str()) { - tracker.write(state, &mut TabRewriter(&mut buf, self.tab_width)); - } else { - match key.as_str() { - "wide_bar" => { - wide = Some(WideElement::Bar { alt_style }); - buf.push('\x00'); - } - "bar" => buf - .write_fmt(format_args!( - "{}", - self.format_bar( - state.fraction(), - width.unwrap_or(20) as usize, - alt_style.as_ref(), - ) - )) - .unwrap(), - "spinner" => buf.push_str(self.current_tick_str(state)), - "wide_msg" => { - wide = Some(WideElement::Message { align }); - buf.push('\x00'); - } - "msg" => buf.push_str(state.message.expanded()), - "prefix" => buf.push_str(state.prefix.expanded()), - "pos" => buf.write_fmt(format_args!("{pos}")).unwrap(), - "human_pos" => { - buf.write_fmt(format_args!("{}", HumanCount(pos))).unwrap(); - } - "len" => buf.write_fmt(format_args!("{len}")).unwrap(), - "human_len" => { - buf.write_fmt(format_args!("{}", HumanCount(len))).unwrap(); - } - "percent" => buf - .write_fmt(format_args!("{:.*}", 0, state.fraction() * 100f32)) - .unwrap(), - "bytes" => buf.write_fmt(format_args!("{}", HumanBytes(pos))).unwrap(), - "total_bytes" => { - buf.write_fmt(format_args!("{}", HumanBytes(len))).unwrap(); - } - "decimal_bytes" => buf - .write_fmt(format_args!("{}", DecimalBytes(pos))) - .unwrap(), - "decimal_total_bytes" => buf - .write_fmt(format_args!("{}", DecimalBytes(len))) - .unwrap(), - "binary_bytes" => { - buf.write_fmt(format_args!("{}", BinaryBytes(pos))).unwrap(); - } - "binary_total_bytes" => { - buf.write_fmt(format_args!("{}", BinaryBytes(len))).unwrap(); - } - "elapsed_precise" => buf - .write_fmt(format_args!("{}", FormattedDuration(state.elapsed()))) - .unwrap(), - "elapsed" => buf - .write_fmt(format_args!("{:#}", HumanDuration(state.elapsed()))) - .unwrap(), - "per_sec" => buf - .write_fmt(format_args!("{}/s", HumanFloatCount(state.per_sec()))) - .unwrap(), - "bytes_per_sec" => buf - .write_fmt(format_args!("{}/s", HumanBytes(state.per_sec() as u64))) - .unwrap(), - "binary_bytes_per_sec" => buf - .write_fmt(format_args!( - "{}/s", - BinaryBytes(state.per_sec() as u64) - )) - .unwrap(), - "eta_precise" => buf - .write_fmt(format_args!("{}", FormattedDuration(state.eta()))) - .unwrap(), - "eta" => buf - .write_fmt(format_args!("{:#}", HumanDuration(state.eta()))) - .unwrap(), - "duration_precise" => buf - .write_fmt(format_args!("{}", FormattedDuration(state.duration()))) - .unwrap(), - "duration" => buf - .write_fmt(format_args!("{:#}", HumanDuration(state.duration()))) - .unwrap(), - _ => (), - } - }; - - match width { - Some(width) => { - let padded = PaddedStringDisplay { - str: &buf, - width: *width as usize, - align: *align, - truncate: *truncate, - }; - match style { - Some(s) => cur - .write_fmt(format_args!("{}", s.apply_to(padded))) - .unwrap(), - None => cur.write_fmt(format_args!("{padded}")).unwrap(), - } - } - None => match style { - Some(s) => cur.write_fmt(format_args!("{}", s.apply_to(&buf))).unwrap(), - None => cur.push_str(&buf), - }, - } - } - TemplatePart::Literal(s) => cur.push_str(s.expanded()), - TemplatePart::NewLine => { - self.push_line(lines, &mut cur, state, &mut buf, target_width, &wide); - } - } - } - - if !cur.is_empty() { - self.push_line(lines, &mut cur, state, &mut buf, target_width, &wide); - } - } - - fn push_line( - &self, - lines: &mut Vec<String>, - cur: &mut String, - state: &ProgressState, - buf: &mut String, - target_width: u16, - wide: &Option<WideElement>, - ) { - let expanded = match wide { - Some(inner) => inner.expand(mem::take(cur), self, state, buf, target_width), - None => mem::take(cur), - }; - - // If there are newlines, we need to split them up - // and add the lines separately so that they're counted - // correctly on re-render. - for (i, line) in expanded.split('\n').enumerate() { - // No newlines found in this case - if i == 0 && line.len() == expanded.len() { - lines.push(expanded); - break; - } - - lines.push(line.to_string()); - } - } -} - -struct TabRewriter<'a>(&'a mut dyn fmt::Write, usize); - -impl Write for TabRewriter<'_> { - fn write_str(&mut self, s: &str) -> fmt::Result { - self.0 - .write_str(s.replace('\t', &" ".repeat(self.1)).as_str()) - } -} - -#[derive(Clone, Copy)] -enum WideElement<'a> { - Bar { alt_style: &'a Option<Style> }, - Message { align: &'a Alignment }, -} - -impl<'a> WideElement<'a> { - fn expand( - self, - cur: String, - style: &ProgressStyle, - state: &ProgressState, - buf: &mut String, - width: u16, - ) -> String { - let left = (width as usize).saturating_sub(measure_text_width(&cur.replace('\x00', ""))); - match self { - Self::Bar { alt_style } => cur.replace( - '\x00', - &format!( - "{}", - style.format_bar(state.fraction(), left, alt_style.as_ref()) - ), - ), - WideElement::Message { align } => { - buf.clear(); - buf.write_fmt(format_args!( - "{}", - PaddedStringDisplay { - str: state.message.expanded(), - width: left, - align: *align, - truncate: true, - } - )) - .unwrap(); - - let trimmed = match cur.as_bytes().last() == Some(&b'\x00') { - true => buf.trim_end(), - false => buf, - }; - - cur.replace('\x00', trimmed) - } - } - } -} - -#[derive(Clone, Debug)] -struct Template { - parts: Vec<TemplatePart>, -} - -impl Template { - fn from_str_with_tab_width(s: &str, tab_width: usize) -> Result<Self, TemplateError> { - use State::*; - let (mut state, mut parts, mut buf) = (Literal, vec![], String::new()); - for c in s.chars() { - let new = match (state, c) { - (Literal, '{') => (MaybeOpen, None), - (Literal, '\n') => { - if !buf.is_empty() { - parts.push(TemplatePart::Literal(TabExpandedString::new( - mem::take(&mut buf).into(), - tab_width, - ))); - } - parts.push(TemplatePart::NewLine); - (Literal, None) - } - (Literal, '}') => (DoubleClose, Some('}')), - (Literal, c) => (Literal, Some(c)), - (DoubleClose, '}') => (Literal, None), - (MaybeOpen, '{') => (Literal, Some('{')), - (MaybeOpen | Key, c) if c.is_ascii_whitespace() => { - // If we find whitespace where the variable key is supposed to go, - // backtrack and act as if this was a literal. - buf.push(c); - let mut new = String::from("{"); - new.push_str(&buf); - buf.clear(); - parts.push(TemplatePart::Literal(TabExpandedString::new( - new.into(), - tab_width, - ))); - (Literal, None) - } - (MaybeOpen, c) if c != '}' && c != ':' => (Key, Some(c)), - (Key, c) if c != '}' && c != ':' => (Key, Some(c)), - (Key, ':') => (Align, None), - (Key, '}') => (Literal, None), - (Key, '!') if !buf.is_empty() => { - parts.push(TemplatePart::Placeholder { - key: mem::take(&mut buf), - align: Alignment::Left, - width: None, - truncate: true, - style: None, - alt_style: None, - }); - (Width, None) - } - (Align, c) if c == '<' || c == '^' || c == '>' => { - if let Some(TemplatePart::Placeholder { align, .. }) = parts.last_mut() { - match c { - '<' => *align = Alignment::Left, - '^' => *align = Alignment::Center, - '>' => *align = Alignment::Right, - _ => (), - } - } - - (Width, None) - } - (Align, c @ '0'..='9') => (Width, Some(c)), - (Align | Width, '!') => { - if let Some(TemplatePart::Placeholder { truncate, .. }) = parts.last_mut() { - *truncate = true; - } - (Width, None) - } - (Align, '.') => (FirstStyle, None), - (Align, '}') => (Literal, None), - (Width, c @ '0'..='9') => (Width, Some(c)), - (Width, '.') => (FirstStyle, None), - (Width, '}') => (Literal, None), - (FirstStyle, '/') => (AltStyle, None), - (FirstStyle, '}') => (Literal, None), - (FirstStyle, c) => (FirstStyle, Some(c)), - (AltStyle, '}') => (Literal, None), - (AltStyle, c) => (AltStyle, Some(c)), - (st, c) => return Err(TemplateError { next: c, state: st }), - }; - - match (state, new.0) { - (MaybeOpen, Key) if !buf.is_empty() => parts.push(TemplatePart::Literal( - TabExpandedString::new(mem::take(&mut buf).into(), tab_width), - )), - (Key, Align | Literal) if !buf.is_empty() => { - parts.push(TemplatePart::Placeholder { - key: mem::take(&mut buf), - align: Alignment::Left, - width: None, - truncate: false, - style: None, - alt_style: None, - }); - } - (Width, FirstStyle | Literal) if !buf.is_empty() => { - if let Some(TemplatePart::Placeholder { width, .. }) = parts.last_mut() { - *width = Some(buf.parse().unwrap()); - buf.clear(); - } - } - (FirstStyle, AltStyle | Literal) if !buf.is_empty() => { - if let Some(TemplatePart::Placeholder { style, .. }) = parts.last_mut() { - *style = Some(Style::from_dotted_str(&buf)); - buf.clear(); - } - } - (AltStyle, Literal) if !buf.is_empty() => { - if let Some(TemplatePart::Placeholder { alt_style, .. }) = parts.last_mut() { - *alt_style = Some(Style::from_dotted_str(&buf)); - buf.clear(); - } - } - (_, _) => (), - } - - state = new.0; - if let Some(c) = new.1 { - buf.push(c); - } - } - - if matches!(state, Literal | DoubleClose) && !buf.is_empty() { - parts.push(TemplatePart::Literal(TabExpandedString::new( - buf.into(), - tab_width, - ))); - } - - Ok(Self { parts }) - } - - fn from_str(s: &str) -> Result<Self, TemplateError> { - Self::from_str_with_tab_width(s, DEFAULT_TAB_WIDTH) - } - - fn set_tab_width(&mut self, new_tab_width: usize) { - for part in &mut self.parts { - if let TemplatePart::Literal(s) = part { - s.set_tab_width(new_tab_width); - } - } - } -} - -#[derive(Debug)] -pub struct TemplateError { - state: State, - next: char, -} - -impl fmt::Display for TemplateError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "TemplateError: unexpected character {:?} in state {:?}", - self.next, self.state - ) - } -} - -impl std::error::Error for TemplateError {} - -#[derive(Clone, Debug, PartialEq, Eq)] -enum TemplatePart { - Literal(TabExpandedString), - Placeholder { - key: String, - align: Alignment, - width: Option<u16>, - truncate: bool, - style: Option<Style>, - alt_style: Option<Style>, - }, - NewLine, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -enum State { - Literal, - MaybeOpen, - DoubleClose, - Key, - Align, - Width, - FirstStyle, - AltStyle, -} - -struct BarDisplay<'a> { - chars: &'a [Box<str>], - filled: usize, - cur: Option<usize>, - rest: console::StyledObject<RepeatedStringDisplay<'a>>, -} - -impl<'a> fmt::Display for BarDisplay<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for _ in 0..self.filled { - f.write_str(&self.chars[0])?; - } - if let Some(cur) = self.cur { - f.write_str(&self.chars[cur])?; - } - self.rest.fmt(f) - } -} - -struct RepeatedStringDisplay<'a> { - str: &'a str, - num: usize, -} - -impl<'a> fmt::Display for RepeatedStringDisplay<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for _ in 0..self.num { - f.write_str(self.str)?; - } - Ok(()) - } -} - -struct PaddedStringDisplay<'a> { - str: &'a str, - width: usize, - align: Alignment, - truncate: bool, -} - -impl<'a> fmt::Display for PaddedStringDisplay<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let cols = measure_text_width(self.str); - let excess = cols.saturating_sub(self.width); - if excess > 0 && !self.truncate { - return f.write_str(self.str); - } else if excess > 0 { - let (start, end) = match self.align { - Alignment::Left => (0, self.str.len() - excess), - Alignment::Right => (excess, self.str.len()), - Alignment::Center => ( - excess / 2, - self.str.len() - excess.saturating_sub(excess / 2), - ), - }; - - return f.write_str(self.str.get(start..end).unwrap_or(self.str)); - } - - let diff = self.width.saturating_sub(cols); - let (left_pad, right_pad) = match self.align { - Alignment::Left => (0, diff), - Alignment::Right => (diff, 0), - Alignment::Center => (diff / 2, diff.saturating_sub(diff / 2)), - }; - - for _ in 0..left_pad { - f.write_char(' ')?; - } - f.write_str(self.str)?; - for _ in 0..right_pad { - f.write_char(' ')?; - } - Ok(()) - } -} - -#[derive(PartialEq, Eq, Debug, Copy, Clone)] -enum Alignment { - Left, - Center, - Right, -} - -/// Trait for defining stateful or stateless formatters -pub trait ProgressTracker: Send + Sync { - /// Creates a new instance of the progress tracker - fn clone_box(&self) -> Box<dyn ProgressTracker>; - /// Notifies the progress tracker of a tick event - fn tick(&mut self, state: &ProgressState, now: Instant); - /// Notifies the progress tracker of a reset event - fn reset(&mut self, state: &ProgressState, now: Instant); - /// Provides access to the progress bar display buffer for custom messages - fn write(&self, state: &ProgressState, w: &mut dyn fmt::Write); -} - -impl Clone for Box<dyn ProgressTracker> { - fn clone(&self) -> Self { - self.clone_box() - } -} - -impl<F> ProgressTracker for F -where - F: Fn(&ProgressState, &mut dyn fmt::Write) + Send + Sync + Clone + 'static, -{ - fn clone_box(&self) -> Box<dyn ProgressTracker> { - Box::new(self.clone()) - } - - fn tick(&mut self, _: &ProgressState, _: Instant) {} - - fn reset(&mut self, _: &ProgressState, _: Instant) {} - - fn write(&self, state: &ProgressState, w: &mut dyn fmt::Write) { - (self)(state, w); - } -} - -#[cfg(test)] -mod tests { - use std::sync::Arc; - - use super::*; - use crate::state::{AtomicPosition, ProgressState}; - use std::sync::Mutex; - - #[test] - fn test_stateful_tracker() { - #[derive(Debug, Clone)] - struct TestTracker(Arc<Mutex<String>>); - - impl ProgressTracker for TestTracker { - fn clone_box(&self) -> Box<dyn ProgressTracker> { - Box::new(self.clone()) - } - - fn tick(&mut self, state: &ProgressState, _: Instant) { - let mut m = self.0.lock().unwrap(); - m.clear(); - m.push_str(format!("{} {}", state.len().unwrap(), state.pos()).as_str()); - } - - fn reset(&mut self, _state: &ProgressState, _: Instant) { - let mut m = self.0.lock().unwrap(); - m.clear(); - } - - fn write(&self, _state: &ProgressState, w: &mut dyn fmt::Write) { - w.write_str(self.0.lock().unwrap().as_str()).unwrap(); - } - } - - use crate::ProgressBar; - - let pb = ProgressBar::new(1); - pb.set_style( - ProgressStyle::with_template("{{ {foo} }}") - .unwrap() - .with_key("foo", TestTracker(Arc::new(Mutex::new(String::default())))) - .progress_chars("#>-"), - ); - - let mut buf = Vec::new(); - let style = pb.clone().style(); - - style.format_state(&pb.state().state, &mut buf, 16); - assert_eq!(&buf[0], "{ }"); - buf.clear(); - pb.inc(1); - style.format_state(&pb.state().state, &mut buf, 16); - assert_eq!(&buf[0], "{ 1 1 }"); - pb.reset(); - buf.clear(); - style.format_state(&pb.state().state, &mut buf, 16); - assert_eq!(&buf[0], "{ }"); - pb.finish_and_clear(); - } - - use crate::state::TabExpandedString; - - #[test] - fn test_expand_template() { - const WIDTH: u16 = 80; - let pos = Arc::new(AtomicPosition::new()); - let state = ProgressState::new(Some(10), pos); - let mut buf = Vec::new(); - - let mut style = ProgressStyle::default_bar(); - style.format_map.insert( - "foo", - Box::new(|_: &ProgressState, w: &mut dyn Write| write!(w, "FOO").unwrap()), - ); - style.format_map.insert( - "bar", - Box::new(|_: &ProgressState, w: &mut dyn Write| write!(w, "BAR").unwrap()), - ); - - style.template = Template::from_str("{{ {foo} {bar} }}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "{ FOO BAR }"); - - buf.clear(); - style.template = Template::from_str(r#"{ "foo": "{foo}", "bar": {bar} }"#).unwrap(); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], r#"{ "foo": "FOO", "bar": BAR }"#); - } - - #[test] - fn test_expand_template_flags() { - use console::set_colors_enabled; - set_colors_enabled(true); - - const WIDTH: u16 = 80; - let pos = Arc::new(AtomicPosition::new()); - let state = ProgressState::new(Some(10), pos); - let mut buf = Vec::new(); - - let mut style = ProgressStyle::default_bar(); - style.format_map.insert( - "foo", - Box::new(|_: &ProgressState, w: &mut dyn Write| write!(w, "XXX").unwrap()), - ); - - style.template = Template::from_str("{foo:5}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "XXX "); - - buf.clear(); - style.template = Template::from_str("{foo:.red.on_blue}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "\u{1b}[31m\u{1b}[44mXXX\u{1b}[0m"); - - buf.clear(); - style.template = Template::from_str("{foo:^5.red.on_blue}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "\u{1b}[31m\u{1b}[44m XXX \u{1b}[0m"); - - buf.clear(); - style.template = Template::from_str("{foo:^5.red.on_blue/green.on_cyan}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "\u{1b}[31m\u{1b}[44m XXX \u{1b}[0m"); - } - - #[test] - fn align_truncation() { - const WIDTH: u16 = 10; - let pos = Arc::new(AtomicPosition::new()); - let mut state = ProgressState::new(Some(10), pos); - let mut buf = Vec::new(); - - let style = ProgressStyle::with_template("{wide_msg}").unwrap(); - state.message = TabExpandedString::NoTabs("abcdefghijklmnopqrst".into()); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "abcdefghij"); - - buf.clear(); - let style = ProgressStyle::with_template("{wide_msg:>}").unwrap(); - state.message = TabExpandedString::NoTabs("abcdefghijklmnopqrst".into()); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "klmnopqrst"); - - buf.clear(); - let style = ProgressStyle::with_template("{wide_msg:^}").unwrap(); - state.message = TabExpandedString::NoTabs("abcdefghijklmnopqrst".into()); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "fghijklmno"); - } - - #[test] - fn wide_element_style() { - const CHARS: &str = "=>-"; - const WIDTH: u16 = 8; - let pos = Arc::new(AtomicPosition::new()); - // half finished - pos.set(2); - let mut state = ProgressState::new(Some(4), pos); - let mut buf = Vec::new(); - - let style = ProgressStyle::with_template("{wide_bar}") - .unwrap() - .progress_chars(CHARS); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "====>---"); - - buf.clear(); - let style = ProgressStyle::with_template("{wide_bar:.red.on_blue/green.on_cyan}") - .unwrap() - .progress_chars(CHARS); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!( - &buf[0], - "\u{1b}[31m\u{1b}[44m====>\u{1b}[32m\u{1b}[46m---\u{1b}[0m\u{1b}[0m" - ); - - buf.clear(); - let style = ProgressStyle::with_template("{wide_msg:^.red.on_blue}").unwrap(); - state.message = TabExpandedString::NoTabs("foobar".into()); - style.format_state(&state, &mut buf, WIDTH); - assert_eq!(&buf[0], "\u{1b}[31m\u{1b}[44m foobar \u{1b}[0m"); - } - - #[test] - fn multiline_handling() { - const WIDTH: u16 = 80; - let pos = Arc::new(AtomicPosition::new()); - let mut state = ProgressState::new(Some(10), pos); - let mut buf = Vec::new(); - - let mut style = ProgressStyle::default_bar(); - state.message = TabExpandedString::new("foo\nbar\nbaz".into(), 2); - style.template = Template::from_str("{msg}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - - assert_eq!(buf.len(), 3); - assert_eq!(&buf[0], "foo"); - assert_eq!(&buf[1], "bar"); - assert_eq!(&buf[2], "baz"); - - buf.clear(); - style.template = Template::from_str("{wide_msg}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - - assert_eq!(buf.len(), 3); - assert_eq!(&buf[0], "foo"); - assert_eq!(&buf[1], "bar"); - assert_eq!(&buf[2], "baz"); - - buf.clear(); - state.prefix = TabExpandedString::new("prefix\nprefix".into(), 2); - style.template = Template::from_str("{prefix} {wide_msg}").unwrap(); - style.format_state(&state, &mut buf, WIDTH); - - assert_eq!(buf.len(), 4); - assert_eq!(&buf[0], "prefix"); - assert_eq!(&buf[1], "prefix foo"); - assert_eq!(&buf[2], "bar"); - assert_eq!(&buf[3], "baz"); - } -} diff --git a/vendor/indicatif/src/term_like.rs b/vendor/indicatif/src/term_like.rs deleted file mode 100644 index b489b65..0000000 --- a/vendor/indicatif/src/term_like.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::fmt::Debug; -use std::io; - -use console::Term; - -/// A trait for minimal terminal-like behavior. -/// -/// Anything that implements this trait can be used a draw target via [`ProgressDrawTarget::term_like`]. -/// -/// [`ProgressDrawTarget::term_like`]: crate::ProgressDrawTarget::term_like -pub trait TermLike: Debug + Send + Sync { - /// Return the terminal width - fn width(&self) -> u16; - /// Return the terminal height - fn height(&self) -> u16 { - // FIXME: remove this default impl in the next major version bump - 20 // sensible default - } - - /// Move the cursor up by `n` lines - fn move_cursor_up(&self, n: usize) -> io::Result<()>; - /// Move the cursor down by `n` lines - fn move_cursor_down(&self, n: usize) -> io::Result<()>; - /// Move the cursor right by `n` chars - fn move_cursor_right(&self, n: usize) -> io::Result<()>; - /// Move the cursor left by `n` chars - fn move_cursor_left(&self, n: usize) -> io::Result<()>; - - /// Write a string and add a newline. - fn write_line(&self, s: &str) -> io::Result<()>; - /// Write a string - fn write_str(&self, s: &str) -> io::Result<()>; - /// Clear the current line and reset the cursor to beginning of the line - fn clear_line(&self) -> io::Result<()>; - - fn flush(&self) -> io::Result<()>; -} - -impl TermLike for Term { - fn width(&self) -> u16 { - self.size().1 - } - - fn height(&self) -> u16 { - self.size().0 - } - - fn move_cursor_up(&self, n: usize) -> io::Result<()> { - self.move_cursor_up(n) - } - - fn move_cursor_down(&self, n: usize) -> io::Result<()> { - self.move_cursor_down(n) - } - - fn move_cursor_right(&self, n: usize) -> io::Result<()> { - self.move_cursor_right(n) - } - - fn move_cursor_left(&self, n: usize) -> io::Result<()> { - self.move_cursor_left(n) - } - - fn write_line(&self, s: &str) -> io::Result<()> { - self.write_line(s) - } - - fn write_str(&self, s: &str) -> io::Result<()> { - self.write_str(s) - } - - fn clear_line(&self) -> io::Result<()> { - self.clear_line() - } - - fn flush(&self) -> io::Result<()> { - self.flush() - } -} diff --git a/vendor/indicatif/tests/multi-autodrop.rs b/vendor/indicatif/tests/multi-autodrop.rs deleted file mode 100644 index 5589ad6..0000000 --- a/vendor/indicatif/tests/multi-autodrop.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::thread; -use std::time::Duration; - -use indicatif::{MultiProgress, ProgressBar}; - -#[test] -fn main() { - let pb = { - let m = MultiProgress::new(); - m.add(ProgressBar::new(10)) - // The MultiProgress is dropped here. - }; - - { - #[allow(clippy::redundant_clone)] - let pb2 = pb.clone(); - for _ in 0..10 { - pb2.inc(1); - thread::sleep(Duration::from_millis(50)); - } - } - - pb.set_message("Done"); - pb.finish(); - - println!("Done with MultiProgress"); -} diff --git a/vendor/indicatif/tests/render.rs b/vendor/indicatif/tests/render.rs deleted file mode 100644 index a891e72..0000000 --- a/vendor/indicatif/tests/render.rs +++ /dev/null @@ -1,1822 +0,0 @@ -#![cfg(feature = "in_memory")] - -use std::time::Duration; - -use indicatif::{ - InMemoryTerm, MultiProgress, MultiProgressAlignment, ProgressBar, ProgressDrawTarget, - ProgressFinish, ProgressStyle, TermLike, -}; -use pretty_assertions::assert_eq; - -#[test] -fn basic_progress_bar() { - let in_mem = InMemoryTerm::new(10, 80); - let pb = ProgressBar::with_draw_target( - Some(10), - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ); - - assert_eq!(in_mem.contents(), String::new()); - - pb.tick(); - assert_eq!( - in_mem.contents(), - "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10" - ); - - pb.inc(1); - assert_eq!( - in_mem.contents(), - "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 1/10" - ); - - pb.finish(); - assert_eq!( - in_mem.contents(), - "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10" - ); -} - -#[test] -fn progress_bar_builder_method_order() { - let in_mem = InMemoryTerm::new(10, 80); - // Test that `with_style` doesn't overwrite the message or prefix - let pb = ProgressBar::with_draw_target( - Some(10), - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ) - .with_message("crate") - .with_prefix("Downloading") - .with_style( - ProgressStyle::with_template("{prefix:>12.cyan.bold} {msg}: {wide_bar} {pos}/{len}") - .unwrap(), - ); - - assert_eq!(in_mem.contents(), String::new()); - - pb.tick(); - assert_eq!( - in_mem.contents(), - " Downloading crate: βββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10" - ); -} - -#[test] -fn progress_bar_percent_with_no_length() { - let in_mem = InMemoryTerm::new(10, 80); - let pb = ProgressBar::with_draw_target( - None, - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ) - .with_style(ProgressStyle::with_template("{wide_bar} {percent}%").unwrap()); - - assert_eq!(in_mem.contents(), String::new()); - - pb.tick(); - - assert_eq!( - in_mem.contents(), - "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0%" - ); - - pb.set_length(10); - - pb.inc(1); - assert_eq!( - in_mem.contents(), - "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10%" - ); - - pb.finish(); - assert_eq!( - in_mem.contents(), - "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 100%" - ); -} - -#[test] -fn multi_progress_single_bar_and_leave() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10).with_finish(ProgressFinish::AndLeave)); - - assert_eq!(in_mem.contents(), String::new()); - - pb1.tick(); - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - - drop(pb1); - assert_eq!( - in_mem.contents(), - r#"ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10"# - ); -} - -#[test] -fn multi_progress_single_bar_and_clear() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10)); - - assert_eq!(in_mem.contents(), String::new()); - - pb1.tick(); - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - - drop(pb1); - assert_eq!(in_mem.contents(), ""); -} -#[test] -fn multi_progress_two_bars() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10).with_finish(ProgressFinish::AndLeave)); - let pb2 = mp.add(ProgressBar::new(5)); - - assert_eq!(in_mem.contents(), String::new()); - - pb1.tick(); - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - - pb2.tick(); - - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/5"# - .trim_start() - ); - - drop(pb1); - assert_eq!( - in_mem.contents(), - r#" -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/5"# - .trim_start() - ); - - drop(pb2); - - assert_eq!( - in_mem.contents(), - r#"ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10"# - ); -} - -#[test] -fn multi_progress() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10).with_finish(ProgressFinish::AndLeave)); - let pb2 = mp.add(ProgressBar::new(5)); - let pb3 = mp.add(ProgressBar::new(100)); - - assert_eq!(in_mem.contents(), String::new()); - - pb1.tick(); - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - - pb2.tick(); - - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/5"# - .trim_start() - ); - - pb3.tick(); - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/5 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/100"# - .trim_start() - ); - - drop(pb1); - assert_eq!( - in_mem.contents(), - r#" -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/5 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/100"# - .trim_start() - ); - - drop(pb2); - assert_eq!( - in_mem.contents(), - r#" -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/100"# - .trim_start() - ); - - drop(pb3); - - assert_eq!( - in_mem.contents(), - r#"ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10"# - ); -} - -#[test] -fn multi_progress_println() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10)); - let pb2 = mp.add(ProgressBar::new(5)); - let pb3 = mp.add(ProgressBar::new(100)); - - assert_eq!(in_mem.contents(), ""); - - pb1.inc(2); - mp.println("message printed :)").unwrap(); - - assert_eq!( - in_mem.contents(), - r#" -message printed :) -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 2/10 - "# - .trim() - ); - - mp.println("another great message!").unwrap(); - assert_eq!( - in_mem.contents(), - r#" -message printed :) -another great message! -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 2/10 - "# - .trim() - ); - - pb2.inc(1); - pb3.tick(); - mp.println("one last message").unwrap(); - - assert_eq!( - in_mem.contents(), - r#" -message printed :) -another great message! -one last message -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 2/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 1/5 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/100 - "# - .trim() - ); - - drop(pb1); - drop(pb2); - drop(pb3); - - assert_eq!( - in_mem.contents(), - r#" -message printed :) -another great message! -one last message"# - .trim() - ); -} - -#[test] -fn multi_progress_suspend() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10)); - let pb2 = mp.add(ProgressBar::new(10)); - - assert_eq!(in_mem.contents(), ""); - - pb1.inc(2); - mp.println("message printed :)").unwrap(); - - assert_eq!( - in_mem.contents(), - r#" -message printed :) -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 2/10 - "# - .trim() - ); - - mp.suspend(|| { - in_mem.write_line("This is write_line output!").unwrap(); - in_mem.write_line("And so is this").unwrap(); - in_mem.move_cursor_down(1).unwrap(); - }); - - assert_eq!( - in_mem.contents(), - r#" -message printed :) -This is write_line output! -And so is this - -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 2/10 - "# - .trim() - ); - - pb2.inc(1); - mp.println("Another line printed").unwrap(); - - assert_eq!( - in_mem.contents(), - r#" -message printed :) -This is write_line output! -And so is this - -Another line printed -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 2/10 -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 1/10 - "# - .trim() - ); - - drop(pb1); - drop(pb2); - - assert_eq!( - in_mem.contents(), - r#" -message printed :) -This is write_line output! -And so is this - -Another line printed"# - .trim() - ); -} - -#[test] -fn ticker_drop() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let mut spinner: Option<ProgressBar> = None; - - for i in 0..5 { - let new_spinner = mp.add( - ProgressBar::new_spinner() - .with_finish(ProgressFinish::AndLeave) - .with_message(format!("doing stuff {i}")), - ); - new_spinner.enable_steady_tick(Duration::from_millis(100)); - spinner.replace(new_spinner); - } - - drop(spinner); - assert_eq!( - in_mem.contents(), - " doing stuff 0\n doing stuff 1\n doing stuff 2\n doing stuff 3\n doing stuff 4" - ); -} - -#[test] -fn manually_inc_ticker() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let spinner = mp.add(ProgressBar::new_spinner().with_message("msg")); - - assert_eq!(in_mem.contents(), ""); - - spinner.inc(1); - assert_eq!(in_mem.contents(), "β msg"); - - spinner.inc(1); - assert_eq!(in_mem.contents(), "β msg"); - - // set_message / set_prefix shouldn't increase tick - spinner.set_message("new message"); - spinner.set_prefix("prefix"); - assert_eq!(in_mem.contents(), "β new message"); -} - -#[test] -fn multi_progress_prune_zombies() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb0 = mp - .add(ProgressBar::new(10)) - .with_finish(ProgressFinish::AndLeave); - let pb1 = mp.add(ProgressBar::new(15)); - pb0.tick(); - assert_eq!( - in_mem.contents(), - "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10" - ); - - pb0.inc(1); - assert_eq!( - in_mem.contents(), - "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 1/10" - ); - - drop(pb0); - - // Clear the screen - mp.clear().unwrap(); - - // Write a line that we expect to remain. This helps ensure the adjustment to last_line_count is - // working as expected, and `MultiState` isn't erasing lines when it shouldn't. - in_mem.write_line("don't erase me plz").unwrap(); - - // pb0 is dead, so only pb1 should be drawn from now on - pb1.tick(); - assert_eq!( - in_mem.contents(), - "don't erase me plz\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/15" - ); -} - -#[test] -fn multi_progress_prune_zombies_2() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10).with_finish(ProgressFinish::AndLeave)); - let pb2 = mp.add(ProgressBar::new(5)); - let pb3 = mp - .add(ProgressBar::new(100)) - .with_finish(ProgressFinish::Abandon); - let pb4 = mp - .add(ProgressBar::new(500)) - .with_finish(ProgressFinish::AndLeave); - let pb5 = mp.add(ProgressBar::new(7)); - - assert_eq!(in_mem.contents(), String::new()); - - pb1.tick(); - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - - pb2.tick(); - - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/5"# - .trim_start() - ); - - pb3.tick(); - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/5 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/100"# - .trim_start() - ); - - drop(pb1); - drop(pb2); - drop(pb3); - - assert_eq!( - in_mem.contents(), - r#" -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10 -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/100"# - .trim_start() - ); - - mp.clear().unwrap(); - - assert_eq!(in_mem.contents(), ""); - - // A sacrificial line we expect shouldn't be touched - in_mem.write_line("don't erase plz").unwrap(); - - mp.println("Test friend :)").unwrap(); - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :)"# - .trim_start() - ); - - pb4.tick(); - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :) -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/500"# - .trim_start() - ); - - drop(pb4); - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :) -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 500/500"# - .trim_start() - ); - - mp.clear().unwrap(); - assert_eq!(in_mem.contents(), "don't erase plz\nTest friend :)"); - - pb5.tick(); - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :) -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/7"# - .trim_start() - ); - - mp.println("not your friend, buddy").unwrap(); - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :) -not your friend, buddy -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/7"# - .trim_start() - ); - - pb5.inc(1); - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :) -not your friend, buddy -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 1/7"# - .trim_start() - ); - - mp.clear().unwrap(); - in_mem.write_line("don't erase me either").unwrap(); - - pb5.inc(1); - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :) -not your friend, buddy -don't erase me either -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 2/7"# - .trim_start() - ); - - drop(pb5); - - assert_eq!( - in_mem.contents(), - r#" -don't erase plz -Test friend :) -not your friend, buddy -don't erase me either"# - .trim_start() - ); -} - -#[test] -fn basic_tab_expansion() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let mut spinner = mp.add(ProgressBar::new_spinner().with_message("Test\t:)")); - spinner.tick(); - - // 8 is the default number of spaces - assert_eq!(in_mem.contents(), "β Test :)"); - - spinner.set_tab_width(4); - assert_eq!(in_mem.contents(), "β Test :)"); -} - -#[test] -fn tab_expansion_in_template() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let mut spinner = mp.add( - ProgressBar::new_spinner() - .with_message("Test\t:)") - .with_prefix("Pre\tfix!") - .with_style(ProgressStyle::with_template("{spinner}{prefix}\t{msg}").unwrap()), - ); - - spinner.tick(); - assert_eq!(in_mem.contents(), "β Pre fix! Test :)"); - - spinner.set_tab_width(4); - assert_eq!(in_mem.contents(), "β Pre fix! Test :)"); - - spinner.set_tab_width(2); - assert_eq!(in_mem.contents(), "β Pre fix! Test :)"); -} - -#[test] -fn progress_style_tab_width_unification() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - // Style will have default of 8 spaces for tabs - let style = ProgressStyle::with_template("{msg}\t{msg}").unwrap(); - - let spinner = mp.add( - ProgressBar::new_spinner() - .with_message("OK") - .with_tab_width(4), - ); - - // Setting the spinner's style to |style| should override the style's tab width with that of bar - spinner.set_style(style); - spinner.tick(); - assert_eq!(in_mem.contents(), "OK OK"); -} - -#[test] -fn multi_progress_clear_println() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - mp.println("Test of println").unwrap(); - // Should have no effect - mp.clear().unwrap(); - assert_eq!(in_mem.contents(), "Test of println"); -} - -#[test] -fn multi_progress_clear_zombies_no_ticks() { - _multi_progress_clear_zombies(0); -} - -#[test] -fn multi_progress_clear_zombies_one_tick() { - _multi_progress_clear_zombies(1); -} - -#[test] -fn multi_progress_clear_zombies_two_ticks() { - _multi_progress_clear_zombies(2); -} - -// In the old (broken) implementation, zombie handling sometimes worked differently depending on -// how many draws were between certain operations. Let's make sure that doesn't happen again. -fn _multi_progress_clear_zombies(ticks: usize) { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - let style = ProgressStyle::with_template("{msg}").unwrap(); - - let pb1 = mp.add( - ProgressBar::new_spinner() - .with_style(style.clone()) - .with_message("pb1"), - ); - pb1.tick(); - - let pb2 = mp.add( - ProgressBar::new_spinner() - .with_style(style) - .with_message("pb2"), - ); - - pb2.tick(); - assert_eq!(in_mem.contents(), "pb1\npb2"); - - pb1.finish_with_message("pb1 done"); - drop(pb1); - assert_eq!(in_mem.contents(), "pb1 done\npb2"); - - for _ in 0..ticks { - pb2.tick(); - } - - mp.clear().unwrap(); - assert_eq!(in_mem.contents(), ""); -} - -// This test reproduces examples/multi.rs in a simpler form -#[test] -fn multi_zombie_handling() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - let style = ProgressStyle::with_template("{msg}").unwrap(); - - let pb1 = mp.add( - ProgressBar::new_spinner() - .with_style(style.clone()) - .with_message("pb1"), - ); - pb1.tick(); - let pb2 = mp.add( - ProgressBar::new_spinner() - .with_style(style.clone()) - .with_message("pb2"), - ); - pb2.tick(); - let pb3 = mp.add( - ProgressBar::new_spinner() - .with_style(style) - .with_message("pb3"), - ); - pb3.tick(); - - mp.println("pb1 done!").unwrap(); - pb1.finish_with_message("done"); - assert_eq!(in_mem.contents(), "pb1 done!\ndone\npb2\npb3"); - drop(pb1); - - assert_eq!(in_mem.contents(), "pb1 done!\ndone\npb2\npb3"); - - pb2.tick(); - assert_eq!(in_mem.contents(), "pb1 done!\ndone\npb2\npb3"); - pb3.tick(); - assert_eq!(in_mem.contents(), "pb1 done!\ndone\npb2\npb3"); - - mp.println("pb3 done!").unwrap(); - assert_eq!(in_mem.contents(), "pb1 done!\npb3 done!\npb2\npb3"); - - pb3.finish_with_message("done"); - drop(pb3); - - pb2.tick(); - - mp.println("pb2 done!").unwrap(); - pb2.finish_with_message("done"); - drop(pb2); - - assert_eq!( - in_mem.contents(), - "pb1 done!\npb3 done!\npb2 done!\ndone\ndone" - ); - - mp.clear().unwrap(); - - assert_eq!(in_mem.contents(), "pb1 done!\npb3 done!\npb2 done!"); -} - -#[test] -fn multi_progress_multiline_msg() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new_spinner().with_message("test1")); - let pb2 = mp.add(ProgressBar::new_spinner().with_message("test2")); - - assert_eq!(in_mem.contents(), ""); - - pb1.inc(1); - pb2.inc(1); - - assert_eq!( - in_mem.contents(), - r#" -β test1 -β test2 - "# - .trim() - ); - - pb1.set_message("test1\n test1 line2\n test1 line3"); - - assert_eq!( - in_mem.contents(), - r#" -β test1 - test1 line2 - test1 line3 -β test2 - "# - .trim() - ); - - pb1.inc(1); - pb2.inc(1); - - assert_eq!( - in_mem.contents(), - r#" -β test1 - test1 line2 - test1 line3 -β test2 - "# - .trim() - ); - - pb2.set_message("test2\n test2 line2"); - - assert_eq!( - in_mem.contents(), - r#" -β test1 - test1 line2 - test1 line3 -β test2 - test2 line2 - "# - .trim() - ); - - pb1.set_message("single line again"); - - assert_eq!( - in_mem.contents(), - r#" -β single line again -β test2 - test2 line2 - "# - .trim() - ); - - pb1.finish_with_message("test1 done!"); - pb2.finish_with_message("test2 done!"); - - assert_eq!( - in_mem.contents(), - r#" test1 done! - test2 done!"# - ); -} - -#[test] -fn multi_progress_bottom_alignment() { - let in_mem = InMemoryTerm::new(10, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - mp.set_alignment(MultiProgressAlignment::Bottom); - - let pb1 = mp.add(ProgressBar::new_spinner().with_message("test1")); - let pb2 = mp.add(ProgressBar::new_spinner().with_message("test2")); - - pb1.tick(); - pb2.tick(); - pb1.finish_and_clear(); - - assert_eq!(in_mem.contents(), "\nβ test2"); - - pb2.finish_and_clear(); - // `InMemoryTerm::contents` normally gets rid of trailing newlines, so write some text to ensure - // the newlines are seen. - in_mem.write_line("anchor").unwrap(); - assert_eq!(in_mem.contents(), "\n\nanchor"); -} - -#[test] -fn progress_bar_terminal_wrap() { - use std::cmp::min; - let in_mem = InMemoryTerm::new(10, 20); - - let mut downloaded = 0; - let total_size = 231231231; - - let pb = ProgressBar::with_draw_target( - None, - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ); - pb.set_style(ProgressStyle::default_bar() - .template("{msg:>12.cyan.bold} {spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {bytes}/{total_bytes}").unwrap() - .progress_chars("#>-")); - - pb.set_message("Downloading"); - assert_eq!( - in_mem.contents(), - r#" Downloading β [00:0 -0:00] [------------- --------------------- --------] 0 B/0 B"# - ); - - let new = min(downloaded + 223211, total_size); - downloaded = new; - pb.set_position(new); - assert_eq!( - in_mem.contents(), - r#" Downloading β [00:0 -0:00] [------------- --------------------- --------] 217.98 KiB/ -217.98 KiB"# - ); - - let new = min(downloaded + 223211, total_size); - pb.set_position(new); - assert_eq!( - in_mem.contents(), - r#" Downloading β [00:0 -0:00] [------------- --------------------- --------] 435.96 KiB/ -435.96 KiB"# - ); - - pb.set_style( - ProgressStyle::default_bar() - .template("{msg:>12.green.bold} downloading {total_bytes:.green} in {elapsed:.green}") - .unwrap(), - ); - pb.finish_with_message("Finished"); - assert_eq!( - in_mem.contents(), - r#" Finished downloa -ding 435.96 KiB in 0 -s"# - ); - - println!("{:?}", in_mem.contents()) -} - -#[test] -fn spinner_terminal_cleared_log_line_with_ansi_codes() { - let in_mem = InMemoryTerm::new(10, 100); - - let pb = ProgressBar::with_draw_target( - Some(10), - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ); - pb.set_style(ProgressStyle::default_spinner()); - assert_eq!(in_mem.contents(), String::new()); - - pb.finish_and_clear(); - // Visually empty, but consists of an ANSII code - pb.println("\u{1b}[1m"); - - pb.println("text\u{1b}[0m"); - assert_eq!(in_mem.contents(), "\ntext"); -} - -#[test] -fn multi_progress_println_terminal_wrap() { - let in_mem = InMemoryTerm::new(10, 48); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10)); - let pb2 = mp.add(ProgressBar::new(5)); - let pb3 = mp.add(ProgressBar::new(100)); - - assert_eq!(in_mem.contents(), ""); - - pb1.inc(2); - mp.println("message printed that is longer than terminal width :)") - .unwrap(); - assert_eq!( - in_mem.contents(), - r#"message printed that is longer than terminal wid -th :) -βββββββββββββββββββββββββββββββββββββββββββ 2/10"# - ); - - mp.println("another great message!").unwrap(); - assert_eq!( - in_mem.contents(), - r#"message printed that is longer than terminal wid -th :) -another great message! -βββββββββββββββββββββββββββββββββββββββββββ 2/10"# - ); - - pb2.inc(1); - pb3.tick(); - mp.println("one last message but this one is also longer than terminal width") - .unwrap(); - - assert_eq!( - in_mem.contents(), - r#"message printed that is longer than terminal wid -th :) -another great message! -one last message but this one is also longer tha -n terminal width -βββββββββββββββββββββββββββββββββββββββββββ 2/10 -ββββββββββββββββββββββββββββββββββββββββββββ 1/5 -ββββββββββββββββββββββββββββββββββββββββββ 0/100"# - .trim() - ); - - drop(pb1); - drop(pb2); - drop(pb3); - - assert_eq!( - in_mem.contents(), - r#"message printed that is longer than terminal wid -th :) -another great message! -one last message but this one is also longer tha -n terminal width"# - .trim() - ); -} - -#[test] -fn basic_progress_bar_newline() { - let in_mem = InMemoryTerm::new(10, 80); - let pb = ProgressBar::with_draw_target( - Some(10), - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ); - - assert_eq!(in_mem.contents(), String::new()); - - pb.println("\nhello"); - pb.tick(); - assert_eq!( - in_mem.contents(), - r#" -hello -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - - pb.inc(1); - pb.println(""); - assert_eq!( - in_mem.contents(), - r#" -hello - -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 1/10"# - ); - - pb.finish(); - assert_eq!( - in_mem.contents(), - " -hello - -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10" - ); -} - -#[test] -fn multi_progress_many_bars() { - let in_mem = InMemoryTerm::new(4, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10).with_finish(ProgressFinish::AndLeave)); - let mut spinners = vec![]; - for i in 0..7 { - let spinner = ProgressBar::new_spinner().with_message(i.to_string()); - mp.add(spinner.clone()); - spinners.push(spinner); - } - - assert_eq!(in_mem.contents(), String::new()); - - pb1.tick(); - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -Flush -"# - ); - - for spinner in &spinners { - spinner.tick() - } - - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -β 0 -β 1 -β 2"# - .trim_start() - ); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Clear -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str(" ") -Flush -Up(1) -Clear -Down(1) -Clear -Up(1) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str(" ") -Flush -Up(2) -Clear -Down(1) -Clear -Down(1) -Clear -Up(2) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str(" ") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -"# - ); - - drop(pb1); - assert_eq!( - in_mem.contents(), - r#" -ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10 -β 0 -β 1 -β 2"# - .trim_start() - ); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 10/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -"# - ); - - drop(spinners); - - assert_eq!(in_mem.contents(), r#""#); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Up(2) -Clear -Down(1) -Clear -Down(1) -Clear -Up(2) -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -NewLine -Str("β 3") -Str("") -NewLine -Str("β 4") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("β 2") -Str("") -NewLine -Str("β 3") -Str("") -NewLine -Str("β 4") -Str("") -NewLine -Str("β 5") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("β 3") -Str("") -NewLine -Str("β 4") -Str("") -NewLine -Str("β 5") -Str("") -NewLine -Str("β 6") -Str(" ") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("β 4") -Str("") -NewLine -Str("β 5") -Str("") -NewLine -Str("β 6") -Str(" ") -Flush -Up(2) -Clear -Down(1) -Clear -Down(1) -Clear -Up(2) -Str("β 5") -Str("") -NewLine -Str("β 6") -Str(" ") -Flush -Up(1) -Clear -Down(1) -Clear -Up(1) -Str("β 6") -Str(" ") -Flush -Clear -Str("") -Flush -"# - ); -} - -#[test] -fn multi_progress_many_spinners() { - let in_mem = InMemoryTerm::new(4, 80); - let mp = - MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone()))); - - let pb1 = mp.add(ProgressBar::new(10).with_finish(ProgressFinish::AndLeave)); - let mut spinners = vec![]; - for i in 0..7 { - let spinner = ProgressBar::new_spinner().with_message(i.to_string()); - mp.add(spinner.clone()); - spinners.push(spinner); - } - - assert_eq!(in_mem.contents(), String::new()); - - pb1.tick(); - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -Flush -"# - ); - - for spinner in &spinners { - spinner.tick() - } - - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -β 0 -β 1 -β 2"# - .trim_start() - ); - - assert_eq!( - in_mem.moves_since_last_check(), - r#"Clear -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str(" ") -Flush -Up(1) -Clear -Down(1) -Clear -Up(1) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str(" ") -Flush -Up(2) -Clear -Down(1) -Clear -Down(1) -Clear -Up(2) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str(" ") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -"# - ); - - spinners.remove(3); - - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -β 0 -β 1 -β 2"# - .trim_start() - ); - - assert_eq!( - in_mem.moves_since_last_check(), - r#"Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -"# - ); - - spinners.remove(4); - - assert_eq!( - in_mem.contents(), - r#" -βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10 -β 0 -β 1 -β 2"# - .trim_start() - ); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 0") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -Flush -"# - ); - - drop(spinners); - - assert_eq!( - in_mem.contents(), - r#"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10"# - ); - assert_eq!( - in_mem.moves_since_last_check(), - r#"Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 1") -Str("") -NewLine -Str("β 2") -Str("") -NewLine -Str("β 4") -Str("") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 2") -Str("") -NewLine -Str("β 4") -Str("") -NewLine -Str("β 6") -Str(" ") -Flush -Up(3) -Clear -Down(1) -Clear -Down(1) -Clear -Down(1) -Clear -Up(3) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 4") -Str("") -NewLine -Str("β 6") -Str(" ") -Flush -Up(2) -Clear -Down(1) -Clear -Down(1) -Clear -Up(2) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -NewLine -Str("β 6") -Str(" ") -Flush -Up(1) -Clear -Down(1) -Clear -Up(1) -Str("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 0/10") -Str("") -Flush -"# - ); -} - -#[test] -fn orphan_lines() { - let in_mem = InMemoryTerm::new(10, 80); - - let pb = ProgressBar::with_draw_target( - Some(10), - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ); - assert_eq!(in_mem.contents(), String::new()); - - for i in 0..=10 { - if i != 0 { - pb.inc(1); - } - - let n = 5 + i; - - pb.println("\n".repeat(n)); - } - - pb.finish(); -} - -#[test] -fn orphan_lines_message_above_progress_bar() { - let in_mem = InMemoryTerm::new(10, 80); - - let pb = ProgressBar::with_draw_target( - Some(10), - ProgressDrawTarget::term_like(Box::new(in_mem.clone())), - ); - assert_eq!(in_mem.contents(), String::new()); - - for i in 0..=10 { - if i != 0 { - pb.inc(1); - } - - let n = 5 + i; - - // Test with messages of differing numbers of lines. The messages have the form: - // n - 1 newlines followed by n * 11 dashes (`-`). The value of n ranges from 5 - // (less than the terminal height) to 15 (greater than the terminal height). The - // number 11 is intentionally not a factor of the terminal width (80), but large - // enough that the strings of dashes eventually wrap. - pb.println(format!("{}{}", "\n".repeat(n - 1), "-".repeat(n * 11))); - - // Check that the line above the progress bar is a string of dashes of length - // n * 11 mod the terminal width. - assert_eq!( - format!("{}", "-".repeat(n * 11 % 80)), - in_mem.contents().lines().rev().nth(1).unwrap(), - ); - } - - pb.finish(); -} |