From 6cdcfca573357825e762a5742224b627f22255cd Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 16 Nov 2022 15:11:44 +0100 Subject: [PATCH] uucore: add prompt_yes!() and read_yes() These functions are based on existing functions and macros in utils `cp`, `ln`, `mv ` and `rm`. This unifies the separate implementations. --- src/uucore/src/lib/lib.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 662a371c4..66f8881d6 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -166,6 +166,44 @@ pub fn args_os() -> impl Iterator { ARGV.iter().cloned() } +/// Read a line from stdin and check whether the first character is `'y'` or `'Y'` +pub fn read_yes() -> bool { + let mut s = String::new(); + match std::io::stdin().read_line(&mut s) { + Ok(_) => matches!(s.chars().next(), Some('y' | 'Y')), + _ => false, + } +} + +/// Prompt the user with a formatted string and returns `true` if they reply `'y'` or `'Y'` +/// +/// This macro functions accepts the same syntax as `format!`. The prompt is written to +/// `stderr`. A space is also printed at the end for nice spacing between the prompt and +/// the user input. Any input starting with `'y'` or `'Y'` is interpreted as `yes`. +/// +/// # Examples +/// ``` +/// use uucore::prompt_yes; +/// let file = "foo.rs"; +/// prompt_yes!("Do you want to delete '{}'?", file); +/// ``` +/// will print something like below to `stderr` (with `util_name` substituted by the actual +/// util name) and will wait for user input. +/// ```txt +/// util_name: Do you want to delete 'foo.rs'? +/// ``` +#[macro_export] +macro_rules! prompt_yes( + ($($args:tt)+) => ({ + use std::io::Write; + eprint!("{}: ", uucore::util_name()); + eprint!($($args)+); + eprint!(" "); + uucore::crash_if_err!(1, std::io::stderr().flush()); + uucore::read_yes() + }) +); + #[cfg(test)] mod tests { use super::*;