diff --git a/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs b/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs index 282459e4ee..dd8af6dcbe 100644 --- a/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs +++ b/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs @@ -25,7 +25,8 @@ fn vertical_rotate_value( let span = value.span(); match value { Value::List { mut vals, .. } => { - let rotations = by.map(|n| n % vals.len()).unwrap_or(1); + // `checked_rem` is `None` for an empty list, so there is nothing to rotate. + let rotations = by.unwrap_or(1).checked_rem(vals.len()).unwrap_or(0); let values = vals.to_mut().as_mut_slice(); match direction { @@ -56,7 +57,8 @@ fn horizontal_rotate_value( let span = value.span(); match value { Value::Record { val: record, .. } => { - let rotations = by.map(|n| n % record.len()).unwrap_or(1); + // `checked_rem` is `None` for an empty record, so there is nothing to rotate. + let rotations = by.unwrap_or(1).checked_rem(record.len()).unwrap_or(0); let (mut cols, mut vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip(); if !cells_only { diff --git a/crates/nu-command/tests/commands/roll.rs b/crates/nu-command/tests/commands/roll.rs index 668deebbd3..28716d1b2d 100644 --- a/crates/nu-command/tests/commands/roll.rs +++ b/crates/nu-command/tests/commands/roll.rs @@ -26,6 +26,23 @@ mod rows { test().run_with_data(code, table()).expect_value_eq("HERE") } + + #[test] + fn roll_down_empty_list_is_unchanged() -> Result { + test().run("[] | roll down").expect_value_eq(test_list![]) + } + + #[test] + fn roll_up_empty_list_is_unchanged() -> Result { + test().run("[] | roll up").expect_value_eq(test_list![]) + } + + #[test] + fn roll_up_empty_list_with_by_is_unchanged() -> Result { + test() + .run("[] | roll up --by 3") + .expect_value_eq(test_list![]) + } } mod columns { @@ -72,6 +89,34 @@ mod columns { .expect_value_eq(expected_value.1) } + #[test] + fn roll_left_empty_record_is_unchanged() -> Result { + test() + .run("{} | roll left") + .expect_value_eq(test_record! {}) + } + + #[test] + fn roll_right_empty_record_is_unchanged() -> Result { + test() + .run("{} | roll right") + .expect_value_eq(test_record! {}) + } + + #[test] + fn roll_left_empty_record_in_a_list_is_unchanged() -> Result { + test() + .run("[{} {}] | roll left --by 2 | to nuon") + .expect_value_eq("[{}, {}]") + } + + #[test] + fn roll_left_skips_empty_row_in_a_table() -> Result { + test() + .run("[{a: 1, b: 2} {}] | roll left | to nuon") + .expect_value_eq("[{b: 2, a: 1}, {}]") + } + #[test] fn four_in_bitstring_left_shifted_with_three_bits_should_be_32_in_decimal() -> Result { let four_bitstring = "00000100";