Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions src/uu/echo/src/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

for arg in args {
if arg == "--" && is_first_double_hyphen {
result.push(OsString::from("--"));
is_first_double_hyphen = false;
let mut is_first_argument = true;
let mut args_iter = args.into_iter();

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()
Expand Down
101 changes: 101 additions & 0 deletions tests/by-util/test_echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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]
Expand Down
Loading