mirror of
https://github.com/nushell/nushell.git
synced 2025-02-16 10:32:29 +01:00
parent
b4b7524206
commit
1fd7b9ac38
@ -94,6 +94,11 @@ pub fn create_default_context(cwd: impl AsRef<Path>) -> EngineState {
|
||||
Reject,
|
||||
Rename,
|
||||
Reverse,
|
||||
Roll,
|
||||
RollDown,
|
||||
RollUp,
|
||||
RollLeft,
|
||||
RollRight,
|
||||
Rotate,
|
||||
Select,
|
||||
Shuffle,
|
||||
|
@ -31,6 +31,7 @@ mod reduce;
|
||||
mod reject;
|
||||
mod rename;
|
||||
mod reverse;
|
||||
mod roll;
|
||||
mod rotate;
|
||||
mod select;
|
||||
mod shuffle;
|
||||
@ -78,6 +79,7 @@ pub use reduce::Reduce;
|
||||
pub use reject::Reject;
|
||||
pub use rename::Rename;
|
||||
pub use reverse::Reverse;
|
||||
pub use roll::*;
|
||||
pub use rotate::Rotate;
|
||||
pub use select::Select;
|
||||
pub use shuffle::Shuffle;
|
||||
|
101
crates/nu-command/src/filters/roll/mod.rs
Normal file
101
crates/nu-command/src/filters/roll/mod.rs
Normal file
@ -0,0 +1,101 @@
|
||||
mod roll_;
|
||||
mod roll_down;
|
||||
mod roll_left;
|
||||
mod roll_right;
|
||||
mod roll_up;
|
||||
|
||||
use nu_protocol::{ShellError, Value};
|
||||
pub use roll_::Roll;
|
||||
pub use roll_down::RollDown;
|
||||
pub use roll_left::RollLeft;
|
||||
pub use roll_right::RollRight;
|
||||
pub use roll_up::RollUp;
|
||||
|
||||
enum VerticalDirection {
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
fn vertical_rotate_value(
|
||||
value: Value,
|
||||
by: Option<usize>,
|
||||
direction: VerticalDirection,
|
||||
) -> Result<Value, ShellError> {
|
||||
match value {
|
||||
Value::List { mut vals, span } => {
|
||||
let rotations = by.map(|n| n % vals.len()).unwrap_or(1);
|
||||
let values = vals.as_mut_slice();
|
||||
|
||||
match direction {
|
||||
VerticalDirection::Up => values.rotate_left(rotations),
|
||||
VerticalDirection::Down => values.rotate_right(rotations),
|
||||
}
|
||||
|
||||
Ok(Value::List {
|
||||
vals: values.to_owned(),
|
||||
span,
|
||||
})
|
||||
}
|
||||
_ => Err(ShellError::TypeMismatch("list".to_string(), value.span()?)),
|
||||
}
|
||||
}
|
||||
|
||||
enum HorizontalDirection {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
fn horizontal_rotate_value(
|
||||
value: Value,
|
||||
by: &Option<usize>,
|
||||
cells_only: bool,
|
||||
direction: &HorizontalDirection,
|
||||
) -> Result<Value, ShellError> {
|
||||
match value {
|
||||
Value::Record {
|
||||
mut cols,
|
||||
mut vals,
|
||||
span,
|
||||
} => {
|
||||
let rotations = by.map(|n| n % vals.len()).unwrap_or(1);
|
||||
|
||||
let columns = if cells_only {
|
||||
cols
|
||||
} else {
|
||||
let columns = cols.as_mut_slice();
|
||||
|
||||
match direction {
|
||||
HorizontalDirection::Right => columns.rotate_right(rotations),
|
||||
HorizontalDirection::Left => columns.rotate_left(rotations),
|
||||
}
|
||||
|
||||
columns.to_owned()
|
||||
};
|
||||
|
||||
let values = vals.as_mut_slice();
|
||||
|
||||
match direction {
|
||||
HorizontalDirection::Right => values.rotate_right(rotations),
|
||||
HorizontalDirection::Left => values.rotate_left(rotations),
|
||||
}
|
||||
|
||||
Ok(Value::Record {
|
||||
cols: columns,
|
||||
vals: values.to_owned(),
|
||||
span,
|
||||
})
|
||||
}
|
||||
Value::List { vals, span } => {
|
||||
let values = vals
|
||||
.into_iter()
|
||||
.map(|value| horizontal_rotate_value(value, by, cells_only, direction))
|
||||
.collect::<Result<Vec<Value>, ShellError>>()?;
|
||||
|
||||
Ok(Value::List { vals: values, span })
|
||||
}
|
||||
_ => Err(ShellError::TypeMismatch(
|
||||
"record".to_string(),
|
||||
value.span()?,
|
||||
)),
|
||||
}
|
||||
}
|
35
crates/nu-command/src/filters/roll/roll_.rs
Normal file
35
crates/nu-command/src/filters/roll/roll_.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use nu_engine::get_full_help;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, IntoPipelineData, PipelineData, ShellError, Signature, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Roll;
|
||||
|
||||
impl Command for Roll {
|
||||
fn name(&self) -> &str {
|
||||
"roll"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name()).category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Rolling commands for tables"
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
Ok(Value::String {
|
||||
val: get_full_help(&Roll.signature(), &Roll.examples(), engine_state, stack),
|
||||
span: call.head,
|
||||
}
|
||||
.into_pipeline_data())
|
||||
}
|
||||
}
|
82
crates/nu-command/src/filters/roll/roll_down.rs
Normal file
82
crates/nu-command/src/filters/roll/roll_down.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
};
|
||||
|
||||
use super::{vertical_rotate_value, VerticalDirection};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RollDown;
|
||||
|
||||
impl Command for RollDown {
|
||||
fn name(&self) -> &str {
|
||||
"roll down"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.named("by", SyntaxShape::Int, "Number of rows to roll", Some('b'))
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Roll table rows down"
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let columns = vec!["a".to_string(), "b".to_string()];
|
||||
vec![Example {
|
||||
description: "Rolls rows down",
|
||||
example: "[[a b]; [1 2] [3 4] [5 6]] | roll down",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::Record {
|
||||
cols: columns.clone(),
|
||||
vals: vec![Value::test_int(5), Value::test_int(6)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: columns.clone(),
|
||||
vals: vec![Value::test_int(1), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: columns,
|
||||
vals: vec![Value::test_int(3), Value::test_int(4)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
}]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, ShellError> {
|
||||
let by: Option<usize> = call.get_flag(engine_state, stack, "by")?;
|
||||
let value = input.into_value(call.head);
|
||||
let rotated_value = vertical_rotate_value(value, by, VerticalDirection::Down)?;
|
||||
|
||||
Ok(rotated_value.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(RollDown {})
|
||||
}
|
||||
}
|
111
crates/nu-command/src/filters/roll/roll_left.rs
Normal file
111
crates/nu-command/src/filters/roll/roll_left.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
};
|
||||
|
||||
use super::{horizontal_rotate_value, HorizontalDirection};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RollLeft;
|
||||
|
||||
impl Command for RollLeft {
|
||||
fn name(&self) -> &str {
|
||||
"roll left"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.named(
|
||||
"by",
|
||||
SyntaxShape::Int,
|
||||
"Number of columns to roll",
|
||||
Some('b'),
|
||||
)
|
||||
.switch(
|
||||
"cells-only",
|
||||
"rotates columns leaving headers fixed",
|
||||
Some('c'),
|
||||
)
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Roll table columns left"
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let columns = vec!["a".to_string(), "b".to_string(), "c".to_string()];
|
||||
let rotated_columns = vec!["b".to_string(), "c".to_string(), "a".to_string()];
|
||||
vec![
|
||||
Example {
|
||||
description: "Rolls columns to the left",
|
||||
example: "[[a b c]; [1 2 3] [4 5 6]] | roll left",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::Record {
|
||||
cols: rotated_columns.clone(),
|
||||
vals: vec![Value::test_int(2), Value::test_int(3), Value::test_int(1)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: rotated_columns,
|
||||
vals: vec![Value::test_int(5), Value::test_int(6), Value::test_int(4)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Rolls columns to the left with fixed headers",
|
||||
example: "[[a b c]; [1 2 3] [4 5 6]] | roll left --cells-only",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::Record {
|
||||
cols: columns.clone(),
|
||||
vals: vec![Value::test_int(2), Value::test_int(3), Value::test_int(1)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: columns,
|
||||
vals: vec![Value::test_int(5), Value::test_int(6), Value::test_int(4)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, ShellError> {
|
||||
let by: Option<usize> = call.get_flag(engine_state, stack, "by")?;
|
||||
let cells_only = call.has_flag("cells-only");
|
||||
let value = input.into_value(call.head);
|
||||
let rotated_value =
|
||||
horizontal_rotate_value(value, &by, cells_only, &HorizontalDirection::Left)?;
|
||||
|
||||
Ok(rotated_value.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(RollLeft {})
|
||||
}
|
||||
}
|
111
crates/nu-command/src/filters/roll/roll_right.rs
Normal file
111
crates/nu-command/src/filters/roll/roll_right.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
};
|
||||
|
||||
use super::{horizontal_rotate_value, HorizontalDirection};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RollRight;
|
||||
|
||||
impl Command for RollRight {
|
||||
fn name(&self) -> &str {
|
||||
"roll right"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.named(
|
||||
"by",
|
||||
SyntaxShape::Int,
|
||||
"Number of columns to roll",
|
||||
Some('b'),
|
||||
)
|
||||
.switch(
|
||||
"cells-only",
|
||||
"rotates columns leaving headers fixed",
|
||||
Some('c'),
|
||||
)
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Roll table columns right"
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let columns = vec!["a".to_string(), "b".to_string(), "c".to_string()];
|
||||
let rotated_columns = vec!["c".to_string(), "a".to_string(), "b".to_string()];
|
||||
vec![
|
||||
Example {
|
||||
description: "Rolls columns to the right",
|
||||
example: "[[a b c]; [1 2 3] [4 5 6]] | roll right",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::Record {
|
||||
cols: rotated_columns.clone(),
|
||||
vals: vec![Value::test_int(3), Value::test_int(1), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: rotated_columns,
|
||||
vals: vec![Value::test_int(6), Value::test_int(4), Value::test_int(5)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Rolls columns to the right with fixed headers",
|
||||
example: "[[a b c]; [1 2 3] [4 5 6]] | roll right --cells-only",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::Record {
|
||||
cols: columns.clone(),
|
||||
vals: vec![Value::test_int(3), Value::test_int(1), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: columns,
|
||||
vals: vec![Value::test_int(6), Value::test_int(4), Value::test_int(5)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, ShellError> {
|
||||
let by: Option<usize> = call.get_flag(engine_state, stack, "by")?;
|
||||
let cells_only = call.has_flag("cells-only");
|
||||
let value = input.into_value(call.head);
|
||||
let rotated_value =
|
||||
horizontal_rotate_value(value, &by, cells_only, &HorizontalDirection::Right)?;
|
||||
|
||||
Ok(rotated_value.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(RollRight {})
|
||||
}
|
||||
}
|
82
crates/nu-command/src/filters/roll/roll_up.rs
Normal file
82
crates/nu-command/src/filters/roll/roll_up.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
};
|
||||
|
||||
use super::{vertical_rotate_value, VerticalDirection};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RollUp;
|
||||
|
||||
impl Command for RollUp {
|
||||
fn name(&self) -> &str {
|
||||
"roll up"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.named("by", SyntaxShape::Int, "Number of rows to roll", Some('b'))
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Roll table rows up"
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let columns = vec!["a".to_string(), "b".to_string()];
|
||||
vec![Example {
|
||||
description: "Rolls rows up",
|
||||
example: "[[a b]; [1 2] [3 4] [5 6]] | roll up",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::Record {
|
||||
cols: columns.clone(),
|
||||
vals: vec![Value::test_int(3), Value::test_int(4)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: columns.clone(),
|
||||
vals: vec![Value::test_int(5), Value::test_int(6)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: columns,
|
||||
vals: vec![Value::test_int(1), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
}]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, ShellError> {
|
||||
let by: Option<usize> = call.get_flag(engine_state, stack, "by")?;
|
||||
let value = input.into_value(call.head);
|
||||
let rotated_value = vertical_rotate_value(value, by, VerticalDirection::Up)?;
|
||||
|
||||
Ok(rotated_value.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(RollUp {})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user