Option to replace command same name (#374)

* option to replace command same name

* moved order of custom value declarations

* arranged dataframe folders and objects

* sort help commands by name

* added dtypes function for debugging

* corrected name for dataframe commands

* command names using function
This commit is contained in:
Fernando Herrera 2021-11-28 19:35:02 +00:00 committed by GitHub
parent e1e7e94261
commit c8b16c14d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 490 additions and 220 deletions

15
Cargo.lock generated
View File

@ -1444,7 +1444,6 @@ dependencies = [
"lscolors", "lscolors",
"meval", "meval",
"nu-ansi-term 0.39.0", "nu-ansi-term 0.39.0",
"nu-dataframe",
"nu-engine", "nu-engine",
"nu-json", "nu-json",
"nu-parser", "nu-parser",
@ -1452,6 +1451,7 @@ dependencies = [
"nu-protocol", "nu-protocol",
"nu-table", "nu-table",
"nu-term-grid", "nu-term-grid",
"num",
"polars", "polars",
"rand", "rand",
"rayon", "rayon",
@ -1469,19 +1469,6 @@ dependencies = [
"unicode-segmentation", "unicode-segmentation",
] ]
[[package]]
name = "nu-dataframe"
version = "0.1.0"
dependencies = [
"chrono",
"indexmap",
"nu-json",
"nu-protocol",
"num",
"polars",
"serde",
]
[[package]] [[package]]
name = "nu-engine" name = "nu-engine"
version = "0.1.0" version = "0.1.0"

View File

@ -13,7 +13,6 @@ members = [
"crates/nu-command", "crates/nu-command",
"crates/nu-protocol", "crates/nu-protocol",
"crates/nu-plugin", "crates/nu-plugin",
"crates/nu-dataframe",
"crates/nu_plugin_inc", "crates/nu_plugin_inc",
] ]
@ -38,9 +37,8 @@ ctrlc = "3.2.1"
[features] [features]
plugin = ["nu-plugin", "nu-parser/plugin", "nu-command/plugin", "nu-protocol/plugin"] plugin = ["nu-plugin", "nu-parser/plugin", "nu-command/plugin", "nu-protocol/plugin"]
custom = ["nu-command/custom", "nu-protocol/custom"] dataframe = ["nu-command/dataframe"]
dataframe = ["custom", "nu-command/dataframe"] default = ["plugin"]
default = ["plugin", "custom"]
[dev-dependencies] [dev-dependencies]
tempfile = "3.2.0" tempfile = "3.2.0"

View File

@ -13,7 +13,6 @@ nu-protocol = { path = "../nu-protocol" }
nu-table = { path = "../nu-table" } nu-table = { path = "../nu-table" }
nu-term-grid = { path = "../nu-term-grid" } nu-term-grid = { path = "../nu-term-grid" }
nu-parser = { path = "../nu-parser" } nu-parser = { path = "../nu-parser" }
nu-dataframe = { path = "../nu-dataframe", optional = true }
nu-ansi-term = { path = "../nu-ansi-term" } nu-ansi-term = { path = "../nu-ansi-term" }
trash = { version = "1.3.0", optional = true } trash = { version = "1.3.0", optional = true }
unicode-segmentation = "1.8.0" unicode-segmentation = "1.8.0"
@ -47,13 +46,14 @@ ical = "0.7.0"
calamine = "0.18.0" calamine = "0.18.0"
rand = "0.8" rand = "0.8"
num = {version="0.4.0", optional=true}
[dependencies.polars] [dependencies.polars]
version = "0.17.0" version = "0.17.0"
optional = true optional = true
features = ["default", "parquet", "json"] features = ["default", "parquet", "json", "serde", "object", "checked_arithmetic", "strings"]
[features] [features]
trash-support = ["trash"] trash-support = ["trash"]
plugin = ["nu-parser/plugin"] plugin = ["nu-parser/plugin"]
custom = ["nu-protocol/custom"] dataframe = ["polars", "num"]
dataframe = ["custom", "nu-dataframe", "polars"]

View File

@ -15,7 +15,7 @@ impl Command for Debug {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("describe").category(Category::Core) Signature::build("debug").category(Category::Core)
} }
fn run( fn run(

View File

@ -187,7 +187,6 @@ fn help(
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(engine_state.ctrlc.clone()))
} else { } else {
let mut name = String::new(); let mut name = String::new();
let mut output = String::new();
for r in &rest { for r in &rest {
if !name.is_empty() { if !name.is_empty() {
@ -196,16 +195,15 @@ fn help(
name.push_str(&r.item); name.push_str(&r.item);
} }
for cmd in full_commands { let output = full_commands
if cmd.0.name == name { .iter()
let help = get_full_help(&cmd.0, &cmd.1, engine_state); .filter(|(signature, _, _)| signature.name == name)
output.push_str(&help); .map(|(signature, examples, _)| get_full_help(signature, examples, engine_state))
} .collect::<Vec<String>>();
}
if !output.is_empty() { if !output.is_empty() {
Ok(Value::String { Ok(Value::String {
val: output, val: output.join("======================\n\n"),
span: call.head, span: call.head,
} }
.into_pipeline_data()) .into_pipeline_data())

View File

@ -0,0 +1,183 @@
use super::objects::nu_dataframe::NuDataFrame;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature,
};
use polars::{
chunked_array::ChunkedArray,
prelude::{
AnyValue, DataFrame, DataType, Float64Type, IntoSeries, NewChunkedArray, Series, Utf8Type,
},
};
#[derive(Clone)]
pub struct DescribeDF;
impl Command for DescribeDF {
fn name(&self) -> &str {
"describe"
}
fn usage(&self) -> &str {
"Describes dataframes numeric columns"
}
fn signature(&self) -> Signature {
Signature::build(self.name().to_string()).category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "dataframe description",
example: "[[a b]; [1 1] [1 1]] | to-df | describe",
result: None,
}]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
command(engine_state, stack, call, input)
}
}
fn command(
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head.clone())?;
let names = ChunkedArray::<Utf8Type>::new_from_opt_slice(
"descriptor",
&[
Some("count"),
Some("sum"),
Some("mean"),
Some("median"),
Some("std"),
Some("min"),
Some("25%"),
Some("50%"),
Some("75%"),
Some("max"),
],
)
.into_series();
let head = std::iter::once(names);
let tail = df
.as_ref()
.get_columns()
.iter()
.filter(|col| col.dtype() != &DataType::Object("object"))
.map(|col| {
let count = col.len() as f64;
let sum = match col.sum_as_series().cast(&DataType::Float64) {
Ok(ca) => match ca.get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
},
Err(_) => None,
};
let mean = match col.mean_as_series().get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
};
let median = match col.median_as_series().get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
};
let std = match col.std_as_series().get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
};
let min = match col.min_as_series().cast(&DataType::Float64) {
Ok(ca) => match ca.get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
},
Err(_) => None,
};
let q_25 = match col.quantile_as_series(0.25) {
Ok(ca) => match ca.cast(&DataType::Float64) {
Ok(ca) => match ca.get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
},
Err(_) => None,
},
Err(_) => None,
};
let q_50 = match col.quantile_as_series(0.50) {
Ok(ca) => match ca.cast(&DataType::Float64) {
Ok(ca) => match ca.get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
},
Err(_) => None,
},
Err(_) => None,
};
let q_75 = match col.quantile_as_series(0.75) {
Ok(ca) => match ca.cast(&DataType::Float64) {
Ok(ca) => match ca.get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
},
Err(_) => None,
},
Err(_) => None,
};
let max = match col.max_as_series().cast(&DataType::Float64) {
Ok(ca) => match ca.get(0) {
AnyValue::Float64(v) => Some(v),
_ => None,
},
Err(_) => None,
};
let name = format!("{} ({})", col.name(), col.dtype());
ChunkedArray::<Float64Type>::new_from_opt_slice(
&name,
&[
Some(count),
sum,
mean,
median,
std,
min,
q_25,
q_50,
q_75,
max,
],
)
.into_series()
});
let res = head.chain(tail).collect::<Vec<Series>>();
let df = DataFrame::new(res).map_err(|e| {
ShellError::LabeledError("Dataframe Error".into(), e.to_string(), call.head)
})?;
Ok(PipelineData::Value(NuDataFrame::dataframe_into_value(
df, call.head,
)))
}

