diff --git a/src/uu/echo/src/echo.rs b/src/uu/echo/src/echo.rs index c8d31a729..7ce2fa9ad 100644 --- a/src/uu/echo/src/echo.rs +++ b/src/uu/echo/src/echo.rs @@ -23,18 +23,32 @@ mod options { pub const DISABLE_BACKSLASH_ESCAPE: &str = "disable_backslash_escape"; } +fn is_echo_flag(arg: &OsString) -> bool { + matches!(arg.to_str(), Some("-e" | "-E" | "-n")) +} + // A workaround because clap interprets the first '--' as a marker that a value // follows. In order to use '--' as a value, we have to inject an additional '--' fn handle_double_hyphens(args: impl uucore::Args) -> impl uucore::Args { let mut result = Vec::new(); - let mut is_first_double_hyphen = true; + let mut is_first_argument = true; + let mut args_iter = args.into_iter(); - for arg in args { - if arg == "--" && is_first_double_hyphen { - result.push(OsString::from("--")); - is_first_double_hyphen = false; + if let Some(first_val) = args_iter.next() { + // the first argument ('echo') gets pushed before we start with the checks for flags/'--' + result.push(first_val); + // We need to skip any possible Flag arguments until we find the first argument to echo that + // is not a flag. If the first argument is double hyphen we inject an additional '--' + // otherwise we switch is_first_argument boolean to skip the checks for any further arguments + for arg in args_iter { + if is_first_argument && !is_echo_flag(&arg) { + is_first_argument = false; + if arg == "--" { + result.push(OsString::from("--")); + } + } + result.push(arg); } - result.push(arg); } result.into_iter() diff --git a/tests/by-util/test_echo.rs b/tests/by-util/test_echo.rs index d4430d056..9e2f686af 100644 --- a/tests/by-util/test_echo.rs +++ b/tests/by-util/test_echo.rs @@ -242,6 +242,84 @@ fn test_hyphen_values_between() { .stdout_is("dumdum dum dum dum -e dum\n"); } +#[test] +fn test_double_hyphens_at_start() { + new_ucmd!().arg("--").succeeds().stdout_only("--\n"); + new_ucmd!() + .arg("--") + .arg("--") + .succeeds() + .stdout_only("-- --\n"); + + new_ucmd!() + .arg("--") + .arg("a") + .succeeds() + .stdout_only("-- a\n"); + + new_ucmd!() + .arg("--") + .arg("a") + .arg("b") + .succeeds() + .stdout_only("-- a b\n"); + + new_ucmd!() + .arg("--") + .arg("a") + .arg("b") + .arg("--") + .succeeds() + .stdout_only("-- a b --\n"); +} + +#[test] +fn test_double_hyphens_after_flags() { + new_ucmd!() + .arg("-e") + .arg("--") + .succeeds() + .stdout_only("--\n"); + + new_ucmd!() + .arg("-n") + .arg("-e") + .arg("--") + .arg("foo\n") + .succeeds() + .stdout_only("-- foo\n"); + + new_ucmd!() + .arg("-e") + .arg("--") + .arg("--") + .succeeds() + .stdout_only("-- --\n"); + + new_ucmd!() + .arg("-e") + .arg("--") + .arg("a") + .arg("--") + .succeeds() + .stdout_only("-- a --\n"); + + new_ucmd!() + .arg("-n") + .arg("--") + .arg("a") + .succeeds() + .stdout_only("-- a"); + + new_ucmd!() + .arg("-n") + .arg("--") + .arg("a") + .arg("--") + .succeeds() + .stdout_only("-- a --"); +} + #[test] fn test_double_hyphens() { new_ucmd!().arg("--").succeeds().stdout_only("--\n"); @@ -250,6 +328,29 @@ fn test_double_hyphens() { .arg("--") .succeeds() .stdout_only("-- --\n"); + + new_ucmd!() + .arg("a") + .arg("--") + .arg("b") + .succeeds() + .stdout_only("a -- b\n"); + + new_ucmd!() + .arg("a") + .arg("--") + .arg("b") + .arg("--") + .succeeds() + .stdout_only("a -- b --\n"); + + new_ucmd!() + .arg("a") + .arg("b") + .arg("--") + .arg("--") + .succeeds() + .stdout_only("a b -- --\n"); } #[test]