1use crate::util::errors::wrap;
6use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
7use indicatif::ProgressBar;
8use std::fmt::Display;
9
10use super::{errors::WrappedError, io::ReportCopyProgress};
11
12pub struct ProgressBarReporter {
14 bar: ProgressBar,
15 has_set_total: bool,
16}
17
18impl From<ProgressBar> for ProgressBarReporter {
19 fn from(bar: ProgressBar) -> Self {
20 ProgressBarReporter {
21 bar,
22 has_set_total: false,
23 }
24 }
25}
26
27impl ReportCopyProgress for ProgressBarReporter {
28 fn report_progress(&mut self, bytes_so_far: u64, total_bytes: u64) {
29 if !self.has_set_total {
30 self.bar.set_length(total_bytes);
31 }
32
33 if bytes_so_far == total_bytes {
34 self.bar.finish_and_clear();
35 } else {
36 self.bar.set_position(bytes_so_far);
37 }
38 }
39}
40
41pub fn prompt_yn(text: &str) -> Result<bool, WrappedError> {
42 Confirm::with_theme(&ColorfulTheme::default())
43 .with_prompt(text)
44 .default(true)
45 .interact()
46 .map_err(|e| wrap(e, "Failed to read confirm input"))
47}
48
49pub fn prompt_options<T>(text: impl Into<String>, options: &[T]) -> Result<T, WrappedError>
50where
51 T: Display + Copy,
52{
53 let chosen = Select::with_theme(&ColorfulTheme::default())
54 .with_prompt(text)
55 .items(options)
56 .default(0)
57 .interact()
58 .map_err(|e| wrap(e, "Failed to read select input"))?;
59
60 Ok(options[chosen])
61}
62
63pub fn prompt_placeholder(question: &str, placeholder: &str) -> Result<String, WrappedError> {
64 Input::with_theme(&ColorfulTheme::default())
65 .with_prompt(question)
66 .default(placeholder.to_string())
67 .interact_text()
68 .map_err(|e| wrap(e, "Failed to read confirm input"))
69}