mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-21 13:08:42 +00:00
Impl helpers::confirm::Confirmer
Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
c1809d41fa
commit
dd2fa2de33
2 changed files with 100 additions and 4 deletions
|
@ -20,7 +20,7 @@ mod auto_abort_join_handle;
|
||||||
pub use auto_abort_join_handle::AutoAbortJoinHandle;
|
pub use auto_abort_join_handle::AutoAbortJoinHandle;
|
||||||
|
|
||||||
mod confirm;
|
mod confirm;
|
||||||
pub use confirm::confirm;
|
pub use confirm::{confirm, Confirmer};
|
||||||
|
|
||||||
mod extracter;
|
mod extracter;
|
||||||
mod readable_rx;
|
mod readable_rx;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
use std::io::{self, BufRead, Write};
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::io::{stderr, stdin, Write};
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
use crate::BinstallError;
|
use crate::BinstallError;
|
||||||
|
|
||||||
|
@ -7,10 +10,10 @@ pub fn confirm() -> Result<(), BinstallError> {
|
||||||
loop {
|
loop {
|
||||||
info!("Do you wish to continue? yes/[no]");
|
info!("Do you wish to continue? yes/[no]");
|
||||||
eprint!("? ");
|
eprint!("? ");
|
||||||
stderr().flush().ok();
|
io::stderr().flush().ok();
|
||||||
|
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
stdin().read_line(&mut input).unwrap();
|
io::stdin().read_line(&mut input).unwrap();
|
||||||
|
|
||||||
match input.as_str().trim() {
|
match input.as_str().trim() {
|
||||||
"yes" | "y" | "YES" | "Y" => break Ok(()),
|
"yes" | "y" | "YES" | "Y" => break Ok(()),
|
||||||
|
@ -19,3 +22,96 @@ pub fn confirm() -> Result<(), BinstallError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ConfirmerInner {
|
||||||
|
/// Request for confirmation
|
||||||
|
request_tx: mpsc::Sender<()>,
|
||||||
|
|
||||||
|
/// Confirmation
|
||||||
|
confirm_rx: mpsc::Receiver<Result<(), BinstallError>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfirmerInner {
|
||||||
|
fn new() -> Self {
|
||||||
|
let (request_tx, mut request_rx) = mpsc::channel(1);
|
||||||
|
let (confirm_tx, confirm_rx) = mpsc::channel(10);
|
||||||
|
|
||||||
|
spawn_blocking(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);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if request_rx.blocking_recv().is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock stdout so that nobody can interfere
|
||||||
|
// with confirmation.
|
||||||
|
let mut stdout = io::stdout().lock();
|
||||||
|
|
||||||
|
let res = loop {
|
||||||
|
writeln!(&mut stdout, "Do you wish to continue? yes/[no]").unwrap();
|
||||||
|
write!(&mut stdout, "? ").unwrap();
|
||||||
|
stdout.flush().unwrap();
|
||||||
|
|
||||||
|
input.clear();
|
||||||
|
if stdin.read_line(&mut input).is_err() {
|
||||||
|
break Err(BinstallError::UserAbort);
|
||||||
|
}
|
||||||
|
|
||||||
|
match input.as_str().trim() {
|
||||||
|
"yes" | "y" | "YES" | "Y" => break Ok(()),
|
||||||
|
"no" | "n" | "NO" | "N" | "" => break Err(BinstallError::UserAbort),
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
confirm_tx
|
||||||
|
.blocking_send(res)
|
||||||
|
.expect("entry exits when confirming request");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
request_tx,
|
||||||
|
confirm_rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn confirm(&mut self) -> Result<(), BinstallError> {
|
||||||
|
self.request_tx
|
||||||
|
.send(())
|
||||||
|
.await
|
||||||
|
.map_err(|_| BinstallError::UserAbort)?;
|
||||||
|
|
||||||
|
self.confirm_rx
|
||||||
|
.recv()
|
||||||
|
.await
|
||||||
|
.unwrap_or(Err(BinstallError::UserAbort))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Confirmer(Option<ConfirmerInner>);
|
||||||
|
|
||||||
|
impl Confirmer {
|
||||||
|
/// * `enable` - `true` to enable confirmation, `false` to disable it.
|
||||||
|
pub fn new(enable: bool) -> Self {
|
||||||
|
Self(if enable {
|
||||||
|
Some(ConfirmerInner::new())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn confirm(&mut self) -> Result<(), BinstallError> {
|
||||||
|
if let Some(inner) = self.0.as_mut() {
|
||||||
|
inner.confirm().await
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue