diff --git a/src/uu/rm/Cargo.toml b/src/uu/rm/Cargo.toml index 01056009a..a7d959977 100644 --- a/src/uu/rm/Cargo.toml +++ b/src/uu/rm/Cargo.toml @@ -20,7 +20,7 @@ path = "src/rm.rs" [dependencies] thiserror = { workspace = true } clap = { workspace = true } -uucore = { workspace = true, features = ["fs"] } +uucore = { workspace = true, features = ["fs", "parser"] } fluent = { workspace = true } [target.'cfg(unix)'.dependencies] diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index 18c963611..5cda4b03d 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -5,7 +5,8 @@ // spell-checker:ignore (path) eacces inacc rm-r4 -use clap::{Arg, ArgAction, Command, builder::ValueParser, parser::ValueSource}; +use clap::builder::{PossibleValue, ValueParser}; +use clap::{Arg, ArgAction, Command, parser::ValueSource}; use std::ffi::{OsStr, OsString}; use std::fs::{self, Metadata}; use std::io::{IsTerminal, stdin}; @@ -19,6 +20,7 @@ use std::path::{Path, PathBuf}; use thiserror::Error; use uucore::display::Quotable; use uucore::error::{FromIo, UError, UResult}; +use uucore::parser::shortcut_value_parser::ShortcutValueParser; use uucore::translate; use uucore::{format_usage, os_str_as_bytes, prompt_yes, show_error}; @@ -249,6 +251,11 @@ pub fn uu_app() -> Command { .long(OPT_INTERACTIVE) .help(translate!("rm-help-interactive")) .value_name("WHEN") + .value_parser(ShortcutValueParser::new([ + PossibleValue::new("always").alias("yes"), + PossibleValue::new("once"), + PossibleValue::new("never").alias("no").alias("none"), + ])) .num_args(0..=1) .require_equals(true) .default_missing_value("always") diff --git a/tests/by-util/test_rm.rs b/tests/by-util/test_rm.rs index 5589286e7..ec7de9136 100644 --- a/tests/by-util/test_rm.rs +++ b/tests/by-util/test_rm.rs @@ -6,8 +6,7 @@ use std::process::Stdio; -use uutests::util::TestScenario; -use uutests::{at_and_ucmd, new_ucmd, util_name}; +use uutests::{at_and_ucmd, new_ucmd, util::TestScenario, util_name}; #[test] fn test_invalid_arg() { @@ -379,42 +378,53 @@ fn test_silently_accepts_presume_input_tty2() { fn test_interactive_never() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; + let file = "a"; - let file_2 = "test_rm_interactive"; + for arg in ["never", "no", "none"] { + at.touch(file); + #[cfg(feature = "chmod")] + scene.ccmd("chmod").arg("0").arg(file).succeeds(); - at.touch(file_2); - #[cfg(feature = "chmod")] - scene.ccmd("chmod").arg("0").arg(file_2).succeeds(); + scene + .ucmd() + .arg(format!("--interactive={arg}")) + .arg(file) + .succeeds() + .no_output(); - scene - .ucmd() - .arg("--interactive=never") - .arg(file_2) - .succeeds() - .stdout_is(""); - - assert!(!at.file_exists(file_2)); + assert!(!at.file_exists(file)); + } } #[test] -fn test_interactive_missing_value() { - // `--interactive` is equivalent to `--interactive=always` or `-i` - let (at, mut ucmd) = at_and_ucmd!(); +fn test_interactive_always() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; - let file1 = "test_rm_interactive_missing_value_file1"; - let file2 = "test_rm_interactive_missing_value_file2"; + let file_a = "a"; + let file_b = "b"; - at.touch(file1); - at.touch(file2); + for arg in [ + "-i", + "--interactive", + "--interactive=always", + "--interactive=yes", + ] { + at.touch(file_a); + at.touch(file_b); - ucmd.arg("--interactive") - .arg(file1) - .arg(file2) - .pipe_in("y\ny") - .succeeds(); + scene + .ucmd() + .arg(arg) + .arg(file_a) + .arg(file_b) + .pipe_in("y\ny") + .succeeds() + .no_stdout(); - assert!(!at.file_exists(file1)); - assert!(!at.file_exists(file2)); + assert!(!at.file_exists(file_a)); + assert!(!at.file_exists(file_b)); + } } #[test]