diff --git a/src/uu/fold/src/fold.rs b/src/uu/fold/src/fold.rs index 3bcb55e51..54cb41e27 100644 --- a/src/uu/fold/src/fold.rs +++ b/src/uu/fold/src/fold.rs @@ -132,7 +132,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, } @@ -175,7 +175,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. @@ -192,11 +191,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; }; @@ -221,6 +219,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; @@ -229,32 +228,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' => { if col_count > 0 { col_count -= 1; } } - '\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 char_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 287b05157..61c057782 100644 --- a/tests/by-util/test_fold.rs +++ b/tests/by-util/test_fold.rs @@ -285,6 +285,34 @@ fn test_backspace_is_not_word_boundary() { .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 @@ -470,3 +498,39 @@ fn test_bytewise_backspace_is_not_word_boundary() { .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"); +}