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.
@@ -166,6 +166,44 @@ pub fn args_os() -> impl Iterator<Item = OsString> {
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::*;
