mirror of
https://github.com/nushell/nushell
synced 2024-12-28 22:13:10 +00:00
Merge pull request #266 from luccasmmg/engine-q-math-2
Added math and min commands
This commit is contained in:
commit
80a4a5eb28
6 changed files with 181 additions and 6 deletions
|
@ -53,6 +53,8 @@ pub fn create_default_context() -> EngineState {
|
||||||
Math,
|
Math,
|
||||||
MathAbs,
|
MathAbs,
|
||||||
MathAvg,
|
MathAvg,
|
||||||
|
MathMax,
|
||||||
|
MathMin,
|
||||||
Mkdir,
|
Mkdir,
|
||||||
Module,
|
Module,
|
||||||
Mv,
|
Mv,
|
||||||
|
|
|
@ -50,6 +50,7 @@ pub fn average(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
},
|
},
|
||||||
values.to_vec(),
|
values.to_vec(),
|
||||||
|
*head,
|
||||||
)?;
|
)?;
|
||||||
match total {
|
match total {
|
||||||
Value::Filesize { val, span } => Ok(Value::Filesize {
|
Value::Filesize { val, span } => Ok(Value::Filesize {
|
||||||
|
|
57
crates/nu-command/src/math/max.rs
Normal file
57
crates/nu-command/src/math/max.rs
Normal 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 {})
|
||||||
|
}
|
||||||
|
}
|
57
crates/nu-command/src/math/min.rs
Normal file
57
crates/nu-command/src/math/min.rs
Normal 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 {})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,13 @@
|
||||||
mod abs;
|
mod abs;
|
||||||
mod avg;
|
mod avg;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
|
mod max;
|
||||||
|
mod min;
|
||||||
mod reducers;
|
mod reducers;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
pub use abs::SubCommand as MathAbs;
|
pub use abs::SubCommand as MathAbs;
|
||||||
pub use avg::SubCommand as MathAvg;
|
pub use avg::SubCommand as MathAvg;
|
||||||
pub use command::MathCommand as Math;
|
pub use command::MathCommand as Math;
|
||||||
|
pub use max::SubCommand as MathMax;
|
||||||
|
pub use min::SubCommand as MathMin;
|
||||||
|
|
|
@ -1,19 +1,73 @@
|
||||||
use nu_protocol::{ShellError, Span, Value};
|
use nu_protocol::{ShellError, Span, Value};
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum Reduce {
|
pub enum Reduce {
|
||||||
Summation,
|
Summation,
|
||||||
|
Minimum,
|
||||||
|
Maximum,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reducer_for(
|
pub type ReducerFunction =
|
||||||
command: Reduce,
|
Box<dyn Fn(Value, Vec<Value>, Span) -> Result<Value, ShellError> + Send + Sync + 'static>;
|
||||||
) -> Box<dyn Fn(Value, Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static> {
|
|
||||||
|
pub fn reducer_for(command: Reduce) -> ReducerFunction {
|
||||||
match command {
|
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 initial_value = data.get(0);
|
||||||
|
|
||||||
let mut acc = match initial_value {
|
let mut acc = match initial_value {
|
||||||
|
@ -42,7 +96,7 @@ pub fn sum(data: Vec<Value>) -> Result<Value, ShellError> {
|
||||||
| Value::Float { .. }
|
| Value::Float { .. }
|
||||||
| Value::Filesize { .. }
|
| Value::Filesize { .. }
|
||||||
| Value::Duration { .. } => {
|
| 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() {
|
if new_value.is_err() {
|
||||||
return new_value;
|
return new_value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue