diff --git a/crates/nu-cli/tests/completions.rs b/crates/nu-cli/tests/completions.rs index 59ebb74e5..4d646cbc9 100644 --- a/crates/nu-cli/tests/completions.rs +++ b/crates/nu-cli/tests/completions.rs @@ -822,7 +822,7 @@ fn alias_offset_bug_7748() { // Create an alias let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir.clone()).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); @@ -841,7 +841,7 @@ fn alias_offset_bug_7754() { // Create an alias let alias = r#"alias ll = ls -l"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir.clone()).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); diff --git a/crates/nu-color-config/src/style_computer.rs b/crates/nu-color-config/src/style_computer.rs index 5d0fdb6f4..c78b72631 100644 --- a/crates/nu-color-config/src/style_computer.rs +++ b/crates/nu-color-config/src/style_computer.rs @@ -226,10 +226,10 @@ fn test_computable_style_static() { let style2 = Style::default().underline(); // Create a "dummy" style_computer for this test. let dummy_engine_state = EngineState::new(); - let mut dummy_stack = Stack::new(); + let dummy_stack = Stack::new(); let style_computer = StyleComputer::new( &dummy_engine_state, - &mut dummy_stack, + &dummy_stack, HashMap::from([ ("string".into(), ComputableStyle::Static(style1)), ("row_index".into(), ComputableStyle::Static(style2)), diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 8ec92b6e9..fc2794d03 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -95,6 +95,7 @@ pub fn create_default_context() -> EngineState { Each, EachWhile, Empty, + Enumerate, Every, Filter, Find, diff --git a/crates/nu-command/src/filters/enumerate.rs b/crates/nu-command/src/filters/enumerate.rs new file mode 100644 index 000000000..d029ae301 --- /dev/null +++ b/crates/nu-command/src/filters/enumerate.rs @@ -0,0 +1,95 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Category, Example, IntoInterruptiblePipelineData, PipelineData, Signature, Span, Type, Value, +}; + +#[derive(Clone)] +pub struct Enumerate; + +impl Command for Enumerate { + fn name(&self) -> &str { + "enumerate" + } + + fn usage(&self) -> &str { + "Enumerate the elements in a stream." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["itemize"] + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("enumerate") + .input_output_types(vec![(Type::Any, Type::Any)]) + .category(Category::Filters) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Add an index to each element of a list", + example: r#"[a, b, c] | enumerate "#, + result: Some(Value::List { + vals: vec![ + Value::Record { + cols: vec!["index".into(), "item".into()], + vals: vec![Value::test_int(0), Value::test_string("a")], + span: Span::test_data(), + }, + Value::Record { + cols: vec!["index".into(), "item".into()], + vals: vec![Value::test_int(1), Value::test_string("b")], + span: Span::test_data(), + }, + Value::Record { + cols: vec!["index".into(), "item".into()], + vals: vec![Value::test_int(2), Value::test_string("c")], + span: Span::test_data(), + }, + ], + span: Span::test_data(), + }), + }] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let metadata = input.metadata(); + let ctrlc = engine_state.ctrlc.clone(); + let span = call.head; + + Ok(input + .into_iter() + .enumerate() + .map(move |(idx, x)| Value::Record { + cols: vec!["index".into(), "item".into()], + vals: vec![ + Value::Int { + val: idx as i64, + span, + }, + x, + ], + span, + }) + .into_pipeline_data_with_metadata(metadata, ctrlc)) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Enumerate {}) + } +} diff --git a/crates/nu-command/src/filters/mod.rs b/crates/nu-command/src/filters/mod.rs index 9a0f268e8..5f6296eb5 100644 --- a/crates/nu-command/src/filters/mod.rs +++ b/crates/nu-command/src/filters/mod.rs @@ -9,6 +9,7 @@ mod drop; mod each; mod each_while; mod empty; +mod enumerate; mod every; mod filter; mod find; @@ -64,6 +65,7 @@ pub use drop::*; pub use each::Each; pub use each_while::EachWhile; pub use empty::Empty; +pub use enumerate::Enumerate; pub use every::Every; pub use filter::Filter; pub use find::Find; diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index ca093d541..fd35599ea 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -455,16 +455,13 @@ mod string { assert_eq!(expressions.len(), 1); if let PipelineElement::Expression(_, expr) = &expressions[0] { - let subexprs: Vec<&Expr>; - match expr { + let subexprs: Vec<&Expr> = match expr { Expression { expr: Expr::StringInterpolation(expressions), .. - } => { - subexprs = expressions.iter().map(|e| &e.expr).collect(); - } + } => expressions.iter().map(|e| &e.expr).collect(), _ => panic!("Expected an `Expr::StringInterpolation`"), - } + }; assert_eq!(subexprs.len(), 2); @@ -491,16 +488,13 @@ mod string { assert_eq!(expressions.len(), 1); if let PipelineElement::Expression(_, expr) = &expressions[0] { - let subexprs: Vec<&Expr>; - match expr { + let subexprs: Vec<&Expr> = match expr { Expression { expr: Expr::StringInterpolation(expressions), .. - } => { - subexprs = expressions.iter().map(|e| &e.expr).collect(); - } + } => expressions.iter().map(|e| &e.expr).collect(), _ => panic!("Expected an `Expr::StringInterpolation`"), - } + }; assert_eq!(subexprs.len(), 1); @@ -531,16 +525,13 @@ mod string { assert_eq!(expressions.len(), 1); if let PipelineElement::Expression(_, expr) = &expressions[0] { - let subexprs: Vec<&Expr>; - match expr { + let subexprs: Vec<&Expr> = match expr { Expression { expr: Expr::StringInterpolation(expressions), .. - } => { - subexprs = expressions.iter().map(|e| &e.expr).collect(); - } + } => expressions.iter().map(|e| &e.expr).collect(), _ => panic!("Expected an `Expr::StringInterpolation`"), - } + }; assert_eq!(subexprs.len(), 2); @@ -573,16 +564,13 @@ mod string { assert_eq!(expressions.len(), 1); if let PipelineElement::Expression(_, expr) = &expressions[0] { - let subexprs: Vec<&Expr>; - match expr { + let subexprs: Vec<&Expr> = match expr { Expression { expr: Expr::StringInterpolation(expressions), .. - } => { - subexprs = expressions.iter().map(|e| &e.expr).collect(); - } + } => expressions.iter().map(|e| &e.expr).collect(), _ => panic!("Expected an `Expr::StringInterpolation`"), - } + }; assert_eq!(subexprs.len(), 1); assert_eq!(subexprs[0], &Expr::String("(1 + 3)(7 - 5)".to_string()));