diff --git a/crates/nu-command/src/filters/for_.rs b/crates/nu-command/src/core_commands/for_.rs similarity index 98% rename from crates/nu-command/src/filters/for_.rs rename to crates/nu-command/src/core_commands/for_.rs index ddb69e0f96..7da8a03eac 100644 --- a/crates/nu-command/src/filters/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -18,7 +18,7 @@ impl Command for For { Signature::build("for") .required( "var_name", - SyntaxShape::Variable, + SyntaxShape::VarWithOptType, "name of the looping variable", ) .required( @@ -34,6 +34,7 @@ impl Command for For { SyntaxShape::Block(Some(vec![])), "the block to run", ) + .creates_scope() } fn run( diff --git a/crates/nu-command/src/core_commands/mod.rs b/crates/nu-command/src/core_commands/mod.rs index 7418026a56..a124ffcf18 100644 --- a/crates/nu-command/src/core_commands/mod.rs +++ b/crates/nu-command/src/core_commands/mod.rs @@ -2,6 +2,7 @@ mod alias; mod def; mod do_; mod export_def; +mod for_; mod help; mod hide; mod if_; @@ -14,6 +15,7 @@ pub use alias::Alias; pub use def::Def; pub use do_::Do; pub use export_def::ExportDef; +pub use for_::For; pub use help::Help; pub use hide::Hide; pub use if_::If; diff --git a/crates/nu-command/src/filters/mod.rs b/crates/nu-command/src/filters/mod.rs index c905721569..e4e68902da 100644 --- a/crates/nu-command/src/filters/mod.rs +++ b/crates/nu-command/src/filters/mod.rs @@ -1,5 +1,4 @@ mod each; -mod for_; mod get; mod length; mod lines; @@ -8,7 +7,6 @@ mod where_; mod wrap; pub use each::Each; -pub use for_::For; pub use get::Get; pub use length::Length; pub use lines::Lines; diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index dbd2ddc298..e1cdcb9781 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -459,6 +459,10 @@ pub fn parse_internal_call( let signature = working_set.get_decl(decl_id).signature(); + if signature.creates_scope { + working_set.enter_scope(); + } + // The index into the positional parameter in the definition let mut positional_idx = 0; @@ -554,6 +558,10 @@ pub fn parse_internal_call( let err = check_call(command_span, &signature, &call); error = error.or(err); + if signature.creates_scope { + working_set.exit_scope(); + } + // FIXME: type unknown (Box::new(call), span(spans), error) } diff --git a/crates/nu-protocol/src/signature.rs b/crates/nu-protocol/src/signature.rs index 49bae4280f..d1abc77330 100644 --- a/crates/nu-protocol/src/signature.rs +++ b/crates/nu-protocol/src/signature.rs @@ -36,6 +36,7 @@ pub struct Signature { pub rest_positional: Option, pub named: Vec, pub is_filter: bool, + pub creates_scope: bool, } impl PartialEq for Signature { @@ -62,6 +63,7 @@ impl Signature { rest_positional: None, named: vec![], is_filter: false, + creates_scope: false, } } pub fn build(name: impl Into) -> Signature { @@ -189,6 +191,12 @@ impl Signature { self } + /// Sets that signature will create a scope as it parses + pub fn creates_scope(mut self) -> Signature { + self.creates_scope = true; + self + } + /// Get list of the short-hand flags pub fn get_shorts(&self) -> Vec { self.named.iter().filter_map(|f| f.short).collect() diff --git a/src/tests.rs b/src/tests.rs index 38a9376239..4c2c96191d 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -564,3 +564,8 @@ fn split_column() -> TestResult { "hello", ) } + +#[test] +fn for_loops() -> TestResult { + run_test(r#"(for x in [1, 2, 3] { $x + 10 }).1"#, "12") +}