use std::io::{self, Read, Write};
pub fn confirm(prompt: &str, default_yes: bool) -> io::Result<bool> {
let hint = if default_yes { "Y/n" } else { "y/N" };
print!("{} [{}] ", prompt, hint);
io::stdout().flush()?;
let result = read_single_key();
match result {
Ok(ch) => {
if ch == '\n' || ch == '\r' {
println!();
} else {
println!("{}", ch);
}
match ch {
'y' | 'Y' => Ok(true),
'n' | 'N' => Ok(false),
'\n' | '\r' => Ok(default_yes),
_ => Ok(default_yes),
}
}
Err(e) => Err(e),
}
}
#[cfg(unix)]
fn read_single_key() -> io::Result<char> {
use std::os::unix::io::AsRawFd;
let stdin_fd = io::stdin().as_raw_fd();
let mut old_termios: libc::termios = unsafe { std::mem::zeroed() };
if unsafe { libc::tcgetattr(stdin_fd, &mut old_termios) } != 0 {
return Err(io::Error::last_os_error());
}
let mut new_termios = old_termios;
new_termios.c_lflag &= !(libc::ICANON | libc::ECHO);
new_termios.c_cc[libc::VMIN] = 1;
new_termios.c_cc[libc::VTIME] = 0;
if unsafe { libc::tcsetattr(stdin_fd, libc::TCSANOW, &new_termios) } != 0 {
return Err(io::Error::last_os_error());
}
let mut buf = [0u8; 1];
let result = io::stdin().read_exact(&mut buf);
unsafe {
libc::tcsetattr(stdin_fd, libc::TCSANOW, &old_termios);
}
result?;
Ok(buf[0] as char)
}
#[cfg(windows)]
fn read_single_key() -> io::Result<char> {
let mut input = String::new();
io::stdin().read_line(&mut input)?;
Ok(input.chars().next().unwrap_or('\n'))
}