aboutsummaryrefslogtreecommitdiff
path: root/vendor/indicatif
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/indicatif')
-rw-r--r--vendor/indicatif/.cargo-checksum.json1
-rw-r--r--vendor/indicatif/Cargo.lock872
-rw-r--r--vendor/indicatif/Cargo.toml117
-rw-r--r--vendor/indicatif/LICENSE22
-rw-r--r--vendor/indicatif/README.md30
-rw-r--r--vendor/indicatif/deny.toml3
-rw-r--r--vendor/indicatif/examples/cargo.rs122
-rw-r--r--vendor/indicatif/examples/cargowrap.rs41
-rw-r--r--vendor/indicatif/examples/download-continued.rs29
-rw-r--r--vendor/indicatif/examples/download-speed.rs24
-rw-r--r--vendor/indicatif/examples/download.rs25
-rw-r--r--vendor/indicatif/examples/fastbar.rs23
-rw-r--r--vendor/indicatif/examples/finebars.rs43
-rw-r--r--vendor/indicatif/examples/iterator.rs31
-rw-r--r--vendor/indicatif/examples/log.rs14
-rw-r--r--vendor/indicatif/examples/long-spinner.rs27
-rw-r--r--vendor/indicatif/examples/message.rs11
-rw-r--r--vendor/indicatif/examples/morebars.rs28
-rw-r--r--vendor/indicatif/examples/multi-tree-ext.rs280
-rw-r--r--vendor/indicatif/examples/multi-tree.rs189
-rw-r--r--vendor/indicatif/examples/multi.rs67
-rw-r--r--vendor/indicatif/examples/single.rs13
-rw-r--r--vendor/indicatif/examples/slow.rs12
-rw-r--r--vendor/indicatif/examples/spinner-loop.rs18
-rw-r--r--vendor/indicatif/examples/steady.rs50
-rw-r--r--vendor/indicatif/examples/tokio.rs34
-rw-r--r--vendor/indicatif/examples/yarnish.rs97
-rw-r--r--vendor/indicatif/src/draw_target.rs561
-rw-r--r--vendor/indicatif/src/format.rs337
-rw-r--r--vendor/indicatif/src/in_memory.rs399
-rw-r--r--vendor/indicatif/src/iter.rs355
-rw-r--r--vendor/indicatif/src/lib.rs247
-rw-r--r--vendor/indicatif/src/multi.rs688
-rw-r--r--vendor/indicatif/src/progress_bar.rs808
-rw-r--r--vendor/indicatif/src/rayon.rs235
-rw-r--r--vendor/indicatif/src/state.rs798
-rw-r--r--vendor/indicatif/src/style.rs987
-rw-r--r--vendor/indicatif/src/term_like.rs79
-rw-r--r--vendor/indicatif/tests/multi-autodrop.rs27
-rw-r--r--vendor/indicatif/tests/render.rs1822
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"";
- 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();
-}