diff --git a/src/uu/expand/src/expand.rs b/src/uu/expand/src/expand.rs index cbb5593f9..7976a0a97 100644 --- a/src/uu/expand/src/expand.rs +++ b/src/uu/expand/src/expand.rs @@ -126,12 +126,8 @@ fn tabstops_parse(s: &str) -> Result<(RemainingMode, Vec), ParseError> { let bytes = word.as_bytes(); for i in 0..bytes.len() { match bytes[i] { - b'+' => { - remaining_mode = RemainingMode::Plus; - } - b'/' => { - remaining_mode = RemainingMode::Slash; - } + b'+' => remaining_mode = RemainingMode::Plus, + b'/' => remaining_mode = RemainingMode::Slash, _ => { // Parse a number from the byte sequence. let s = from_utf8(&bytes[i..]).unwrap(); @@ -191,6 +187,10 @@ fn tabstops_parse(s: &str) -> Result<(RemainingMode, Vec), ParseError> { if nums.is_empty() { nums = vec![DEFAULT_TABSTOP]; } + + if nums.len() < 2 { + remaining_mode = RemainingMode::None; + } Ok((remaining_mode, nums)) } @@ -336,17 +336,19 @@ fn open(path: &str) -> BufReader> { /// in the `tabstops` slice is interpreted as a relative number of /// spaces, which this function will return for every input value of /// `col` beyond the end of the second-to-last element of `tabstops`. -/// -/// If `remaining_mode` is [`RemainingMode::Plus`], then the last entry -/// in the `tabstops` slice is interpreted as a relative number of -/// spaces, which this function will return for every input value of -/// `col` beyond the end of the second-to-last element of `tabstops`. fn next_tabstop(tabstops: &[usize], col: usize, remaining_mode: &RemainingMode) -> usize { let num_tabstops = tabstops.len(); match remaining_mode { RemainingMode::Plus => match tabstops[0..num_tabstops - 1].iter().find(|&&t| t > col) { Some(t) => t - col, - None => tabstops[num_tabstops - 1] - 1, + None => { + let step_size = tabstops[num_tabstops - 1]; + let last_fixed_tabstop = tabstops[num_tabstops - 2]; + let characters_since_last_tabstop = col - last_fixed_tabstop; + + let steps_required = 1 + characters_since_last_tabstop / step_size; + steps_required * step_size - characters_since_last_tabstop + } }, RemainingMode::Slash => match tabstops[0..num_tabstops - 1].iter().find(|&&t| t > col) { Some(t) => t - col, @@ -487,8 +489,8 @@ mod tests { #[test] fn test_next_tabstop_remaining_mode_plus() { assert_eq!(next_tabstop(&[1, 5], 0, &RemainingMode::Plus), 1); - assert_eq!(next_tabstop(&[1, 5], 3, &RemainingMode::Plus), 4); - assert_eq!(next_tabstop(&[1, 5], 6, &RemainingMode::Plus), 4); + assert_eq!(next_tabstop(&[1, 5], 3, &RemainingMode::Plus), 3); + assert_eq!(next_tabstop(&[1, 5], 6, &RemainingMode::Plus), 5); } #[test] diff --git a/tests/by-util/test_expand.rs b/tests/by-util/test_expand.rs index ac9eb1fad..5b4f269ea 100644 --- a/tests/by-util/test_expand.rs +++ b/tests/by-util/test_expand.rs @@ -298,3 +298,93 @@ fn test_tabs_and_tabs_shortcut_mixed() { // 01234567890 .stdout_is(" a b c"); } + +#[test] +fn test_ignore_initial_plus() { + new_ucmd!() + .args(&["--tabs=+3"]) + .pipe_in("\ta\tb\tc") + .succeeds() + // 01234567890 + .stdout_is(" a b c"); +} + +#[test] +fn test_ignore_initial_pluses() { + new_ucmd!() + .args(&["--tabs=++3"]) + .pipe_in("\ta\tb\tc") + .succeeds() + // 01234567890 + .stdout_is(" a b c"); +} + +#[test] +fn test_ignore_initial_slash() { + new_ucmd!() + .args(&["--tabs=/3"]) + .pipe_in("\ta\tb\tc") + .succeeds() + // 01234567890 + .stdout_is(" a b c"); +} + +#[test] +fn test_ignore_initial_slashes() { + new_ucmd!() + .args(&["--tabs=//3"]) + .pipe_in("\ta\tb\tc") + .succeeds() + // 01234567890 + .stdout_is(" a b c"); +} + +#[test] +fn test_ignore_initial_plus_slash_combination() { + new_ucmd!() + .args(&["--tabs=+/3"]) + .pipe_in("\ta\tb\tc") + .succeeds() + // 01234567890 + .stdout_is(" a b c"); +} + +#[test] +fn test_comma_with_plus_1() { + new_ucmd!() + .args(&["--tabs=3,+6"]) + .pipe_in("\t111\t222\t333") + .succeeds() + // 01234567890 + .stdout_is(" 111 222 333"); +} + +#[test] +fn test_comma_with_plus_2() { + new_ucmd!() + .args(&["--tabs=1,+5"]) + .pipe_in("\ta\tb\tc") + .succeeds() + // 01234567890 + .stdout_is(" a b c"); +} + +#[test] +fn test_comma_with_plus_3() { + new_ucmd!() + .args(&["--tabs=2,+5"]) + .pipe_in("a\tb\tc") + .succeeds() + // 01234567890 + .stdout_is("a b c"); +} + +#[test] +fn test_comma_with_plus_4() { + new_ucmd!() + .args(&["--tabs=1,3,+5"]) + .pipe_in("a\tb\tc") + .succeeds() + // 01234567890 + .stdout_is("a b c"); +}