diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index b93274bdf..c751a5b56 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -105,8 +105,8 @@ features = [ "default", "to_dummies", "parquet", "json", "serde", "serde-lazy", "object", "checked_arithmetic", "strings", "cum_agg", "is_in", "rolling_window", "strings", "rows", "random", - "dtype-datetime", "dtype-struct", "lazy", "cross_join", - "dynamic_groupby", "dtype-categorical" + "dtype-datetime", "dtype-struct", "lazy", "cross_join", + "dynamic_groupby", "dtype-categorical", "concat_str" ] [target.'cfg(windows)'.dependencies.windows] diff --git a/crates/nu-command/src/dataframe/expressions/concat_str.rs b/crates/nu-command/src/dataframe/expressions/concat_str.rs new file mode 100644 index 000000000..3f847a0cc --- /dev/null +++ b/crates/nu-command/src/dataframe/expressions/concat_str.rs @@ -0,0 +1,106 @@ +use crate::dataframe::values::{Column, NuDataFrame, NuExpression}; +use nu_engine::CallExt; +use nu_protocol::{ + ast::Call, + engine::{Command, EngineState, Stack}, + Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, +}; +use polars::prelude::concat_str; + +#[derive(Clone)] +pub struct ExprConcatStr; + +impl Command for ExprConcatStr { + fn name(&self) -> &str { + "concat-str" + } + + fn usage(&self) -> &str { + "Creates a concat string expression" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .required( + "separator", + SyntaxShape::String, + "Separator used during the concatenation", + ) + .required( + "concat expressions", + SyntaxShape::List(Box::new(SyntaxShape::Any)), + "Expression(s) that define the string concatenation", + ) + .input_type(Type::Any) + .output_type(Type::Custom("expression".into())) + .category(Category::Custom("expression".into())) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Creates a concat string expression", + example: r#"let df = ([[a b c]; [one two 1] [three four 2]] | into df); + $df | with-column ((concat-str "-" [(col a) (col b) ((col c) * 2)]) | as concat)"#, + result: Some( + NuDataFrame::try_from_columns(vec![ + Column::new( + "a".to_string(), + vec![Value::test_string("one"), Value::test_string("three")], + ), + Column::new( + "b".to_string(), + vec![Value::test_string("two"), Value::test_string("four")], + ), + Column::new( + "c".to_string(), + vec![Value::test_int(1), Value::test_int(2)], + ), + Column::new( + "concat".to_string(), + vec![ + Value::test_string("one-two-2"), + Value::test_string("three-four-4"), + ], + ), + ]) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let separator: String = call.req(engine_state, stack, 0)?; + let value: Value = call.req(engine_state, stack, 1)?; + + let expressions = NuExpression::extract_exprs(value)?; + let expr: NuExpression = concat_str(expressions, &separator).into(); + + Ok(PipelineData::Value(expr.into_value(call.head), None)) + } +} + +#[cfg(test)] +mod test { + use super::super::super::test_dataframe::test_dataframe; + use super::*; + use crate::dataframe::eager::WithColumn; + use crate::dataframe::expressions::alias::ExprAlias; + use crate::dataframe::expressions::col::ExprCol; + + #[test] + fn test_examples() { + test_dataframe(vec![ + Box::new(ExprConcatStr {}), + Box::new(ExprAlias {}), + Box::new(ExprCol {}), + Box::new(WithColumn {}), + ]) + } +} diff --git a/crates/nu-command/src/dataframe/expressions/mod.rs b/crates/nu-command/src/dataframe/expressions/mod.rs index 74b8714d3..2133dcf0e 100644 --- a/crates/nu-command/src/dataframe/expressions/mod.rs +++ b/crates/nu-command/src/dataframe/expressions/mod.rs @@ -1,6 +1,7 @@ mod alias; mod as_nu; mod col; +mod concat_str; mod expressions_macro; mod lit; mod otherwise; @@ -12,6 +13,7 @@ use nu_protocol::engine::StateWorkingSet; pub(crate) use crate::dataframe::expressions::alias::ExprAlias; use crate::dataframe::expressions::as_nu::ExprAsNu; pub(super) use crate::dataframe::expressions::col::ExprCol; +pub(super) use crate::dataframe::expressions::concat_str::ExprConcatStr; pub(crate) use crate::dataframe::expressions::expressions_macro::*; pub(super) use crate::dataframe::expressions::lit::ExprLit; pub(super) use crate::dataframe::expressions::otherwise::ExprOtherwise; @@ -32,6 +34,7 @@ pub fn add_expressions(working_set: &mut StateWorkingSet) { bind_command!( ExprAlias, ExprCol, + ExprConcatStr, ExprCount, ExprLit, ExprAsNu,