View File

@ -0,0 +1,82 @@
use super::objects::nu_dataframe::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Value,
};
#[derive(Clone)]
pub struct DataTypes;
impl Command for DataTypes {
fn name(&self) -> &str {
"dtypes"
}
fn usage(&self) -> &str {
"Show dataframe data types"
}
fn signature(&self) -> Signature {
Signature::build(self.name().to_string()).category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "drop column a",
example: "[[a b]; [1 2] [3 4]] | to-df | dtypes",
result: None,
}]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
command(engine_state, stack, call, input)
}
}
#[allow(clippy::needless_collect)]
fn command(
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head.clone())?;
let mut dtypes: Vec<Value> = Vec::new();
let names: Vec<Value> = df
.as_ref()
.get_column_names()
.iter()
.map(|v| {
let dtype = df
.as_ref()
.column(v)
.expect("using name from list of names from dataframe")
.dtype();
let dtype_str = dtype.to_string();
dtypes.push(Value::String {
val: dtype_str.into(),
span: call.head,
});
Value::String {
val: v.to_string().into(),
span: call.head,
}
})
.collect();
let names_col = Column::new("column".to_string(), names);
let dtypes_col = Column::new("dtype".to_string(), dtypes);
let df = NuDataFrame::try_from_columns(vec![names_col, dtypes_col])?;
Ok(PipelineData::Value(df.to_value(call.head)))
}

View File

@ -1,5 +1,10 @@
mod describe;
mod dtypes;
mod objects;
mod open; mod open;
mod to_df; mod to_df;
pub use describe::DescribeDF;
pub use dtypes::DataTypes;
pub use open::OpenDataFrame; pub use open::OpenDataFrame;
pub use to_df::ToDataFrame; pub use to_df::ToDataFrame;

View File

@ -0,0 +1 @@
pub(super) mod nu_dataframe;

View File

