diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index fb8d5f7986..4c90338d75 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -5781,6 +5781,31 @@ pub fn parse_builtin_commands( _ => { let element = parse_pipeline_element(working_set, lite_command); + // There is still a chance to make `parse_pipeline_element` parse into + // some keyword that should apply side effects first, Example: + // + // module a { export alias b = overlay use first.nu }; + // use a + // a b + // + // In this case, `a b` will be parsed as a pipeline element, which leads + // to the `overlay use` command. + // In this case, we need to ensure that the side effects of these keywords + // are applied. + if let Expression { + expr: Expr::Call(call), + .. + } = &element.expr + { + // Apply parse keyword side effects + let cmd = working_set.get_decl(call.decl_id); + match cmd.name() { + "overlay hide" => return parse_overlay_hide(working_set, call.clone()), + "overlay new" => return parse_overlay_new(working_set, call.clone()), + "overlay use" => return parse_overlay_use(working_set, call.clone()), + _ => { /* this alias is not a parser keyword */ } + } + } Pipeline { elements: vec![element], } diff --git a/tests/overlays/mod.rs b/tests/overlays/mod.rs index a04f44641b..f3126c8140 100644 --- a/tests/overlays/mod.rs +++ b/tests/overlays/mod.rs @@ -1287,6 +1287,44 @@ fn alias_overlay_use() { assert_eq!(actual_repl.out, "foo"); } +#[test] +fn alias_overlay_use_2() { + let inp = &[ + "module inner {}", + "module spam { export alias b = overlay use inner }", + "use spam", + "spam b", + "overlay list | get 1", + ]; + + let actual = nu!(&inp.join("; ")); + let actual_repl = nu!(nu_repl_code(inp)); + + assert!(actual.err.is_empty()); + assert!(actual_repl.err.is_empty()); + assert_eq!(actual.out, "inner"); + assert_eq!(actual_repl.out, "inner"); +} + +#[test] +fn alias_overlay_use_3() { + let inp = &[ + "module inner {}", + "module spam { export alias b = overlay use inner }", + "use spam b", + "b", + "overlay list | get 1", + ]; + + let actual = nu!(&inp.join("; ")); + let actual_repl = nu!(nu_repl_code(inp)); + + assert!(actual.err.is_empty()); + assert!(actual_repl.err.is_empty()); + assert_eq!(actual.out, "inner"); + assert_eq!(actual_repl.out, "inner"); +} + #[test] fn alias_overlay_new() { let inp = &[