92 lines
2.5 KiB
Rust
92 lines
2.5 KiB
Rust
// Allow dead code, until we've fully implemented CLI/error handling
|
|
#![allow(dead_code)]
|
|
|
|
use std::io::{stderr, stdin, Write};
|
|
|
|
use crate::util::error::{quit_error, ErrorHints};
|
|
|
|
/// Prompt the user to enter some value.
|
|
/// The prompt that is shown should be passed to `msg`,
|
|
/// excluding the `:` suffix.
|
|
pub fn prompt(msg: &str) -> String {
|
|
// Show the prompt
|
|
eprint!("{msg}: ");
|
|
let _ = stderr().flush();
|
|
|
|
// Get the input
|
|
let mut input = String::new();
|
|
if let Err(err) = stdin()
|
|
.read_line(&mut input)
|
|
.map_err(|err| -> anyhow::Error { err.into() })
|
|
{
|
|
quit_error(
|
|
err.context("failed to read input from prompt"),
|
|
ErrorHints::default(),
|
|
);
|
|
}
|
|
|
|
// Trim and return
|
|
input.trim().to_owned()
|
|
}
|
|
|
|
/// Prompt the user for a question, allowing a yes or now answer.
|
|
/// True is returned if yes was answered, false if no.
|
|
///
|
|
/// A default may be given, which is chosen if no-interact mode is
|
|
/// enabled, or if enter was pressed by the user without entering anything.
|
|
pub fn prompt_yes(msg: &str, def: Option<bool>) -> bool {
|
|
// Define the available options string
|
|
let options = format!(
|
|
"[{}/{}]",
|
|
match def {
|
|
Some(def) if def => "Y",
|
|
_ => "y",
|
|
},
|
|
match def {
|
|
Some(def) if !def => "N",
|
|
_ => "n",
|
|
}
|
|
);
|
|
|
|
// Get the user input
|
|
let answer = prompt(&format!("{msg} {options}"));
|
|
|
|
// Assume the default if the answer is empty
|
|
if answer.is_empty() {
|
|
if let Some(def) = def {
|
|
return def;
|
|
}
|
|
}
|
|
|
|
// Derive a boolean and return
|
|
match derive_bool(&answer) {
|
|
Some(answer) => answer,
|
|
None => prompt_yes(msg, def),
|
|
}
|
|
}
|
|
|
|
/// Try to derive true or false (yes or no) from the given input.
|
|
/// None is returned if no boolean could be derived accurately.
|
|
fn derive_bool(input: &str) -> Option<bool> {
|
|
// Process the input
|
|
let input = input.trim().to_lowercase();
|
|
|
|
// Handle short or incomplete answers
|
|
match input.as_str() {
|
|
"y" | "ye" | "t" | "1" => return Some(true),
|
|
"n" | "f" | "0" => return Some(false),
|
|
_ => {}
|
|
}
|
|
|
|
// Handle complete answers with any suffix
|
|
if input.starts_with("yes") || input.starts_with("true") {
|
|
return Some(true);
|
|
}
|
|
if input.starts_with("no") || input.starts_with("false") {
|
|
return Some(false);
|
|
}
|
|
|
|
// The answer could not be determined, return none
|
|
None
|
|
}
|