@ -1,6 +1,6 @@
use super::{operations::Axis, NuDataFrame}; use super::{operations::Axis, NuDataFrame};
use nu_protocol::{ast::Operator, ShellError, Span, Spanned, Value}; use nu_protocol::{ast::Operator, span, ShellError, Span, Spanned, Value};
use num::Zero; use num::Zero;
use polars::prelude::{ use polars::prelude::{
BooleanType, ChunkCompare, ChunkedArray, DataType, Float64Type, Int64Type, IntoSeries, BooleanType, ChunkCompare, ChunkedArray, DataType, Float64Type, Int64Type, IntoSeries,
@ -10,12 +10,12 @@ use std::ops::{Add, BitAnd, BitOr, Div, Mul, Sub};
pub fn between_dataframes( pub fn between_dataframes(
operator: Spanned<Operator>, operator: Spanned<Operator>,
left: Value, left: &Value,
lhs: &NuDataFrame, lhs: &NuDataFrame,
right: &Value, right: &Value,
rhs: &NuDataFrame, rhs: &NuDataFrame,
operation_span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
let operation_span = span(&[left.span()?, right.span()?]);
match operator.item { match operator.item {
Operator::Plus => match lhs.append_df(rhs, Axis::Row, operation_span) { Operator::Plus => match lhs.append_df(rhs, Axis::Row, operation_span) {
Ok(df) => Ok(df.to_value(operation_span)), Ok(df) => Ok(df.to_value(operation_span)),
@ -33,12 +33,12 @@ pub fn between_dataframes(
pub fn compute_between_series( pub fn compute_between_series(
operator: Spanned<Operator>, operator: Spanned<Operator>,
left: Value, left: &Value,
lhs: &Series, lhs: &Series,
right: &Value, right: &Value,
rhs: &Series, rhs: &Series,
operation_span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
let operation_span = span(&[left.span()?, right.span()?]);
match operator.item { match operator.item {
Operator::Plus => { Operator::Plus => {
let mut res = lhs + rhs; let mut res = lhs + rhs;
@ -167,9 +167,8 @@ pub fn compute_between_series(
pub fn compute_series_single_value( pub fn compute_series_single_value(
operator: Spanned<Operator>, operator: Spanned<Operator>,
left: &Value,
lhs: &NuDataFrame, lhs: &NuDataFrame,
lhs_span: &Span,
left: Value,
right: &Value, right: &Value,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
if !lhs.is_series() { if !lhs.is_series() {
@ -182,15 +181,16 @@ pub fn compute_series_single_value(
}); });
} }
let lhs = lhs.as_series(*lhs_span)?; let lhs_span = left.span()?;
let lhs = lhs.as_series(lhs_span)?;
match operator.item { match operator.item {
Operator::Plus => match &right { Operator::Plus => match &right {
Value::Int { val, .. } => { Value::Int { val, .. } => {
compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::add, *lhs_span) compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::add, lhs_span)
} }
Value::Float { val, .. } => { Value::Float { val, .. } => {
compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::add, *lhs_span) compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::add, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -202,10 +202,10 @@ pub fn compute_series_single_value(
}, },
Operator::Minus => match &right { Operator::Minus => match &right {
Value::Int { val, .. } => { Value::Int { val, .. } => {
compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::sub, *lhs_span) compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::sub, lhs_span)
} }
Value::Float { val, .. } => { Value::Float { val, .. } => {
compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::sub, *lhs_span) compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::sub, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -217,10 +217,10 @@ pub fn compute_series_single_value(
}, },
Operator::Multiply => match &right { Operator::Multiply => match &right {
Value::Int { val, .. } => { Value::Int { val, .. } => {
compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::mul, *lhs_span) compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::mul, lhs_span)
} }
Value::Float { val, .. } => { Value::Float { val, .. } => {
compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::mul, *lhs_span) compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::mul, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -235,14 +235,14 @@ pub fn compute_series_single_value(
if *val == 0 { if *val == 0 {
Err(ShellError::DivisionByZero(*span)) Err(ShellError::DivisionByZero(*span))
} else { } else {
compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::div, *lhs_span) compute_series_i64(&lhs, *val, <ChunkedArray<Int64Type>>::div, lhs_span)
} }
} }
Value::Float { val, span } => { Value::Float { val, span } => {
if val.is_zero() { if val.is_zero() {
Err(ShellError::DivisionByZero(*span)) Err(ShellError::DivisionByZero(*span))
} else { } else {
compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::div, *lhs_span) compute_series_decimal(&lhs, *val, <ChunkedArray<Float64Type>>::div, lhs_span)
} }
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
@ -254,9 +254,9 @@ pub fn compute_series_single_value(
}), }),
}, },
Operator::Equal => match &right { Operator::Equal => match &right {
Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::eq, *lhs_span), Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::eq, lhs_span),
Value::Float { val, .. } => { Value::Float { val, .. } => {
compare_series_decimal(&lhs, *val, ChunkedArray::eq, *lhs_span) compare_series_decimal(&lhs, *val, ChunkedArray::eq, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -267,9 +267,9 @@ pub fn compute_series_single_value(
}), }),
}, },
Operator::NotEqual => match &right { Operator::NotEqual => match &right {
Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::neq, *lhs_span), Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::neq, lhs_span),
Value::Float { val, .. } => { Value::Float { val, .. } => {
compare_series_decimal(&lhs, *val, ChunkedArray::neq, *lhs_span) compare_series_decimal(&lhs, *val, ChunkedArray::neq, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -280,9 +280,9 @@ pub fn compute_series_single_value(
}), }),
}, },
Operator::LessThan => match &right { Operator::LessThan => match &right {
Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::lt, *lhs_span), Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::lt, lhs_span),
Value::Float { val, .. } => { Value::Float { val, .. } => {
compare_series_decimal(&lhs, *val, ChunkedArray::lt, *lhs_span) compare_series_decimal(&lhs, *val, ChunkedArray::lt, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -293,11 +293,9 @@ pub fn compute_series_single_value(
}), }),
}, },
Operator::LessThanOrEqual => match &right { Operator::LessThanOrEqual => match &right {
Value::Int { val, .. } => { Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::lt_eq, lhs_span),
compare_series_i64(&lhs, *val, ChunkedArray::lt_eq, *lhs_span)
}
Value::Float { val, .. } => { Value::Float { val, .. } => {
compare_series_decimal(&lhs, *val, ChunkedArray::lt_eq, *lhs_span) compare_series_decimal(&lhs, *val, ChunkedArray::lt_eq, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -308,9 +306,9 @@ pub fn compute_series_single_value(
}), }),
}, },
Operator::GreaterThan => match &right { Operator::GreaterThan => match &right {
Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::gt, *lhs_span), Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::gt, lhs_span),
Value::Float { val, .. } => { Value::Float { val, .. } => {
compare_series_decimal(&lhs, *val, ChunkedArray::gt, *lhs_span) compare_series_decimal(&lhs, *val, ChunkedArray::gt, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -321,11 +319,9 @@ pub fn compute_series_single_value(
}), }),
}, },
Operator::GreaterThanOrEqual => match &right { Operator::GreaterThanOrEqual => match &right {
Value::Int { val, .. } => { Value::Int { val, .. } => compare_series_i64(&lhs, *val, ChunkedArray::gt_eq, lhs_span),
compare_series_i64(&lhs, *val, ChunkedArray::gt_eq, *lhs_span)
}
Value::Float { val, .. } => { Value::Float { val, .. } => {
compare_series_decimal(&lhs, *val, ChunkedArray::gt_eq, *lhs_span) compare_series_decimal(&lhs, *val, ChunkedArray::gt_eq, lhs_span)
} }
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
@ -336,7 +332,7 @@ pub fn compute_series_single_value(
}), }),
}, },
Operator::Contains => match &right { Operator::Contains => match &right {
Value::String { val, .. } => contains_series_pat(&lhs, val, *lhs_span), Value::String { val, .. } => contains_series_pat(&lhs, val, lhs_span),
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: operator.span, op_span: operator.span,
lhs_ty: left.get_type(), lhs_ty: left.get_type(),

View File

@ -1,5 +1,4 @@
use super::NuDataFrame; use super::{DataFrameValue, NuDataFrame};
use crate::DataFrameValue;
use chrono::{DateTime, FixedOffset, NaiveDateTime}; use chrono::{DateTime, FixedOffset, NaiveDateTime};
use indexmap::map::{Entry, IndexMap}; use indexmap::map::{Entry, IndexMap};
use nu_protocol::{ShellError, Span, Value}; use nu_protocol::{ShellError, Span, Value};
@ -35,9 +34,9 @@ impl Column {
self.name.as_str() self.name.as_str()
} }
pub fn iter(&self) -> impl Iterator<Item = &Value> { //pub fn iter(&self) -> impl Iterator<Item = &Value> {
self.values.iter() // self.values.iter()
} //}
} }
impl IntoIterator for Column { impl IntoIterator for Column {

View File

@ -1,5 +1,5 @@
use crate::NuDataFrame; use super::NuDataFrame;
use nu_protocol::{ast::Operator, CustomValue, ShellError, Span, Value}; use nu_protocol::{ast::Operator, Category, CustomValue, ShellError, Span, Value};
// CustomValue implementation for NuDataFrame // CustomValue implementation for NuDataFrame
impl CustomValue for NuDataFrame { impl CustomValue for NuDataFrame {
@ -20,6 +20,10 @@ impl CustomValue for NuDataFrame {
} }
} }
fn category(&self) -> Category {
Category::Custom(self.typetag_name().into())
}
fn value_string(&self) -> String { fn value_string(&self) -> String {
self.typetag_name().to_string() self.typetag_name().to_string()
} }

View File

@ -5,9 +5,9 @@ mod operations;
use std::{cmp::Ordering, fmt::Display, hash::Hasher}; use std::{cmp::Ordering, fmt::Display, hash::Hasher};
use conversion::{Column, ColumnMap}; pub use conversion::{Column, ColumnMap};
use indexmap::map::IndexMap; use indexmap::map::IndexMap;
use nu_protocol::{did_you_mean, ShellError, Span, Value}; use nu_protocol::{did_you_mean, PipelineData, ShellError, Span, Value};
use polars::prelude::{DataFrame, PolarsObject, Series}; use polars::prelude::{DataFrame, PolarsObject, Series};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -62,13 +62,25 @@ impl std::hash::Hash for DataFrameValue {
impl PolarsObject for DataFrameValue { impl PolarsObject for DataFrameValue {
fn type_name() -> &'static str { fn type_name() -> &'static str {
"value" "object"
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct NuDataFrame(DataFrame); pub struct NuDataFrame(DataFrame);
impl AsRef<DataFrame> for NuDataFrame {
fn as_ref(&self) -> &polars::prelude::DataFrame {
&self.0
}
}
impl AsMut<DataFrame> for NuDataFrame {
fn as_mut(&mut self) -> &mut polars::prelude::DataFrame {
&mut self.0
}
}
impl NuDataFrame { impl NuDataFrame {
pub fn new(dataframe: DataFrame) -> Self { pub fn new(dataframe: DataFrame) -> Self {
Self(dataframe) Self(dataframe)
@ -131,12 +143,12 @@ impl NuDataFrame {
conversion::from_parsed_columns(column_values) conversion::from_parsed_columns(column_values)
} }
pub fn try_from_series(columns: Vec<Series>) -> Result<Self, ShellError> { //pub fn try_from_series(columns: Vec<Series>) -> Result<Self, ShellError> {
let dataframe = DataFrame::new(columns) // let dataframe = DataFrame::new(columns)
.map_err(|e| ShellError::InternalError(format!("Unable to create DataFrame: {}", e)))?; // .map_err(|e| ShellError::InternalError(format!("Unable to create DataFrame: {}", e)))?;
Ok(Self::new(dataframe)) // Ok(Self::new(dataframe))
} //}
pub fn try_from_columns(columns: Vec<Column>) -> Result<Self, ShellError> { pub fn try_from_columns(columns: Vec<Column>) -> Result<Self, ShellError> {
let mut column_values: ColumnMap = IndexMap::new(); let mut column_values: ColumnMap = IndexMap::new();
@ -151,6 +163,24 @@ impl NuDataFrame {
conversion::from_parsed_columns(column_values) conversion::from_parsed_columns(column_values)
} }
pub fn try_from_pipeline(input: PipelineData, span: Span) -> Result<Self, ShellError> {
match input.into_value(span) {
Value::CustomValue { val, span } => match val.as_any().downcast_ref::<NuDataFrame>() {
Some(df) => Ok(NuDataFrame(df.0.clone())),
None => Err(ShellError::CantConvert(
"Dataframe not found".into(),
"value is not a dataframe".into(),
span,
)),
},
_ => Err(ShellError::CantConvert(
"Dataframe not found".into(),
"value is not a dataframe".into(),
span,
)),
}
}
pub fn column(&self, column: &str, span: Span) -> Result<Self, ShellError> { pub fn column(&self, column: &str, span: Span) -> Result<Self, ShellError> {
let s = self.0.column(column).map_err(|_| { let s = self.0.column(column).map_err(|_| {
let possibilities = self let possibilities = self

View File

@ -1,7 +1,7 @@
use nu_protocol::{ast::Operator, span, ShellError, Span, Spanned, Value}; use nu_protocol::{ast::Operator, ShellError, Span, Spanned, Value};
use polars::prelude::{DataFrame, Series}; use polars::prelude::{DataFrame, Series};
use crate::between_values::{ use super::between_values::{
between_dataframes, compute_between_series, compute_series_single_value, between_dataframes, compute_between_series, compute_series_single_value,
}; };
@ -9,18 +9,18 @@ use super::NuDataFrame;
pub enum Axis { pub enum Axis {
Row, Row,
Column, //Column,
} }
impl Axis { //impl Axis {
pub fn try_from_str(axis: &str, span: Span) -> Result<Axis, ShellError> { // pub fn try_from_str(axis: &str, span: Span) -> Result<Axis, ShellError> {
match axis { // match axis {
"row" => Ok(Axis::Row), // "row" => Ok(Axis::Row),
"col" => Ok(Axis::Column), // "col" => Ok(Axis::Column),
_ => Err(ShellError::DidYouMean("'row' or 'col'".into(), span)), // _ => Err(ShellError::DidYouMean("'row' or 'col'".into(), span)),
} // }
} // }
} //}
impl NuDataFrame { impl NuDataFrame {
pub fn compute_with_value( pub fn compute_with_value(
@ -42,7 +42,6 @@ impl NuDataFrame {
) )
})?; })?;
let operation_span = span(&[lhs_span, *rhs_span]);
match (self.is_series(), rhs.is_series()) { match (self.is_series(), rhs.is_series()) {
(true, true) => { (true, true) => {
let lhs = &self let lhs = &self
@ -77,11 +76,10 @@ impl NuDataFrame {
compute_between_series( compute_between_series(
op, op,
NuDataFrame::default_value(lhs_span), &NuDataFrame::default_value(lhs_span),
lhs, lhs,
right, right,
rhs, rhs,
operation_span,
) )
} }
_ => { _ => {
@ -101,11 +99,10 @@ impl NuDataFrame {
between_dataframes( between_dataframes(
op, op,
NuDataFrame::default_value(lhs_span), &NuDataFrame::default_value(lhs_span),
self, self,
right, right,
rhs, rhs,
operation_span,
) )
} }
} }
@ -116,13 +113,7 @@ impl NuDataFrame {
span: op_span, span: op_span,
}; };
compute_series_single_value( compute_series_single_value(op, &NuDataFrame::default_value(lhs_span), self, right)
op,
self,
&lhs_span,
NuDataFrame::default_value(lhs_span),
right,
)
} }
} }
} }
@ -131,7 +122,7 @@ impl NuDataFrame {
&self, &self,
other: &NuDataFrame, other: &NuDataFrame,
axis: Axis, axis: Axis,
span: Span, _span: Span,
) -> Result<Self, ShellError> { ) -> Result<Self, ShellError> {
match axis { match axis {
Axis::Row => { Axis::Row => {
@ -160,61 +151,60 @@ impl NuDataFrame {
.map_err(|e| ShellError::InternalError(e.to_string()))?; .map_err(|e| ShellError::InternalError(e.to_string()))?;
Ok(NuDataFrame::new(df_new)) Ok(NuDataFrame::new(df_new))
} } //Axis::Column => {
Axis::Column => { // if self.0.width() != other.0.width() {
if self.0.width() != other.0.width() { // return Err(ShellError::IncompatibleParametersSingle(
return Err(ShellError::IncompatibleParametersSingle( // "Dataframes with different number of columns".into(),
"Dataframes with different number of columns".into(), // span,
span, // ));
)); // }
}
if !self // if !self
.0 // .0
.get_column_names() // .get_column_names()
.iter() // .iter()
.all(|col| other.0.get_column_names().contains(col)) // .all(|col| other.0.get_column_names().contains(col))
{ // {
return Err(ShellError::IncompatibleParametersSingle( // return Err(ShellError::IncompatibleParametersSingle(
"Dataframes with different columns names".into(), // "Dataframes with different columns names".into(),
span, // span,
)); // ));
} // }
let new_cols = self // let new_cols = self
.0 // .0
.get_columns() // .get_columns()
.iter() // .iter()
.map(|s| { // .map(|s| {
let other_col = other // let other_col = other
.0 // .0
.column(s.name()) // .column(s.name())
.expect("Already checked that dataframes have same columns"); // .expect("Already checked that dataframes have same columns");
let mut tmp = s.clone(); // let mut tmp = s.clone();
let res = tmp.append(other_col); // let res = tmp.append(other_col);
match res { // match res {
Ok(s) => Ok(s.clone()), // Ok(s) => Ok(s.clone()),
Err(e) => Err({ // Err(e) => Err({
ShellError::InternalError(format!( // ShellError::InternalError(format!(
"Unable to append dataframes: {}", // "Unable to append dataframes: {}",
e // e
)) // ))
}), // }),
} // }
}) // })
.collect::<Result<Vec<Series>, ShellError>>()?; // .collect::<Result<Vec<Series>, ShellError>>()?;
let df_new = DataFrame::new(new_cols).map_err(|e| { // let df_new = DataFrame::new(new_cols).map_err(|e| {
ShellError::InternalError(format!( // ShellError::InternalError(format!(
"Unable to append dataframes: {}", // "Unable to append dataframes: {}",
e.to_string() // e.to_string()
)) // ))
})?; // })?;
Ok(NuDataFrame::new(df_new)) // Ok(NuDataFrame::new(df_new))
} //}
} }
} }
} }

View File

@ -1,6 +1,6 @@
use std::{fs::File, path::PathBuf}; use std::{fs::File, path::PathBuf};
use nu_dataframe::NuDataFrame; use super::objects::nu_dataframe::NuDataFrame;
use nu_engine::CallExt; use nu_engine::CallExt;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
@ -23,7 +23,7 @@ impl Command for OpenDataFrame {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("open-df") Signature::build(self.name().to_string())
.required( .required(
"file", "file",
SyntaxShape::Filepath, SyntaxShape::Filepath,
@ -64,7 +64,7 @@ impl Command for OpenDataFrame {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Takes a file name and creates a dataframe", description: "Takes a file name and creates a dataframe",
example: "dataframe open test.csv", example: "open-df test.csv",
result: None, result: None,
}] }]
} }

View File

@ -1,4 +1,4 @@
use nu_dataframe::NuDataFrame; use super::objects::nu_dataframe::NuDataFrame;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
@ -10,7 +10,7 @@ pub struct ToDataFrame;
impl Command for ToDataFrame { impl Command for ToDataFrame {
fn name(&self) -> &str { fn name(&self) -> &str {
"to-df" "to df"
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -18,29 +18,29 @@ impl Command for ToDataFrame {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-df").category(Category::Custom("dataframe".into())) Signature::build(self.name().to_string()).category(Category::Custom("dataframe".into()))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![ vec![
Example { Example {
description: "Takes a dictionary and creates a dataframe", description: "Takes a dictionary and creates a dataframe",
example: "[[a b];[1 2] [3 4]] | to-df", example: "[[a b];[1 2] [3 4]] | to df",
result: None, result: None,
}, },
Example { Example {
description: "Takes a list of tables and creates a dataframe", description: "Takes a list of tables and creates a dataframe",
example: "[[1 2 a] [3 4 b] [5 6 c]] | to-df", example: "[[1 2 a] [3 4 b] [5 6 c]] | to df",
result: None, result: None,
}, },
Example { Example {
description: "Takes a list and creates a dataframe", description: "Takes a list and creates a dataframe",
example: "[a b c] | to-df", example: "[a b c] | to df",
result: None, result: None,
}, },
Example { Example {
description: "Takes a list of booleans and creates a dataframe", description: "Takes a list of booleans and creates a dataframe",
example: "[$true $true $false] | to-df", example: "[$true $true $false] | to df",
result: None, result: None,
}, },
] ]

View File

@ -17,6 +17,13 @@ pub fn create_default_context() -> EngineState {
}; };
} }
// If there are commands that have the same name as default declarations,
// they have to be registered before the main declarations. This helps to make
// them only accessible if the correct input value category is used with the
// declaration
#[cfg(feature = "dataframe")]
bind_command!(DataTypes, DescribeDF, OpenDataFrame, ToDataFrame);
// TODO: sort default context items categorically // TODO: sort default context items categorically
bind_command!( bind_command!(
Alias, Alias,
@ -148,9 +155,6 @@ pub fn create_default_context() -> EngineState {
#[cfg(feature = "plugin")] #[cfg(feature = "plugin")]
bind_command!(Register); bind_command!(Register);
#[cfg(feature = "dataframe")]
bind_command!(OpenDataFrame, ToDataFrame);
// This is a WIP proof of concept // This is a WIP proof of concept
// bind_command!(ListGitBranches, Git, GitCheckout, Source); // bind_command!(ListGitBranches, Git, GitCheckout, Source);

View File

@ -73,7 +73,6 @@ pub fn value_to_json_value(v: &Value) -> Result<nu_json::Value, ShellError> {
} }
nu_json::Value::Object(m) nu_json::Value::Object(m)
} }
#[cfg(feature = "custom")]
Value::CustomValue { val, .. } => val.to_json(), Value::CustomValue { val, .. } => val.to_json(),
}) })
} }

