Files
TrustTunnel/tools/setup_wizard/user_interaction.rs
Andrey Meshkov d7273ea729 Pull request 94: Added auto-formatting and pre-commit hook
Squashed commit of the following:

commit 0dc9600ff3bd8573d805e4de4d85290b1052a222
Author: Andrey Meshkov <am@adguard.com>
Date:   Sun Dec 21 20:53:02 2025 +0300

    Rollback to the old changelog

commit fb56f619d5f703d712dbfdb95ab093a211dc0c58
Author: Andrey Meshkov <am@adguard.com>
Date:   Sun Dec 21 20:36:24 2025 +0300

    Improve the dev doc

commit afd44a5e2bebd51b07dcb587cf39ada925a42db9
Author: Andrey Meshkov <am@adguard.com>
Date:   Sun Dec 21 20:32:49 2025 +0300

    Added auto-formatting and pre-commit hook
2025-12-21 20:54:46 +03:00

103 lines
2.9 KiB
Rust

use crate::Mode;
use dialoguer::theme::ColorfulTheme;
use dialoguer::{Confirm, Input, Password, Select};
use once_cell::sync::Lazy;
use std::fs;
use std::ops::Deref;
use std::path::Path;
use std::str::FromStr;
pub static THEME: Lazy<ColorfulTheme> = Lazy::new(ColorfulTheme::default);
/// Ask user to enter a value.
/// If [`default`] is [`Some`], suggest the value in the prompt.
pub fn ask_for_input<T>(message: &str, default: Option<T>) -> T
where
T: Clone + Default + FromStr + ToString,
<T as FromStr>::Err: ToString,
{
if crate::get_mode() == Mode::NonInteractive {
return default.expect("Expecting a user input in non-interactive mode");
}
if default.is_some() {
Input::<T>::with_theme(THEME.deref())
.with_prompt(message)
.show_default(default.is_some())
.default(default.unwrap_or_default())
.interact()
.unwrap()
} else {
Input::<T>::with_theme(THEME.deref())
.with_prompt(message)
.interact()
.unwrap()
}
}
/// Ask if one wants to do something (yes/no)
pub fn ask_for_agreement(message: &str) -> bool {
assert_ne!(
crate::get_mode(),
Mode::NonInteractive,
"Expecting a user input in non-interactive mode"
);
Confirm::with_theme(THEME.deref())
.with_prompt(message)
.default(false)
.show_default(true)
.interact()
.unwrap()
}
/// Ask user to enter a password in a secure way
pub fn ask_for_password(message: &str) -> String {
assert_ne!(
crate::get_mode(),
Mode::NonInteractive,
"Expecting a user input in non-interactive mode"
);
Password::with_theme(THEME.deref())
.with_prompt(message)
.interact()
.unwrap()
}
/// Check if a file exists and if it does, ask if one wants to overwrite it
pub fn checked_overwrite(path: &str, message: &str) -> bool {
crate::get_mode() == Mode::NonInteractive
|| !fs::metadata(Path::new(&path))
.as_ref()
.map(fs::Metadata::is_file)
.unwrap_or_default()
|| ask_for_agreement(message)
}
/// Ask user to select a variant. Returns index of the selected variant.
pub fn select_index<S: Into<String>>(
prompt: S,
variants: &[&str],
default: Option<usize>,
) -> usize {
if crate::get_mode() == Mode::NonInteractive {
return default.expect("Expecting a user input in non-interactive mode");
}
Select::with_theme(THEME.deref())
.with_prompt(prompt)
.items(variants)
.report(true)
.default(default.unwrap_or_default())
.interact_opt()
.expect("Interaction failure")
.expect("None selected")
}
/// Ask user to select a variant. Returns the selected variant.
pub fn select_variant<'a, S>(prompt: S, variants: &[&'a str], default: Option<usize>) -> &'a str
where
S: Into<String>,
{
variants[select_index(prompt, variants, default)]
}