diff --git a/src/uu/fold/src/fold.rs b/src/uu/fold/src/fold.rs index e19e9db19..cfd3b74cf 100644 --- a/src/uu/fold/src/fold.rs +++ b/src/uu/fold/src/fold.rs @@ -156,7 +156,7 @@ fn fold_file_bytewise(mut file: BufReader, spaces: bool, width: usiz let slice = { let slice = &line[i..i + width]; if spaces && i + width < len { - match slice.rfind(char::is_whitespace) { + match slice.rfind(|c: char| c.is_whitespace() && c != '\r') { Some(m) => &slice[..=m], None => slice, } @@ -199,7 +199,6 @@ fn fold_file(mut file: BufReader, spaces: bool, width: usize) { let mut line = String::new(); let mut output = String::new(); let mut col_count = 0; - let mut char_count = 0; let mut last_space = None; /// Print the output line, resetting the column and character counts. @@ -216,11 +215,10 @@ fn fold_file(mut file: BufReader, spaces: bool, width: usize) { println!("{}", &output[..consume]); output.replace_range(..consume, ""); - char_count = output.len(); // we know there are no tabs left in output, so each char counts // as 1 column - col_count = char_count; + col_count = output.len(); last_space = None; }; @@ -245,6 +243,7 @@ fn fold_file(mut file: BufReader, spaces: bool, width: usize) { } match ch { + '\r' => col_count = 0, '\t' => { let next_tab_stop = col_count + TAB_WIDTH - col_count % TAB_WIDTH; @@ -253,36 +252,24 @@ fn fold_file(mut file: BufReader, spaces: bool, width: usize) { } col_count = next_tab_stop; - last_space = if spaces { Some(char_count) } else { None }; + last_space = if spaces { Some(output.len()) } else { None }; } '\x08' => { - // FIXME: does not match GNU's handling of backspace if col_count > 0 { col_count -= 1; - char_count -= 1; - output.truncate(char_count); } - continue; - } - '\r' => { - // FIXME: does not match GNU's handling of carriage return - output.truncate(0); - col_count = 0; - char_count = 0; - continue; } _ if spaces && ch.is_whitespace() => { - last_space = Some(char_count); - col_count += 1 + last_space = Some(output.len()); + col_count += 1; } _ => col_count += 1, }; output.push(ch); - char_count += 1; } - if col_count > 0 { + if !output.is_empty() { print!("{}", output); output.truncate(0); } diff --git a/tests/by-util/test_fold.rs b/tests/by-util/test_fold.rs index bdc5e2246..ffcd65737 100644 --- a/tests/by-util/test_fold.rs +++ b/tests/by-util/test_fold.rs @@ -248,6 +248,71 @@ fn test_fold_at_word_boundary_only_whitespace_preserve_final_newline() { .stdout_is(" \n \n"); } +#[test] +fn test_backspace_should_be_preserved() { + new_ucmd!().pipe_in("\x08").succeeds().stdout_is("\x08"); +} + +#[test] +fn test_backspaced_char_should_be_preserved() { + new_ucmd!().pipe_in("x\x08").succeeds().stdout_is("x\x08"); +} + +#[test] +fn test_backspace_should_decrease_column_count() { + new_ucmd!() + .arg("-w2") + .pipe_in("1\x08345") + .succeeds() + .stdout_is("1\x0834\n5"); +} + +#[test] +fn test_backspace_should_not_decrease_column_count_past_zero() { + new_ucmd!() + .arg("-w2") + .pipe_in("1\x08\x083456") + .succeeds() + .stdout_is("1\x08\x0834\n56"); +} + +#[test] +fn test_backspace_is_not_word_boundary() { + new_ucmd!() + .args(&["-w10", "-s"]) + .pipe_in("foobar\x086789abcdef") + .succeeds() + .stdout_is("foobar\x086789a\nbcdef"); +} + +#[test] +fn test_carriage_return_should_be_preserved() { + new_ucmd!().pipe_in("\r").succeeds().stdout_is("\r"); +} + +#[test] +fn test_carriage_return_overwrriten_char_should_be_preserved() { + new_ucmd!().pipe_in("x\ry").succeeds().stdout_is("x\ry"); +} + +#[test] +fn test_carriage_return_should_reset_column_count() { + new_ucmd!() + .arg("-w6") + .pipe_in("12345\r123456789abcdef") + .succeeds() + .stdout_is("12345\r123456\n789abc\ndef"); +} + +#[test] +fn test_carriage_return_is_not_word_boundary() { + new_ucmd!() + .args(&["-w6", "-s"]) + .pipe_in("fizz\rbuzz\rfizzbuzz") + .succeeds() + .stdout_is("fizz\rbuzz\rfizzbu\nzz"); +} + // // bytewise tests @@ -398,6 +463,77 @@ fn test_bytewise_fold_at_word_boundary_only_whitespace_preserve_final_newline() .stdout_is(" \n \n"); } +#[test] +fn test_bytewise_backspace_should_be_preserved() { + new_ucmd!() + .arg("-b") + .pipe_in("\x08") + .succeeds() + .stdout_is("\x08"); +} + +#[test] +fn test_bytewise_backspaced_char_should_be_preserved() { + new_ucmd!() + .arg("-b") + .pipe_in("x\x08") + .succeeds() + .stdout_is("x\x08"); +} + +#[test] +fn test_bytewise_backspace_should_not_decrease_column_count() { + new_ucmd!() + .args(&["-w2", "-b"]) + .pipe_in("1\x08345") + .succeeds() + .stdout_is("1\x08\n34\n5"); +} + +#[test] +fn test_bytewise_backspace_is_not_word_boundary() { + new_ucmd!() + .args(&["-w10", "-s", "-b"]) + .pipe_in("foobar\x0889abcdef") + .succeeds() + .stdout_is("foobar\x0889a\nbcdef"); +} + +#[test] +fn test_bytewise_carriage_return_should_be_preserved() { + new_ucmd!() + .arg("-b") + .pipe_in("\r") + .succeeds() + .stdout_is("\r"); +} + +#[test] +fn test_bytewise_carriage_return_overwrriten_char_should_be_preserved() { + new_ucmd!() + .arg("-b") + .pipe_in("x\ry") + .succeeds() + .stdout_is("x\ry"); +} + +#[test] +fn test_bytewise_carriage_return_should_not_reset_column_count() { + new_ucmd!() + .args(&["-w6", "-b"]) + .pipe_in("12345\r123456789abcdef") + .succeeds() + .stdout_is("12345\r\n123456\n789abc\ndef"); +} + +#[test] +fn test_bytewise_carriage_return_is_not_word_boundary() { + new_ucmd!() + .args(&["-w6", "-s", "-b"]) + .pipe_in("fizz\rbuzz\rfizzbuzz") + .succeeds() + .stdout_is("fizz\rb\nuzz\rfi\nzzbuzz"); +} #[test] fn test_obsolete_syntax() { new_ucmd!() @@ -406,4 +542,4 @@ fn test_obsolete_syntax() { .arg("space_separated_words.txt") .succeeds() .stdout_is("test1\n \ntest2\n \ntest3\n \ntest4\n \ntest5\n \ntest6\n "); -} +} \ No newline at end of file