pub struct Loader { /* private fields */ }Expand description
A live progress reveal.
Create one with Loader::new, advance it, and finish.
Dropping the last handle finishes it for you, and the terminal is restored on
panic and on Ctrl+C too. Not Clone; for cross-thread updates take a
Handle.
Implementations§
Source§impl Loader
impl Loader
Sourcepub fn new(total: u64) -> Self
pub fn new(total: u64) -> Self
A determinate loader for total units of work, using the built-in dragon.
Examples found in repository?
21fn main() {
22 match std::env::args().nth(1).as_deref() {
23 Some("iter") => {
24 for _ in (0..100).inkling() {
25 work(20);
26 }
27 }
28 Some("spinner") => {
29 let loader = Loader::spinner();
30 loader.set_message("Doing something mysterious");
31 work(2500);
32 loader.finish();
33 }
34 Some("threads") => {
35 let loader = Loader::new(120);
36 loader.set_message("Four workers, one dragon");
37 thread::scope(|s| {
38 for _ in 0..4 {
39 let handle = loader.handle();
40 s.spawn(move || {
41 for _ in 0..30 {
42 work(30);
43 handle.inc(1);
44 }
45 });
46 }
47 });
48 loader.finish();
49 }
50 Some("rainbow") => {
51 let loader = Loader::builder()
52 .total(100)
53 .style(inkling::render::Style::rainbow())
54 .message("Tasting the rainbow")
55 .start();
56 for _ in 0..100 {
57 work(20);
58 loader.inc(1);
59 }
60 loader.finish();
61 }
62 _ => {
63 let total: u64 = 100;
64 let loader = Loader::new(total);
65 loader.set_message("Summoning the dragon");
66 for _ in 0..total {
67 work(20);
68 loader.inc(1);
69 }
70 loader.finish();
71 }
72 }
73}Sourcepub fn spinner() -> Self
pub fn spinner() -> Self
An indeterminate loader (a spinner) for work whose length you do not know.
Examples found in repository?
21fn main() {
22 match std::env::args().nth(1).as_deref() {
23 Some("iter") => {
24 for _ in (0..100).inkling() {
25 work(20);
26 }
27 }
28 Some("spinner") => {
29 let loader = Loader::spinner();
30 loader.set_message("Doing something mysterious");
31 work(2500);
32 loader.finish();
33 }
34 Some("threads") => {
35 let loader = Loader::new(120);
36 loader.set_message("Four workers, one dragon");
37 thread::scope(|s| {
38 for _ in 0..4 {
39 let handle = loader.handle();
40 s.spawn(move || {
41 for _ in 0..30 {
42 work(30);
43 handle.inc(1);
44 }
45 });
46 }
47 });
48 loader.finish();
49 }
50 Some("rainbow") => {
51 let loader = Loader::builder()
52 .total(100)
53 .style(inkling::render::Style::rainbow())
54 .message("Tasting the rainbow")
55 .start();
56 for _ in 0..100 {
57 work(20);
58 loader.inc(1);
59 }
60 loader.finish();
61 }
62 _ => {
63 let total: u64 = 100;
64 let loader = Loader::new(total);
65 loader.set_message("Summoning the dragon");
66 for _ in 0..total {
67 work(20);
68 loader.inc(1);
69 }
70 loader.finish();
71 }
72 }
73}Sourcepub fn builder() -> Builder
pub fn builder() -> Builder
Configure a loader with custom art, ordering, style, easing, or message.
Examples found in repository?
21fn main() {
22 match std::env::args().nth(1).as_deref() {
23 Some("iter") => {
24 for _ in (0..100).inkling() {
25 work(20);
26 }
27 }
28 Some("spinner") => {
29 let loader = Loader::spinner();
30 loader.set_message("Doing something mysterious");
31 work(2500);
32 loader.finish();
33 }
34 Some("threads") => {
35 let loader = Loader::new(120);
36 loader.set_message("Four workers, one dragon");
37 thread::scope(|s| {
38 for _ in 0..4 {
39 let handle = loader.handle();
40 s.spawn(move || {
41 for _ in 0..30 {
42 work(30);
43 handle.inc(1);
44 }
45 });
46 }
47 });
48 loader.finish();
49 }
50 Some("rainbow") => {
51 let loader = Loader::builder()
52 .total(100)
53 .style(inkling::render::Style::rainbow())
54 .message("Tasting the rainbow")
55 .start();
56 for _ in 0..100 {
57 work(20);
58 loader.inc(1);
59 }
60 loader.finish();
61 }
62 _ => {
63 let total: u64 = 100;
64 let loader = Loader::new(total);
65 loader.set_message("Summoning the dragon");
66 for _ in 0..total {
67 work(20);
68 loader.inc(1);
69 }
70 loader.finish();
71 }
72 }
73}More examples
36fn main() {
37 let args: Vec<String> = std::env::args().skip(1).collect();
38 let rainbow = args.iter().any(|a| a == "rainbow");
39 let geodesic = args.iter().any(|a| a == "geodesic");
40 let art_path = args.iter().find(|a| a.ends_with(".txt")).cloned();
41 let started = Instant::now();
42 let gold = Color::Rgb {
43 r: 232,
44 g: 180,
45 b: 85,
46 };
47
48 // Clear to a fresh screen and print the tool banner.
49 let _ = execute!(
50 io::stdout(),
51 Clear(ClearType::All),
52 MoveTo(0, 0),
53 Print("\r\n "),
54 SetForegroundColor(gold),
55 Print("dragonctl"),
56 ResetColor,
57 Print(" v0.2.0\r\n\r\n")
58 );
59
60 step("\u{2713}", Color::Green, "Initializing demo environment");
61 pause(450);
62 step("\u{2713}", Color::Green, "Updating base image index");
63 pause(500);
64 step("\u{2193}", Color::Cyan, "Downloading base image");
65 let _ = execute!(io::stdout(), Print("\r\n"));
66
67 // The download itself, paced unevenly: a connect stall, a hiccup, a burst, a
68 // mid stall, and a slow tail.
69 let total: u64 = 48 * 1024 * 1024;
70 let mb = 1024.0 * 1024.0;
71 let schedule: &[(f64, u64)] = &[
72 (0.0, 600),
73 (5.0, 300),
74 (8.0, 250),
75 (8.0, 650),
76 (16.0, 220),
77 (27.0, 180),
78 (38.0, 200),
79 (45.0, 450),
80 (56.0, 200),
81 (67.0, 220),
82 (78.0, 260),
83 (87.0, 320),
84 (93.0, 480),
85 (97.0, 520),
86 (100.0, 300),
87 ];
88
89 let style = if rainbow {
90 Style::rainbow()
91 } else {
92 Style::default()
93 };
94 let mut builder = Loader::builder().total(total).style(style);
95 if geodesic {
96 builder = builder.ordering(Geodesic::default());
97 }
98 if let Some(path) = &art_path {
99 let text = std::fs::read_to_string(path).unwrap_or_else(|e| {
100 eprintln!("could not read {path}: {e}");
101 std::process::exit(1);
102 });
103 builder = builder.art(inkling::Art::parse(&text));
104 }
105 let loader = builder.start();
106 for &(percent, dwell) in schedule {
107 let done = (percent / 100.0 * total as f64) as u64;
108 loader.set(done);
109 loader.set_message(format!(
110 "dragon.iso {:.1} / {:.1} MB",
111 done as f64 / mb,
112 total as f64 / mb
113 ));
114 pause(dwell);
115 }
116 loader.finish();
117
118 // A finish that ties it together.
119 let _ = execute!(io::stdout(), Print("\r\n"));
120 step(
121 "\u{2713}",
122 Color::Green,
123 "Verified checksum sha256:a1b2c3d4e5",
124 );
125 pause(400);
126 let _ = execute!(
127 io::stdout(),
128 Print("\r\n "),
129 SetForegroundColor(Color::Green),
130 Print("Done"),
131 ResetColor,
132 Print(format!(
133 " in {:.1}s. dragon.iso (48.0 MB) ready.\r\n\r\n",
134 started.elapsed().as_secs_f64()
135 ))
136 );
137 let _ = io::stdout().flush();
138}Sourcepub fn inc(&self, delta: u64)
pub fn inc(&self, delta: u64)
Advance the position by delta.
Examples found in repository?
21fn main() {
22 match std::env::args().nth(1).as_deref() {
23 Some("iter") => {
24 for _ in (0..100).inkling() {
25 work(20);
26 }
27 }
28 Some("spinner") => {
29 let loader = Loader::spinner();
30 loader.set_message("Doing something mysterious");
31 work(2500);
32 loader.finish();
33 }
34 Some("threads") => {
35 let loader = Loader::new(120);
36 loader.set_message("Four workers, one dragon");
37 thread::scope(|s| {
38 for _ in 0..4 {
39 let handle = loader.handle();
40 s.spawn(move || {
41 for _ in 0..30 {
42 work(30);
43 handle.inc(1);
44 }
45 });
46 }
47 });
48 loader.finish();
49 }
50 Some("rainbow") => {
51 let loader = Loader::builder()
52 .total(100)
53 .style(inkling::render::Style::rainbow())
54 .message("Tasting the rainbow")
55 .start();
56 for _ in 0..100 {
57 work(20);
58 loader.inc(1);
59 }
60 loader.finish();
61 }
62 _ => {
63 let total: u64 = 100;
64 let loader = Loader::new(total);
65 loader.set_message("Summoning the dragon");
66 for _ in 0..total {
67 work(20);
68 loader.inc(1);
69 }
70 loader.finish();
71 }
72 }
73}Sourcepub fn set(&self, pos: u64)
pub fn set(&self, pos: u64)
Set the absolute position.
Examples found in repository?
36fn main() {
37 let args: Vec<String> = std::env::args().skip(1).collect();
38 let rainbow = args.iter().any(|a| a == "rainbow");
39 let geodesic = args.iter().any(|a| a == "geodesic");
40 let art_path = args.iter().find(|a| a.ends_with(".txt")).cloned();
41 let started = Instant::now();
42 let gold = Color::Rgb {
43 r: 232,
44 g: 180,
45 b: 85,
46 };
47
48 // Clear to a fresh screen and print the tool banner.
49 let _ = execute!(
50 io::stdout(),
51 Clear(ClearType::All),
52 MoveTo(0, 0),
53 Print("\r\n "),
54 SetForegroundColor(gold),
55 Print("dragonctl"),
56 ResetColor,
57 Print(" v0.2.0\r\n\r\n")
58 );
59
60 step("\u{2713}", Color::Green, "Initializing demo environment");
61 pause(450);
62 step("\u{2713}", Color::Green, "Updating base image index");
63 pause(500);
64 step("\u{2193}", Color::Cyan, "Downloading base image");
65 let _ = execute!(io::stdout(), Print("\r\n"));
66
67 // The download itself, paced unevenly: a connect stall, a hiccup, a burst, a
68 // mid stall, and a slow tail.
69 let total: u64 = 48 * 1024 * 1024;
70 let mb = 1024.0 * 1024.0;
71 let schedule: &[(f64, u64)] = &[
72 (0.0, 600),
73 (5.0, 300),
74 (8.0, 250),
75 (8.0, 650),
76 (16.0, 220),
77 (27.0, 180),
78 (38.0, 200),
79 (45.0, 450),
80 (56.0, 200),
81 (67.0, 220),
82 (78.0, 260),
83 (87.0, 320),
84 (93.0, 480),
85 (97.0, 520),
86 (100.0, 300),
87 ];
88
89 let style = if rainbow {
90 Style::rainbow()
91 } else {
92 Style::default()
93 };
94 let mut builder = Loader::builder().total(total).style(style);
95 if geodesic {
96 builder = builder.ordering(Geodesic::default());
97 }
98 if let Some(path) = &art_path {
99 let text = std::fs::read_to_string(path).unwrap_or_else(|e| {
100 eprintln!("could not read {path}: {e}");
101 std::process::exit(1);
102 });
103 builder = builder.art(inkling::Art::parse(&text));
104 }
105 let loader = builder.start();
106 for &(percent, dwell) in schedule {
107 let done = (percent / 100.0 * total as f64) as u64;
108 loader.set(done);
109 loader.set_message(format!(
110 "dragon.iso {:.1} / {:.1} MB",
111 done as f64 / mb,
112 total as f64 / mb
113 ));
114 pause(dwell);
115 }
116 loader.finish();
117
118 // A finish that ties it together.
119 let _ = execute!(io::stdout(), Print("\r\n"));
120 step(
121 "\u{2713}",
122 Color::Green,
123 "Verified checksum sha256:a1b2c3d4e5",
124 );
125 pause(400);
126 let _ = execute!(
127 io::stdout(),
128 Print("\r\n "),
129 SetForegroundColor(Color::Green),
130 Print("Done"),
131 ResetColor,
132 Print(format!(
133 " in {:.1}s. dragon.iso (48.0 MB) ready.\r\n\r\n",
134 started.elapsed().as_secs_f64()
135 ))
136 );
137 let _ = io::stdout().flush();
138}Sourcepub fn set_length(&self, total: u64)
pub fn set_length(&self, total: u64)
Change the total amount of work.
Sourcepub fn set_message<S: Into<String>>(&self, msg: S)
pub fn set_message<S: Into<String>>(&self, msg: S)
Set a short caption shown beneath the art.
Examples found in repository?
21fn main() {
22 match std::env::args().nth(1).as_deref() {
23 Some("iter") => {
24 for _ in (0..100).inkling() {
25 work(20);
26 }
27 }
28 Some("spinner") => {
29 let loader = Loader::spinner();
30 loader.set_message("Doing something mysterious");
31 work(2500);
32 loader.finish();
33 }
34 Some("threads") => {
35 let loader = Loader::new(120);
36 loader.set_message("Four workers, one dragon");
37 thread::scope(|s| {
38 for _ in 0..4 {
39 let handle = loader.handle();
40 s.spawn(move || {
41 for _ in 0..30 {
42 work(30);
43 handle.inc(1);
44 }
45 });
46 }
47 });
48 loader.finish();
49 }
50 Some("rainbow") => {
51 let loader = Loader::builder()
52 .total(100)
53 .style(inkling::render::Style::rainbow())
54 .message("Tasting the rainbow")
55 .start();
56 for _ in 0..100 {
57 work(20);
58 loader.inc(1);
59 }
60 loader.finish();
61 }
62 _ => {
63 let total: u64 = 100;
64 let loader = Loader::new(total);
65 loader.set_message("Summoning the dragon");
66 for _ in 0..total {
67 work(20);
68 loader.inc(1);
69 }
70 loader.finish();
71 }
72 }
73}More examples
36fn main() {
37 let args: Vec<String> = std::env::args().skip(1).collect();
38 let rainbow = args.iter().any(|a| a == "rainbow");
39 let geodesic = args.iter().any(|a| a == "geodesic");
40 let art_path = args.iter().find(|a| a.ends_with(".txt")).cloned();
41 let started = Instant::now();
42 let gold = Color::Rgb {
43 r: 232,
44 g: 180,
45 b: 85,
46 };
47
48 // Clear to a fresh screen and print the tool banner.
49 let _ = execute!(
50 io::stdout(),
51 Clear(ClearType::All),
52 MoveTo(0, 0),
53 Print("\r\n "),
54 SetForegroundColor(gold),
55 Print("dragonctl"),
56 ResetColor,
57 Print(" v0.2.0\r\n\r\n")
58 );
59
60 step("\u{2713}", Color::Green, "Initializing demo environment");
61 pause(450);
62 step("\u{2713}", Color::Green, "Updating base image index");
63 pause(500);
64 step("\u{2193}", Color::Cyan, "Downloading base image");
65 let _ = execute!(io::stdout(), Print("\r\n"));
66
67 // The download itself, paced unevenly: a connect stall, a hiccup, a burst, a
68 // mid stall, and a slow tail.
69 let total: u64 = 48 * 1024 * 1024;
70 let mb = 1024.0 * 1024.0;
71 let schedule: &[(f64, u64)] = &[
72 (0.0, 600),
73 (5.0, 300),
74 (8.0, 250),
75 (8.0, 650),
76 (16.0, 220),
77 (27.0, 180),
78 (38.0, 200),
79 (45.0, 450),
80 (56.0, 200),
81 (67.0, 220),
82 (78.0, 260),
83 (87.0, 320),
84 (93.0, 480),
85 (97.0, 520),
86 (100.0, 300),
87 ];
88
89 let style = if rainbow {
90 Style::rainbow()
91 } else {
92 Style::default()
93 };
94 let mut builder = Loader::builder().total(total).style(style);
95 if geodesic {
96 builder = builder.ordering(Geodesic::default());
97 }
98 if let Some(path) = &art_path {
99 let text = std::fs::read_to_string(path).unwrap_or_else(|e| {
100 eprintln!("could not read {path}: {e}");
101 std::process::exit(1);
102 });
103 builder = builder.art(inkling::Art::parse(&text));
104 }
105 let loader = builder.start();
106 for &(percent, dwell) in schedule {
107 let done = (percent / 100.0 * total as f64) as u64;
108 loader.set(done);
109 loader.set_message(format!(
110 "dragon.iso {:.1} / {:.1} MB",
111 done as f64 / mb,
112 total as f64 / mb
113 ));
114 pause(dwell);
115 }
116 loader.finish();
117
118 // A finish that ties it together.
119 let _ = execute!(io::stdout(), Print("\r\n"));
120 step(
121 "\u{2713}",
122 Color::Green,
123 "Verified checksum sha256:a1b2c3d4e5",
124 );
125 pause(400);
126 let _ = execute!(
127 io::stdout(),
128 Print("\r\n "),
129 SetForegroundColor(Color::Green),
130 Print("Done"),
131 ResetColor,
132 Print(format!(
133 " in {:.1}s. dragon.iso (48.0 MB) ready.\r\n\r\n",
134 started.elapsed().as_secs_f64()
135 ))
136 );
137 let _ = io::stdout().flush();
138}Sourcepub fn rate(&self) -> f64
pub fn rate(&self) -> f64
Average units of work per second so far, or 0.0 before any time passes.
Sourcepub fn eta(&self) -> Option<Duration>
pub fn eta(&self) -> Option<Duration>
Estimated time remaining, from the average rate so far.
None for an indeterminate loader, before enough has happened to
extrapolate from, or once the work is done.
Sourcepub fn handle(&self) -> Handle
pub fn handle(&self) -> Handle
A cheap, clonable, Send + Sync handle for reporting progress from other
threads. Handles can update but not finish the loader.
Examples found in repository?
21fn main() {
22 match std::env::args().nth(1).as_deref() {
23 Some("iter") => {
24 for _ in (0..100).inkling() {
25 work(20);
26 }
27 }
28 Some("spinner") => {
29 let loader = Loader::spinner();
30 loader.set_message("Doing something mysterious");
31 work(2500);
32 loader.finish();
33 }
34 Some("threads") => {
35 let loader = Loader::new(120);
36 loader.set_message("Four workers, one dragon");
37 thread::scope(|s| {
38 for _ in 0..4 {
39 let handle = loader.handle();
40 s.spawn(move || {
41 for _ in 0..30 {
42 work(30);
43 handle.inc(1);
44 }
45 });
46 }
47 });
48 loader.finish();
49 }
50 Some("rainbow") => {
51 let loader = Loader::builder()
52 .total(100)
53 .style(inkling::render::Style::rainbow())
54 .message("Tasting the rainbow")
55 .start();
56 for _ in 0..100 {
57 work(20);
58 loader.inc(1);
59 }
60 loader.finish();
61 }
62 _ => {
63 let total: u64 = 100;
64 let loader = Loader::new(total);
65 loader.set_message("Summoning the dragon");
66 for _ in 0..total {
67 work(20);
68 loader.inc(1);
69 }
70 loader.finish();
71 }
72 }
73}Sourcepub fn wrap_read<R: Read>(&self, reader: R) -> ProgressReader<R> ⓘ
pub fn wrap_read<R: Read>(&self, reader: R) -> ProgressReader<R> ⓘ
Wrap a reader so every byte read advances the loader. Ideal for downloads: set the length to the content length, then read through the wrapper.
Sourcepub fn suspend<T>(&self, f: impl FnOnce() -> T) -> T
pub fn suspend<T>(&self, f: impl FnOnce() -> T) -> T
Lift the art out of the way, run f, and let the reveal redraw beneath
whatever it printed.
Without this, anything your program writes to the terminal lands in the middle of the block and desynchronises the renderer, which is tracking where its own output sits. Use it for any logging you want interleaved with a live reveal.
let loader = Loader::new(3);
loader.suspend(|| eprintln!("something worth saying"));Sourcepub fn println<S: AsRef<str>>(&self, line: S)
pub fn println<S: AsRef<str>>(&self, line: S)
Print a line above the reveal, which then redraws beneath it.
Shorthand for suspend around a println!.
Sourcepub fn finish(&self)
pub fn finish(&self)
Fill the art, leave it on screen, and restore the terminal.
Examples found in repository?
21fn main() {
22 match std::env::args().nth(1).as_deref() {
23 Some("iter") => {
24 for _ in (0..100).inkling() {
25 work(20);
26 }
27 }
28 Some("spinner") => {
29 let loader = Loader::spinner();
30 loader.set_message("Doing something mysterious");
31 work(2500);
32 loader.finish();
33 }
34 Some("threads") => {
35 let loader = Loader::new(120);
36 loader.set_message("Four workers, one dragon");
37 thread::scope(|s| {
38 for _ in 0..4 {
39 let handle = loader.handle();
40 s.spawn(move || {
41 for _ in 0..30 {
42 work(30);
43 handle.inc(1);
44 }
45 });
46 }
47 });
48 loader.finish();
49 }
50 Some("rainbow") => {
51 let loader = Loader::builder()
52 .total(100)
53 .style(inkling::render::Style::rainbow())
54 .message("Tasting the rainbow")
55 .start();
56 for _ in 0..100 {
57 work(20);
58 loader.inc(1);
59 }
60 loader.finish();
61 }
62 _ => {
63 let total: u64 = 100;
64 let loader = Loader::new(total);
65 loader.set_message("Summoning the dragon");
66 for _ in 0..total {
67 work(20);
68 loader.inc(1);
69 }
70 loader.finish();
71 }
72 }
73}More examples
36fn main() {
37 let args: Vec<String> = std::env::args().skip(1).collect();
38 let rainbow = args.iter().any(|a| a == "rainbow");
39 let geodesic = args.iter().any(|a| a == "geodesic");
40 let art_path = args.iter().find(|a| a.ends_with(".txt")).cloned();
41 let started = Instant::now();
42 let gold = Color::Rgb {
43 r: 232,
44 g: 180,
45 b: 85,
46 };
47
48 // Clear to a fresh screen and print the tool banner.
49 let _ = execute!(
50 io::stdout(),
51 Clear(ClearType::All),
52 MoveTo(0, 0),
53 Print("\r\n "),
54 SetForegroundColor(gold),
55 Print("dragonctl"),
56 ResetColor,
57 Print(" v0.2.0\r\n\r\n")
58 );
59
60 step("\u{2713}", Color::Green, "Initializing demo environment");
61 pause(450);
62 step("\u{2713}", Color::Green, "Updating base image index");
63 pause(500);
64 step("\u{2193}", Color::Cyan, "Downloading base image");
65 let _ = execute!(io::stdout(), Print("\r\n"));
66
67 // The download itself, paced unevenly: a connect stall, a hiccup, a burst, a
68 // mid stall, and a slow tail.
69 let total: u64 = 48 * 1024 * 1024;
70 let mb = 1024.0 * 1024.0;
71 let schedule: &[(f64, u64)] = &[
72 (0.0, 600),
73 (5.0, 300),
74 (8.0, 250),
75 (8.0, 650),
76 (16.0, 220),
77 (27.0, 180),
78 (38.0, 200),
79 (45.0, 450),
80 (56.0, 200),
81 (67.0, 220),
82 (78.0, 260),
83 (87.0, 320),
84 (93.0, 480),
85 (97.0, 520),
86 (100.0, 300),
87 ];
88
89 let style = if rainbow {
90 Style::rainbow()
91 } else {
92 Style::default()
93 };
94 let mut builder = Loader::builder().total(total).style(style);
95 if geodesic {
96 builder = builder.ordering(Geodesic::default());
97 }
98 if let Some(path) = &art_path {
99 let text = std::fs::read_to_string(path).unwrap_or_else(|e| {
100 eprintln!("could not read {path}: {e}");
101 std::process::exit(1);
102 });
103 builder = builder.art(inkling::Art::parse(&text));
104 }
105 let loader = builder.start();
106 for &(percent, dwell) in schedule {
107 let done = (percent / 100.0 * total as f64) as u64;
108 loader.set(done);
109 loader.set_message(format!(
110 "dragon.iso {:.1} / {:.1} MB",
111 done as f64 / mb,
112 total as f64 / mb
113 ));
114 pause(dwell);
115 }
116 loader.finish();
117
118 // A finish that ties it together.
119 let _ = execute!(io::stdout(), Print("\r\n"));
120 step(
121 "\u{2713}",
122 Color::Green,
123 "Verified checksum sha256:a1b2c3d4e5",
124 );
125 pause(400);
126 let _ = execute!(
127 io::stdout(),
128 Print("\r\n "),
129 SetForegroundColor(Color::Green),
130 Print("Done"),
131 ResetColor,
132 Print(format!(
133 " in {:.1}s. dragon.iso (48.0 MB) ready.\r\n\r\n",
134 started.elapsed().as_secs_f64()
135 ))
136 );
137 let _ = io::stdout().flush();
138}Sourcepub fn finish_and_clear(&self)
pub fn finish_and_clear(&self)
Finish and erase the art from the screen.