diff --git a/src/sed/command.rs b/src/sed/command.rs index 250bcbc5..79681743 100644 --- a/src/sed/command.rs +++ b/src/sed/command.rs @@ -70,6 +70,8 @@ pub struct ProcessingContext { pub substitution_made: bool, /// Elements to append at the end of each command processing cycle pub append_elements: Vec, + /// True if a delete command was executed (prevents automatic printing) + pub pattern_deleted: bool, } #[derive(Clone, Debug)] diff --git a/src/sed/mod.rs b/src/sed/mod.rs index 8caef1d5..eef9a955 100644 --- a/src/sed/mod.rs +++ b/src/sed/mod.rs @@ -217,6 +217,7 @@ fn build_context(matches: &ArgMatches) -> ProcessingContext { range_commands: Vec::new(), substitution_made: false, append_elements: Vec::new(), + pattern_deleted: false, } } diff --git a/src/sed/processor.rs b/src/sed/processor.rs index 16781782..7f1432f0 100644 --- a/src/sed/processor.rs +++ b/src/sed/processor.rs @@ -435,6 +435,7 @@ fn process_file( 'lines: while let Some(mut pattern) = reader.get_line()? { context.line_number += 1; context.substitution_made = false; + context.pattern_deleted = false; // Set the script command from which to start. let mut current: Option>> = if let Some(action) = context.input_action.take() { @@ -494,6 +495,7 @@ fn process_file( // At range end replace pattern space with text and // start the next cycle. pattern.clear(); + context.pattern_deleted = true; if command.addr2.is_none() || context.last_address || reader.last_line()? { let text = extract_variant!(command, Text); output.write_str(text.as_ref())?; @@ -503,6 +505,7 @@ fn process_file( 'd' => { // Delete the pattern space and start the next cycle. pattern.clear(); + context.pattern_deleted = true; break; } 'D' => { @@ -515,6 +518,7 @@ fn process_file( } else { // Same as d pattern.clear(); + context.pattern_deleted = true; break; } } @@ -653,7 +657,7 @@ fn process_file( current = command.next.clone(); } - if !context.quiet { + if !context.quiet && !context.pattern_deleted { write_chunk(output, context, &pattern)?; } diff --git a/tests/by-util/test_sed.rs b/tests/by-util/test_sed.rs index b0baf479..a19fb105 100644 --- a/tests/by-util/test_sed.rs +++ b/tests/by-util/test_sed.rs @@ -1232,3 +1232,45 @@ fn test_exchange_command_adds_newline() { .succeeds() .stdout_is("a\n\nc\n"); } + +//////////////////////////////////////////////////////////// +// Test for delete command preventing automatic pattern printing +#[test] +fn test_delete_command_prevents_automatic_printing() { + // Test 'd' command - delete line 2 + new_ucmd!() + .args(&["2d"]) + .pipe_in("line1\nline2\nline3") + .succeeds() + .stdout_is("line1\nline3"); +} + +#[test] +fn test_delete_range_prevents_automatic_printing() { + // Test 'd' command on range - delete lines 2-3 + new_ucmd!() + .args(&["2,3d"]) + .pipe_in("line1\nline2\nline3\nline4") + .succeeds() + .stdout_is("line1\nline4"); +} + +#[test] +fn test_change_command_prevents_automatic_printing() { + // Test 'c' command - change line 2 + new_ucmd!() + .args(&["2c\\replaced"]) + .pipe_in("line1\nline2\nline3") + .succeeds() + .stdout_is("line1\nreplaced\nline3"); +} + +#[test] +fn test_uppercase_delete_prevents_automatic_printing() { + // Test 'D' command - delete up to newline and restart + new_ucmd!() + .args(&["-e", "N", "-e", "D"]) + .pipe_in("line1\nline2\nline3") + .succeeds() + .stdout_is("line3\n"); +}