diff --git a/src/arguments/delete.rs b/src/arguments/delete.rs index bcce0d5..ecf9389 100644 --- a/src/arguments/delete.rs +++ b/src/arguments/delete.rs @@ -1,4 +1,9 @@ -use std::io::{self, Write}; +use std::io::{self, BufRead, Write}; + +#[cfg(unix)] +use std::fs::File; +#[cfg(windows)] +use std::fs::OpenOptions; use clap::Args; use color_eyre::eyre::eyre; @@ -30,8 +35,6 @@ impl SubcommandExecutor for DeleteArgs { .or_else(|| get_first_matching_element(&otp_database, &self)) .ok_or(eyre!("No code has been found using the given arguments"))?; - let mut output = String::with_capacity(1); - let element = otp_database.elements_ref().get(index_to_delete).unwrap(); print!( "Are you sure you want to delete the {}th code ({}, {}) [Y,N]: ", @@ -41,7 +44,7 @@ impl SubcommandExecutor for DeleteArgs { ); io::stdout().flush()?; - io::stdin().read_line(&mut output)?; + let output = read_confirmation_line()?; if output.trim().eq_ignore_ascii_case("y") { otp_database.delete_element(index_to_delete); @@ -52,6 +55,35 @@ impl SubcommandExecutor for DeleteArgs { } } +fn read_confirmation_line() -> color_eyre::Result { + let mut output = String::with_capacity(1); + + if io::stdin().read_line(&mut output)? > 0 { + return Ok(output); + } + + #[cfg(unix)] + { + output.clear(); + let mut tty = io::BufReader::new(File::open("/dev/tty")?); + tty.read_line(&mut output)?; + return Ok(output); + } + + #[cfg(windows)] + { + output.clear(); + let mut tty = io::BufReader::new(OpenOptions::new().read(true).open("CONIN$")?); + tty.read_line(&mut output)?; + return Ok(output); + } + + #[allow(unreachable_code)] + Err(eyre!( + "Unable to read confirmation answer from standard input or terminal" + )) +} + fn get_first_matching_element( otp_database: &OTPDatabase, delete_args: &DeleteArgs,