View File

@ -107,7 +107,6 @@ impl Command for Table {
.into_pipeline_data()) .into_pipeline_data())
} }
PipelineData::Value(Value::Error { error }) => Err(error), PipelineData::Value(Value::Error { error }) => Err(error),
#[cfg(feature = "custom")]
PipelineData::Value(Value::CustomValue { val, span }) => { PipelineData::Value(Value::CustomValue { val, span }) => {
let base_pipeline = val.to_base_value(span)?.into_pipeline_data(); let base_pipeline = val.to_base_value(span)?.into_pipeline_data();
self.run(engine_state, stack, call, base_pipeline) self.run(engine_state, stack, call, base_pipeline)

View File

@ -1,14 +0,0 @@
[package]
name = "nu-dataframe"
version = "0.1.0"
edition = "2018"
[dependencies]
chrono = { version="0.4.19", features=["serde"] }
serde = {version = "1.0.130", features = ["derive"]}
num = "0.4.0"
nu-protocol = { path = "../nu-protocol", features = ["custom"] }
nu-json = { path = "../nu-json"}
indexmap = { version="1.7.0", features=["serde-1"] }
polars = { version = "0.17.0", features = ["default", "serde", "object", "checked_arithmetic", "strings"] }

View File

@ -24,7 +24,8 @@ fn eval_call(
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let decl = engine_state.get_decl(call.decl_id); let decl = engine_state.get_decl_with_input(call.decl_id, &input);
if call.named.iter().any(|(flag, _)| flag.item == "help") { if call.named.iter().any(|(flag, _)| flag.item == "help") {
let full_help = get_full_help(&decl.signature(), &decl.examples(), engine_state); let full_help = get_full_help(&decl.signature(), &decl.examples(), engine_state);
Ok(Value::String { Ok(Value::String {

View File

@ -20,7 +20,6 @@ typetag = "0.1.8"
[features] [features]
plugin = ["serde_json"] plugin = ["serde_json"]
custom = []
[dev-dependencies] [dev-dependencies]
serde_json = "1.0" serde_json = "1.0"

View File

@ -1,7 +1,7 @@
use super::Command; use super::Command;
use crate::{ use crate::{
ast::Block, BlockId, DeclId, Example, Overlay, OverlayId, ShellError, Signature, Span, Type, ast::Block, BlockId, DeclId, Example, Overlay, OverlayId, PipelineData, ShellError, Signature,
VarId, Span, Type, Value, VarId,
}; };
use core::panic; use core::panic;
use std::{ use std::{
@ -357,6 +357,39 @@ impl EngineState {
.expect("internal error: missing declaration") .expect("internal error: missing declaration")
} }
#[allow(clippy::borrowed_box)]
pub fn get_decl_with_input(&self, decl_id: DeclId, input: &PipelineData) -> &Box<dyn Command> {
let decl = self.get_decl(decl_id);
match input {
PipelineData::Stream(_) => decl,
PipelineData::Value(value) => match value {
Value::CustomValue { val, .. } => {
// This filter works because the custom definitions were declared
// before the default nushell declarations. This means that the custom
// declarations that get overridden by the default declarations can only
// be accessed if the input value has the required category
let decls = self
.decls
.iter()
.enumerate()
.filter(|(_, decl_inner)| {
decl.name() == decl_inner.name()
&& decl_inner.signature().category == val.category()
})
.map(|(index, _)| index)
.collect::<Vec<usize>>();
match decls.first() {
Some(index) => self.get_decl(*index),
None => decl,
}
}
_ => decl,
},
}
}
pub fn get_signatures(&self) -> Vec<Signature> { pub fn get_signatures(&self) -> Vec<Signature> {
let mut output = vec![]; let mut output = vec![];
for decl in self.decls.iter() { for decl in self.decls.iter() {
@ -384,6 +417,7 @@ impl EngineState {
} }
} }
output.sort_by(|a, b| a.0.name.cmp(&b.0.name));
output output
} }

View File

@ -26,7 +26,5 @@ pub use signature::*;
pub use span::*; pub use span::*;
pub use syntax_shape::*; pub use syntax_shape::*;
pub use ty::*; pub use ty::*;
pub use value::*;
#[cfg(feature = "custom")]
pub use value::CustomValue; pub use value::CustomValue;
pub use value::*;

View File

@ -31,6 +31,7 @@ use crate::{ast::PathMember, Config, ShellError, Span, Value, ValueStream};
/// * A balance of the two approaches is what we've landed on: Values are thread-safe to pass, and we can stream /// * A balance of the two approaches is what we've landed on: Values are thread-safe to pass, and we can stream
/// them into any sources. Streams are still available to model the infinite streams approach of original /// them into any sources. Streams are still available to model the infinite streams approach of original
/// Nushell. /// Nushell.
#[derive(Debug)]
pub enum PipelineData { pub enum PipelineData {
Value(Value), Value(Value),
Stream(ValueStream), Stream(ValueStream),

View File

@ -210,6 +210,10 @@ pub enum ShellError {
#[error("Casting error")] #[error("Casting error")]
#[diagnostic(code(nu::parser::downcast_not_possible), url(docsrs))] #[diagnostic(code(nu::parser::downcast_not_possible), url(docsrs))]
DowncastNotPossible(String, #[label("{0}")] Span), DowncastNotPossible(String, #[label("{0}")] Span),
#[error("{0}")]
#[diagnostic()]
LabeledError(String, String, #[label("{1}")] Span),
} }
impl From<std::io::Error> for ShellError { impl From<std::io::Error> for ShellError {

View File

@ -1,12 +1,14 @@
use std::fmt; use std::fmt;
use crate::{ast::Operator, ShellError, Span, Value}; use crate::{ast::Operator, Category, ShellError, Span, Value};
// Trait definition for a custom value // Trait definition for a custom value
#[typetag::serde(tag = "type")] #[typetag::serde(tag = "type")]
pub trait CustomValue: fmt::Debug + Send + Sync { pub trait CustomValue: fmt::Debug + Send + Sync {
fn clone_value(&self, span: Span) -> Value; fn clone_value(&self, span: Span) -> Value;
fn category(&self) -> Category;
// Define string representation of the custom value // Define string representation of the custom value
fn value_string(&self) -> String; fn value_string(&self) -> String;

View File

@ -18,10 +18,7 @@ use std::{cmp::Ordering, fmt::Debug};
use crate::ast::{CellPath, PathMember}; use crate::ast::{CellPath, PathMember};
use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type}; use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type};
#[cfg(feature = "custom")]
use crate::ast::Operator; use crate::ast::Operator;
#[cfg(feature = "custom")]
pub use custom_value::CustomValue; pub use custom_value::CustomValue;
use crate::ShellError; use crate::ShellError;
@ -88,7 +85,6 @@ pub enum Value {
val: CellPath, val: CellPath,
span: Span, span: Span,
}, },
#[cfg(feature = "custom")]
CustomValue { CustomValue {
val: Box<dyn CustomValue>, val: Box<dyn CustomValue>,
span: Span, span: Span,
@ -155,7 +151,6 @@ impl Clone for Value {
val: val.clone(), val: val.clone(),
span: *span, span: *span,
}, },
#[cfg(feature = "custom")]
Value::CustomValue { val, span } => val.clone_value(*span), Value::CustomValue { val, span } => val.clone_value(*span),
} }
} }
@ -224,7 +219,6 @@ impl Value {
Value::Nothing { span, .. } => Ok(*span), Value::Nothing { span, .. } => Ok(*span),
Value::Binary { span, .. } => Ok(*span), Value::Binary { span, .. } => Ok(*span),
Value::CellPath { span, .. } => Ok(*span), Value::CellPath { span, .. } => Ok(*span),
#[cfg(feature = "custom")]
Value::CustomValue { span, .. } => Ok(*span), Value::CustomValue { span, .. } => Ok(*span),
} }
} }
@ -247,7 +241,6 @@ impl Value {
Value::Error { .. } => {} Value::Error { .. } => {}
Value::Binary { span, .. } => *span = new_span, Value::Binary { span, .. } => *span = new_span,
Value::CellPath { span, .. } => *span = new_span, Value::CellPath { span, .. } => *span = new_span,
#[cfg(feature = "custom")]
Value::CustomValue { span, .. } => *span = new_span, Value::CustomValue { span, .. } => *span = new_span,
} }
@ -277,7 +270,6 @@ impl Value {
Value::Error { .. } => Type::Error, Value::Error { .. } => Type::Error,
Value::Binary { .. } => Type::Binary, Value::Binary { .. } => Type::Binary,
Value::CellPath { .. } => Type::CellPath, Value::CellPath { .. } => Type::CellPath,
#[cfg(feature = "custom")]
Value::CustomValue { .. } => Type::Custom, Value::CustomValue { .. } => Type::Custom,
} }
} }
@ -319,7 +311,6 @@ impl Value {
Value::Error { error } => format!("{:?}", error), Value::Error { error } => format!("{:?}", error),
Value::Binary { val, .. } => format!("{:?}", val), Value::Binary { val, .. } => format!("{:?}", val),
Value::CellPath { val, .. } => val.into_string(), Value::CellPath { val, .. } => val.into_string(),
#[cfg(feature = "custom")]
Value::CustomValue { val, .. } => val.value_string(), Value::CustomValue { val, .. } => val.value_string(),
} }
} }
@ -361,7 +352,6 @@ impl Value {
Value::Error { error } => format!("{:?}", error), Value::Error { error } => format!("{:?}", error),
Value::Binary { val, .. } => format!("{:?}", val), Value::Binary { val, .. } => format!("{:?}", val),
Value::CellPath { val, .. } => val.into_string(), Value::CellPath { val, .. } => val.into_string(),
#[cfg(feature = "custom")]
Value::CustomValue { val, .. } => val.value_string(), Value::CustomValue { val, .. } => val.value_string(),
} }
} }
@ -408,7 +398,6 @@ impl Value {
return Err(ShellError::AccessBeyondEndOfStream(*origin_span)); return Err(ShellError::AccessBeyondEndOfStream(*origin_span));
} }
} }
#[cfg(feature = "custom")]
Value::CustomValue { val, .. } => { Value::CustomValue { val, .. } => {
current = val.follow_path_int(*count, *origin_span)?; current = val.follow_path_int(*count, *origin_span)?;
} }
@ -459,7 +448,6 @@ impl Value {
span: *span, span: *span,
}; };
} }
#[cfg(feature = "custom")]
Value::CustomValue { val, .. } => { Value::CustomValue { val, .. } => {
current = val.follow_path_string(column_name.clone(), *origin_span)?; current = val.follow_path_string(column_name.clone(), *origin_span)?;
} }
@ -725,7 +713,6 @@ impl Value {
} }
} }
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Plus, op, rhs) lhs.operation(*span, Operator::Plus, op, rhs)
} }
@ -795,7 +782,6 @@ impl Value {
} }
} }
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Minus, op, rhs) lhs.operation(*span, Operator::Minus, op, rhs)
} }
@ -835,7 +821,6 @@ impl Value {
val: lhs * rhs, val: lhs * rhs,
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Multiply, op, rhs) lhs.operation(*span, Operator::Multiply, op, rhs)
} }
@ -900,7 +885,6 @@ impl Value {
Err(ShellError::DivisionByZero(op)) Err(ShellError::DivisionByZero(op))
} }
} }
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Divide, op, rhs) lhs.operation(*span, Operator::Divide, op, rhs)
} }
@ -917,7 +901,6 @@ impl Value {
pub fn lt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn lt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span()?, rhs.span()?]); let span = span(&[self.span()?, rhs.span()?]);
#[cfg(feature = "custom")]
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
return lhs.operation(*span, Operator::LessThan, op, rhs); return lhs.operation(*span, Operator::LessThan, op, rhs);
} }
@ -939,7 +922,6 @@ impl Value {
pub fn lte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn lte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span()?, rhs.span()?]); let span = span(&[self.span()?, rhs.span()?]);
#[cfg(feature = "custom")]
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
return lhs.operation(*span, Operator::LessThanOrEqual, op, rhs); return lhs.operation(*span, Operator::LessThanOrEqual, op, rhs);
} }
@ -961,7 +943,6 @@ impl Value {
pub fn gt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn gt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span()?, rhs.span()?]); let span = span(&[self.span()?, rhs.span()?]);
#[cfg(feature = "custom")]
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
return lhs.operation(*span, Operator::GreaterThan, op, rhs); return lhs.operation(*span, Operator::GreaterThan, op, rhs);
} }
@ -983,7 +964,6 @@ impl Value {
pub fn gte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn gte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span()?, rhs.span()?]); let span = span(&[self.span()?, rhs.span()?]);
#[cfg(feature = "custom")]
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
return lhs.operation(*span, Operator::GreaterThanOrEqual, op, rhs); return lhs.operation(*span, Operator::GreaterThanOrEqual, op, rhs);
} }
@ -1005,7 +985,6 @@ impl Value {
pub fn eq(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn eq(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span()?, rhs.span()?]); let span = span(&[self.span()?, rhs.span()?]);
#[cfg(feature = "custom")]
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
return lhs.operation(*span, Operator::Equal, op, rhs); return lhs.operation(*span, Operator::Equal, op, rhs);
} }
@ -1027,7 +1006,6 @@ impl Value {
pub fn ne(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn ne(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span()?, rhs.span()?]); let span = span(&[self.span()?, rhs.span()?]);
#[cfg(feature = "custom")]
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
return lhs.operation(*span, Operator::NotEqual, op, rhs); return lhs.operation(*span, Operator::NotEqual, op, rhs);
} }
@ -1067,7 +1045,6 @@ impl Value {
val: rhs.contains(lhs), val: rhs.contains(lhs),
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::In, op, rhs) lhs.operation(*span, Operator::In, op, rhs)
} }
@ -1101,7 +1078,6 @@ impl Value {
val: !rhs.contains(lhs), val: !rhs.contains(lhs),
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::NotIn, op, rhs) lhs.operation(*span, Operator::NotIn, op, rhs)
} }
@ -1123,7 +1099,6 @@ impl Value {
val: lhs.contains(rhs), val: lhs.contains(rhs),
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Contains, op, rhs) lhs.operation(*span, Operator::Contains, op, rhs)
} }
@ -1145,7 +1120,6 @@ impl Value {
val: !lhs.contains(rhs), val: !lhs.contains(rhs),
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::NotContains, op, rhs) lhs.operation(*span, Operator::NotContains, op, rhs)
} }
@ -1203,7 +1177,6 @@ impl Value {
Err(ShellError::DivisionByZero(op)) Err(ShellError::DivisionByZero(op))
} }
} }
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Modulo, op, rhs) lhs.operation(*span, Operator::Modulo, op, rhs)
} }
@ -1226,7 +1199,6 @@ impl Value {
val: *lhs && *rhs, val: *lhs && *rhs,
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::And, op, rhs) lhs.operation(*span, Operator::And, op, rhs)
} }
@ -1248,7 +1220,6 @@ impl Value {
val: *lhs || *rhs, val: *lhs || *rhs,
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Or, op, rhs) lhs.operation(*span, Operator::Or, op, rhs)
} }
@ -1288,7 +1259,6 @@ impl Value {
val: lhs.powf(*rhs), val: lhs.powf(*rhs),
span, span,
}), }),
#[cfg(feature = "custom")]
(Value::CustomValue { val: lhs, span }, rhs) => { (Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Pow, op, rhs) lhs.operation(*span, Operator::Pow, op, rhs)
} }