Merge branch 'main' of https://github.com/nushell/engine-q into plugins

This commit is contained in:
Fernando Herrera
2021-11-01 07:24:33 +00:00
14 changed files with 641 additions and 238 deletions

View File

@ -15,7 +15,7 @@ impl Command for Use {
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("use").required("pattern", SyntaxShape::String, "import pattern")
Signature::build("use").rest("pattern", SyntaxShape::String, "import pattern parts")
}
fn run(

View File

@ -53,12 +53,15 @@ pub fn create_default_context() -> EngineState {
Math,
MathAbs,
MathAvg,
MathMax,
MathMin,
Mkdir,
Module,
Mv,
ParEach,
Ps,
Register,
Range,
Rm,
RunPlugin,
Select,

View File

@ -4,6 +4,7 @@ mod last;
mod length;
mod lines;
mod par_each;
mod range;
mod select;
mod where_;
mod wrap;
@ -14,6 +15,7 @@ pub use last::Last;
pub use length::Length;
pub use lines::Lines;
pub use par_each::ParEach;
pub use range::Range;
pub use select::Select;
pub use where_::Where;
pub use wrap::Wrap;

View File

@ -0,0 +1,127 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
Value,
};
#[derive(Clone)]
pub struct Range;
impl Command for Range {
fn name(&self) -> &str {
"range"
}
fn signature(&self) -> Signature {
Signature::build("range").optional(
"rows",
SyntaxShape::Range,
"range of rows to return: Eg) 4..7 (=> from 4 to 7)",
)
}
fn usage(&self) -> &str {
"Return only the selected rows."
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
example: "[0,1,2,3,4,5] | range 4..5",
description: "Get the last 2 items",
result: Some(Value::List {
vals: vec![Value::test_int(4), Value::test_int(5)],
span: Span::unknown(),
}),
},
Example {
example: "[0,1,2,3,4,5] | range (-2)..",
description: "Get the last 2 items",
result: Some(Value::List {
vals: vec![Value::test_int(4), Value::test_int(5)],
span: Span::unknown(),
}),
},
Example {
example: "[0,1,2,3,4,5] | range (-3)..-2",
description: "Get the next to last 2 items",
result: Some(Value::List {
vals: vec![Value::test_int(3), Value::test_int(4)],
span: Span::unknown(),
}),
},
]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let rows: nu_protocol::Range = call.req(engine_state, stack, 0)?;
let rows_from = get_range_val(rows.from);
let rows_to = get_range_val(rows.to);
// only collect the input if we have any negative indices
if rows_from < 0 || rows_to < 0 {
let v: Vec<_> = input.into_iter().collect();
let vlen: i64 = v.len() as i64;
let from = if rows_from < 0 {
(vlen + rows_from) as usize
} else {
rows_from as usize
};
let to = if rows_to < 0 {
(vlen + rows_to) as usize
} else if rows_to > v.len() as i64 {
v.len()
} else {
rows_to as usize
};
if from > to {
Ok(PipelineData::Value(Value::Nothing { span: call.head }))
} else {
let iter = v.into_iter().skip(from).take(to - from + 1);
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
}
} else {
let from = rows_from as usize;
let to = rows_to as usize;
if from > to {
Ok(PipelineData::Value(Value::Nothing { span: call.head }))
} else {
let iter = input.into_iter().skip(from).take(to - from + 1);
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
}
}
}
}
fn get_range_val(rows_val: Value) -> i64 {
match rows_val {
Value::Int { val: x, .. } => x,
_ => 0,
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(Range {})
}
}

View File

@ -50,6 +50,7 @@ pub fn average(values: &[Value], head: &Span) -> Result<Value, ShellError> {
span: Span::unknown(),
},
values.to_vec(),
*head,
)?;
match total {
Value::Filesize { val, span } => Ok(Value::Filesize {

View File

@ -0,0 +1,57 @@
use crate::math::reducers::{reducer_for, Reduce};
use crate::math::utils::run_with_function;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value};
#[derive(Clone)]
pub struct SubCommand;
impl Command for SubCommand {
fn name(&self) -> &str {
"math max"
}
fn signature(&self) -> Signature {
Signature::build("math max")
}
fn usage(&self) -> &str {
"Finds the maximum within a list of numbers or tables"
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
run_with_function(call, input, maximum)
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Find the maximum of list of numbers",
example: "[-50 100 25] | math max",
result: Some(Value::test_int(100)),
}]
}
}
pub fn maximum(values: &[Value], head: &Span) -> Result<Value, ShellError> {
let max_func = reducer_for(Reduce::Maximum);
max_func(Value::nothing(), values.to_vec(), *head)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(SubCommand {})
}
}

