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 for bool { fn from(yn: YesNo) -> Self { yn.0 } } impl FromStr for YesNo { type Err = YesNoParseError; fn from_str(s: &str) -> Result::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 { match ask::(prompt) { Some(yn) => Some(yn.into()), None => None, } } pub fn ask(prompt: &str) -> Option 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); } }; } }