"bitflags",
]
+[[package]]
+name = "console"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45"
+dependencies = [
+ "encode_unicode",
+ "lazy_static",
+ "libc",
+ "regex",
+ "terminal_size",
+ "unicode-width",
+ "winapi 0.3.9",
+]
+
[[package]]
name = "console_error_panic_hook"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+[[package]]
+name = "encode_unicode"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+
[[package]]
name = "encoding_rs"
version = "0.8.28"
"cast_trait_object",
"chrono",
"chrono-tz",
+ "console",
"delegate",
"derive-into-owned",
"digest 0.9.0",
"typetag",
"uds",
"unicase 2.6.0",
+ "unicode-width",
"url 2.2.1",
"usvg",
"vecdeque-stableix",
"winapi-util",
]
+[[package]]
+name = "terminal_size"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406"
+dependencies = [
+ "libc",
+ "winapi 0.3.9",
+]
+
[[package]]
name = "textwrap"
version = "0.11.0"
--- /dev/null
+// Copyright 2020-2021 Ian Jackson and contributors to Otter
+// SPDX-License-Identifier: AGPL-3.0-or-later There is NO WARRANTY.
+
+use crate::prelude::*;
+
+use unicode_width::UnicodeWidthChar;
+
+type Col = usize;
+
+pub trait Reporter {
+ fn report(&mut self, pi: &ProgressInfo<'_>);
+}
+
+pub struct NullReporter;
+
+#[allow(unused_variables)]
+impl Reporter for NullReporter {
+ fn report(&mut self, pi: &ProgressInfo<'_>) { }
+}
+
+pub fn new() -> Box<dyn Reporter> {
+ let term = console::Term::buffered_stderr();
+ if_chain!{
+ if term.is_term();
+ if let Some((_, width)) = term.size_checked();
+ then {
+ Box::new(TermReporter {
+ term,
+ width: width.into(),
+ needs_clear: None,
+ })
+ } else {
+ Box::new(NullReporter)
+ }
+ }
+}
+
+pub struct TermReporter {
+ term: console::Term,
+ width: Col,
+ needs_clear: Option<()>,
+}
+
+const LHS_TARGET: Col = 25;
+const LHS_FRAC: f32 = (LHS_TARGET as f32)/80.0;
+
+impl Reporter for TermReporter {
+ fn report(&mut self, pi: &ProgressInfo<'_>) {
+ if let Some((_, width)) = self.term.size_checked() {
+ self.width = width.into()
+ }
+
+ let mid = min(LHS_TARGET, ((self.width as f32) * LHS_FRAC) as Col);
+ let mut out = String::new();
+ self.bar(&mut out, mid, &pi.phase);
+ self.bar(&mut out, self.width - mid, &pi.item);
+ self.clear_line();
+ self.needs_clear = Some(());
+ self.term.write_str(&out).unwrap_or(());
+ self.term.flush().unwrap_or(());
+ }
+}
+
+impl TermReporter {
+ fn clear_line(&mut self) {
+ if let Some(()) = self.needs_clear.take() {
+ self.term.clear_line().unwrap_or(());
+ }
+ }
+
+ fn bar(&self, out: &mut String, fwidth: Col, info: &progress::Count) {
+ let desc = console::strip_ansi_codes(&info.desc);
+ let w_change = if info.n == 0 { 0 } else {
+ min(
+ ((info.i as f32) / (info.n as f32) * (fwidth as f32)) as Col,
+ LHS_TARGET
+ )
+ };
+ let mut desc = desc
+ .chars()
+ .chain(iter::repeat(' '))
+ .peekable();
+ let mut w_sofar = 0;
+
+ let mut half = |stop_at|{
+ let mut accumulate = String::new();
+ loop {
+ let &c = desc.peek().unwrap();
+ if_let!{ Some(w) = c.width(); else continue; }
+ let w_next = w_sofar + w;
+ if w_next > stop_at { break }
+ accumulate.push(c);
+ w_sofar = w_next;
+ let _ = desc.next().unwrap();
+ }
+ accumulate
+ };
+
+ let lhs = half(w_change);
+ if lhs.len() > 0 {
+ let style = console::Style::new().for_stderr().reverse();
+ *out += &style.apply_to(lhs).to_string();
+ }
+
+ *out += &half(fwidth);
+ out.extend( iter::repeat(' ').take( fwidth - w_sofar ));
+ }
+}
+
+impl Drop for TermReporter {
+ fn drop(&mut self) {
+ self.clear_line();
+ self.term.flush().unwrap_or(());
+ }
+}