nushell/crates/nu-command/src/commands/roll/mod.rs
Andrés N. Robalino 7a77910720
Table content rolling. (#3097)
There are many use cases. Here we introduce the following:

- The rows can be rolled `... | roll` (up) or `... | roll down`
- Columns can be rolled too (the default is on the `left`, you can pass `... | roll column --opposite` to roll in the other direction)
- You can `roll` the cells of a table and keeping the header names in the same order (`... | roll column --cells-only`)
- Above examples can also be passed (Ex. `... | roll down 3`) a number to tell how many places to roll.

Basic working example with rolling columns:

```
> echo '00000100'
| split chars
| each { str to-int }
| rotate counter-clockwise _
| reject _
| rename bit1 bit2 bit3 bit4 bit5 bit6 bit7 bit8

───┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────
 # │ bit1 │ bit2 │ bit3 │ bit4 │ bit5 │ bit6 │ bit7 │ bit8
───┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────
 0 │    0 │    0 │    0 │    0 │    0 │    1 │    0 │    0
───┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────
```

We want to "shift" three bits to the left of the bitstring (four in decimal), let's try it:

```
> echo '00000100'
| split chars
| each { str to-int }
| rotate counter-clockwise _
| reject _
| rename bit1 bit2 bit3 bit4 bit5 bit6 bit7 bit8
| roll column 3

───┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────
 # │ bit4 │ bit5 │ bit6 │ bit7 │ bit8 │ bit1 │ bit2 │ bit3
───┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────
 0 │    0 │    0 │    1 │    0 │    0 │    0 │    0 │    0
───┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────
```

The tables was rolled correctly (32 in decimal, for above bitstring). However, the *last three header names* look confusing.
We can roll the cell contents only to fix it.

```
> echo '00000100'
| split chars
| each { str to-int }
| rotate counter-clockwise _
| reject _
| rename bit1 bit2 bit3 bit4 bit5 bit6 bit7 bit8
| roll column 3 --cells-only

───┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────
 # │ bit1 │ bit2 │ bit3 │ bit4 │ bit5 │ bit6 │ bit7 │ bit8
───┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────
 0 │    0 │    0 │    1 │    0 │    0 │    0 │    0 │    0
───┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────
```

There we go. Let's compute it's decimal value now (should be 32)

```
> echo '00000100'
| split chars
| each { str to-int }
| rotate counter-clockwise _
| reject _
| roll column 3 --cells-only
| pivot bit --ignore-titles
| get bit
| reverse
| each --numbered { = $it.item * (2 ** $it.index) }
| math sum

32
```
2021-02-23 13:29:07 -05:00

43 lines
894 B
Rust

mod column;
mod command;
mod up;
pub use column::SubCommand as RollColumn;
pub use command::Command as Roll;
pub use up::SubCommand as RollUp;
mod support {
pub enum Direction {
Left,
Right,
Down,
Up,
}
pub fn rotate<T: Clone>(
mut collection: Vec<T>,
n: &Option<nu_source::Tagged<u64>>,
direction: Direction,
) -> Option<Vec<T>> {
if collection.is_empty() {
return None;
}
let values = collection.as_mut_slice();
let rotations = if let Some(n) = n {
n.item as usize % values.len()
} else {
1
};
match direction {
Direction::Up | Direction::Right => values.rotate_left(rotations),
Direction::Down | Direction::Left => values.rotate_right(rotations),
}
Some(values.to_vec())
}
}