cargo-binstall/crates/bin/src/ui.rs
pepa65 81a8218794
Yes/NO defaults to "no" when just enter is pressed (#1948)
* yes/NO in interface

* Implement No as default (when only Enter is pressed)

* Update README.md

Mark the default as [yes]

Signed-off-by: pepa65 <pepa65@passchier.net>

* Update ui.rs

Mark the default as [yes]

Signed-off-by: pepa65 <pepa65@passchier.net>

* Update ui.rs

Do not break on yes/y/YES/Y/"", break on no/n/NO/N, and keep asking otherwise

Signed-off-by: pepa65 <pepa65@passchier.net>

* Update ui.rs

After testing empty didn't work correctly

Signed-off-by: pepa65 <pepa65@passchier.net>

---------

Signed-off-by: pepa65 <pepa65@passchier.net>
2024-10-30 13:00:56 +00:00

56 lines
1.3 KiB
Rust

use std::{
io::{self, BufRead, StdinLock, Write},
thread,
};
use binstalk::errors::BinstallError;
use tokio::sync::oneshot;
fn ask_for_confirm(stdin: &mut StdinLock, input: &mut String) -> io::Result<()> {
{
let mut stdout = io::stdout().lock();
write!(&mut stdout, "Do you wish to continue? [yes]/no\n? ")?;
stdout.flush()?;
}
stdin.read_line(input)?;
Ok(())
}
pub async fn confirm() -> Result<(), BinstallError> {
let (tx, rx) = oneshot::channel();
thread::spawn(move || {
// This task should be the only one able to
// access stdin
let mut stdin = io::stdin().lock();
let mut input = String::with_capacity(16);
let res = loop {
if ask_for_confirm(&mut stdin, &mut input).is_err() {
break false;
}
match input.as_str().trim() {
"yes" | "y" | "YES" | "Y" | "" => break true,
"no" | "n" | "NO" | "N" => break false,
_ => {
input.clear();
continue;
}
}
};
// The main thread might be terminated by signal and thus cancelled
// the confirmation.
tx.send(res).ok();
});
if rx.await.unwrap() {
Ok(())
} else {
Err(BinstallError::UserAbort)
}
}