You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
1.6 KiB
74 lines
1.6 KiB
use std::io;
|
|
use std::io::Write;
|
|
use std::str::FromStr;
|
|
|
|
fn flush() {
|
|
io::stdout().flush().expect("Failed to flush stdout");
|
|
}
|
|
|
|
struct YesNo(bool);
|
|
struct YesNoParseError();
|
|
|
|
impl From<YesNo> for bool {
|
|
fn from(yn: YesNo) -> Self {
|
|
yn.0
|
|
}
|
|
}
|
|
|
|
impl FromStr for YesNo {
|
|
type Err = YesNoParseError;
|
|
|
|
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
|
|
match s {
|
|
"true" => Ok(YesNo(true)),
|
|
"y" => Ok(YesNo(true)),
|
|
"1" => Ok(YesNo(true)),
|
|
"yes" => Ok(YesNo(true)),
|
|
"a" => Ok(YesNo(true)),
|
|
"false" => Ok(YesNo(false)),
|
|
"f" => Ok(YesNo(false)),
|
|
"no" => Ok(YesNo(false)),
|
|
"n" => Ok(YesNo(false)),
|
|
"0" => Ok(YesNo(false)),
|
|
_ => Err(YesNoParseError()),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn ask_yn(prompt: &str) -> Option<bool> {
|
|
match ask::<YesNo>(prompt) {
|
|
Some(yn) => Some(yn.into()),
|
|
None => None,
|
|
}
|
|
}
|
|
|
|
pub fn ask<T>(prompt: &str) -> Option<T>
|
|
where
|
|
T: FromStr,
|
|
{
|
|
let mut buf = String::new();
|
|
loop {
|
|
print!("{}", prompt);
|
|
|
|
flush();
|
|
buf.clear();
|
|
io::stdin()
|
|
.read_line(&mut buf)
|
|
.expect("Failed to read line");
|
|
|
|
let s = buf.trim();
|
|
if s.is_empty() {
|
|
println!(); // empty string returns None as a signal to terminate the program
|
|
break None;
|
|
}
|
|
|
|
match s.parse() {
|
|
Ok(val) => {
|
|
break Some(val);
|
|
}
|
|
Err(_) => {
|
|
println!("Could not parse \"{}\", please try again.", s);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|