* Test commands for proper names and search terms Assert that the `Command.name()` is equal to `Signature.name` Check that search terms are not just substrings of the command name as they would not help finding the command. * Clean up search terms Remove redundant terms that just replicate the command name. Try to eliminate substring between search terms, clean up where necessary.
90 lines
2.2 KiB
Rust
90 lines
2.2 KiB
Rust
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::{Category, Example, PipelineData, ShellError, Signature, Span, Value};
|
|
|
|
#[derive(Clone)]
|
|
pub struct SubCommand;
|
|
|
|
impl Command for SubCommand {
|
|
fn name(&self) -> &str {
|
|
"math avg"
|
|
}
|
|
|
|
fn signature(&self) -> Signature {
|
|
Signature::build("math avg").category(Category::Math)
|
|
}
|
|
|
|
fn usage(&self) -> &str {
|
|
"Finds the average of a list of numbers or tables"
|
|
}
|
|
|
|
fn search_terms(&self) -> Vec<&str> {
|
|
vec!["average", "mean", "statistics"]
|
|
}
|
|
|
|
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, average)
|
|
}
|
|
|
|
fn examples(&self) -> Vec<Example> {
|
|
vec![Example {
|
|
description: "Get the average of a list of numbers",
|
|
example: "[-50 100.0 25] | math avg",
|
|
result: Some(Value::Float {
|
|
val: 25.0,
|
|
span: Span::test_data(),
|
|
}),
|
|
}]
|
|
}
|
|
}
|
|
|
|
pub fn average(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
|
let sum = reducer_for(Reduce::Summation);
|
|
let total = &sum(
|
|
Value::Int {
|
|
val: 0,
|
|
span: *head,
|
|
},
|
|
values.to_vec(),
|
|
*head,
|
|
)?;
|
|
match total {
|
|
Value::Filesize { val, span } => Ok(Value::Filesize {
|
|
val: val / values.len() as i64,
|
|
span: *span,
|
|
}),
|
|
Value::Duration { val, span } => Ok(Value::Duration {
|
|
val: val / values.len() as i64,
|
|
span: *span,
|
|
}),
|
|
_ => total.div(
|
|
*head,
|
|
&Value::Int {
|
|
val: values.len() as i64,
|
|
span: *head,
|
|
},
|
|
*head,
|
|
),
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_examples() {
|
|
use crate::test_examples;
|
|
|
|
test_examples(SubCommand {})
|
|
}
|
|
}
|