View File

@ -0,0 +1,57 @@
use crate::math::reducers::{reducer_for, Reduce};
use crate::math::utils::run_with_function;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Value};
#[derive(Clone)]
pub struct SubCommand;
impl Command for SubCommand {
fn name(&self) -> &str {
"math min"
}
fn signature(&self) -> Signature {
Signature::build("math min")
}
fn usage(&self) -> &str {
"Finds the minimum within a list of numbers or tables"
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
run_with_function(call, input, minimum)
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Get the minimum of a list of numbers",
example: "[-50 100 25] | math min",
result: Some(Value::test_int(-50)),
}]
}
}
pub fn minimum(values: &[Value], head: &Span) -> Result<Value, ShellError> {
let min_func = reducer_for(Reduce::Minimum);
min_func(Value::nothing(), values.to_vec(), *head)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(SubCommand {})
}
}

View File

@ -1,9 +1,13 @@
mod abs;
mod avg;
pub mod command;
mod max;
mod min;
mod reducers;
mod utils;
pub use abs::SubCommand as MathAbs;
pub use avg::SubCommand as MathAvg;
pub use command::MathCommand as Math;
pub use max::SubCommand as MathMax;
pub use min::SubCommand as MathMin;

View File

@ -1,19 +1,73 @@
use nu_protocol::{ShellError, Span, Value};
use std::cmp::Ordering;
#[allow(dead_code)]
pub enum Reduce {
Summation,
Minimum,
Maximum,
}
pub fn reducer_for(
command: Reduce,
) -> Box<dyn Fn(Value, Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static> {
pub type ReducerFunction =
Box<dyn Fn(Value, Vec<Value>, Span) -> Result<Value, ShellError> + Send + Sync + 'static>;
pub fn reducer_for(command: Reduce) -> ReducerFunction {
match command {
Reduce::Summation => Box::new(|_, values| sum(values)),
Reduce::Summation => Box::new(|_, values, head| sum(values, head)),
Reduce::Minimum => Box::new(|_, values, head| min(values, head)),
Reduce::Maximum => Box::new(|_, values, head| max(values, head)),
}
}
pub fn sum(data: Vec<Value>) -> Result<Value, ShellError> {
pub fn max(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
let mut biggest = data
.first()
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), Span::unknown()))?
.clone();
for value in &data {
if let Some(result) = value.partial_cmp(&biggest) {
if result == Ordering::Greater {
biggest = value.clone();
}
} else {
return Err(ShellError::OperatorMismatch {
op_span: head,
lhs_ty: biggest.get_type(),
lhs_span: biggest.span()?,
rhs_ty: value.get_type(),
rhs_span: value.span()?,
});
}
}
Ok(biggest)
}
pub fn min(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
let mut smallest = data
.first()
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), Span::unknown()))?
.clone();
for value in &data {
if let Some(result) = value.partial_cmp(&smallest) {
if result == Ordering::Less {
smallest = value.clone();
}
} else {
return Err(ShellError::OperatorMismatch {
op_span: head,
lhs_ty: smallest.get_type(),
lhs_span: smallest.span()?,
rhs_ty: value.get_type(),
rhs_span: value.span()?,
});
}
}
Ok(smallest)
}
pub fn sum(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
let initial_value = data.get(0);
let mut acc = match initial_value {
@ -42,7 +96,7 @@ pub fn sum(data: Vec<Value>) -> Result<Value, ShellError> {
| Value::Float { .. }
| Value::Filesize { .. }
| Value::Duration { .. } => {
let new_value = acc.add(acc.span().unwrap_or_else(|_| Span::unknown()), value);
let new_value = acc.add(head, value);
if new_value.is_err() {
return new_value;
}