diff --git a/crates/nu-command/src/core_commands/use_.rs b/crates/nu-command/src/core_commands/use_.rs index 965200540a..b9bfcc2bbe 100644 --- a/crates/nu-command/src/core_commands/use_.rs +++ b/crates/nu-command/src/core_commands/use_.rs @@ -42,7 +42,7 @@ impl Command for Use { )); }; - if let Some(overlay_id) = engine_state.find_overlay(&import_pattern.head.name) { + if let Some(overlay_id) = import_pattern.head.id { let overlay = engine_state.get_overlay(overlay_id); let env_vars_to_use = if import_pattern.members.is_empty() { @@ -102,14 +102,13 @@ impl Command for Use { } else { // TODO: This is a workaround since call.positional[0].span points at 0 for some reason // when this error is triggered - let bytes = engine_state.get_span_contents(&call.positional[0].span); return Err(ShellError::SpannedLabeledError( format!( - "Could not use '{}' import pattern", - String::from_utf8_lossy(bytes) + "Could not import from '{}'", + String::from_utf8_lossy(&import_pattern.head.name) ), - "called here".to_string(), - call.head, + "module does not exist".to_string(), + import_pattern.head.span, )); } diff --git a/crates/nu-command/tests/commands/mod.rs b/crates/nu-command/tests/commands/mod.rs index 695d7c540c..4e09f4f280 100644 --- a/crates/nu-command/tests/commands/mod.rs +++ b/crates/nu-command/tests/commands/mod.rs @@ -60,6 +60,7 @@ mod str_; mod touch; mod uniq; mod update; +mod use_; mod where_; #[cfg(feature = "which")] mod which; diff --git a/crates/nu-command/tests/commands/use_.rs b/crates/nu-command/tests/commands/use_.rs new file mode 100644 index 0000000000..543dc3df85 --- /dev/null +++ b/crates/nu-command/tests/commands/use_.rs @@ -0,0 +1,34 @@ +use nu_test_support::fs::{AbsolutePath, DisplayPath, Stub::FileWithContent}; +use nu_test_support::nu; +use nu_test_support::pipeline; +use nu_test_support::playground::Playground; + +#[test] +fn use_module_file_within_block() { + Playground::setup("use_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("spam.nu")); + + nu.with_files(vec![FileWithContent( + &file.display_path(), + r#" + export def foo [] { + echo "hello world" + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + def bar [] { + use spam.nu foo; + foo + }; + bar + "# + ) + ); + + assert_eq!(actual.out, "hello world"); + }) +} diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index c40a618c32..ebb69b8ed5 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -1116,12 +1116,13 @@ pub fn parse_use( error = error.or(err); let _ = working_set.add_block(block); - let _ = working_set.add_overlay(&module_name, overlay.clone()); + let overlay_id = working_set.add_overlay(&module_name, overlay.clone()); ( ImportPattern { head: ImportPatternHead { name: module_name.into(), + id: Some(overlay_id), span: spans[1], }, members: import_pattern.members, @@ -1141,10 +1142,7 @@ pub fn parse_use( ); } } else { - error = error.or(Some(ParseError::FileNotFound( - module_filename, - import_pattern.head.span, - ))); + error = error.or(Some(ParseError::ModuleNotFound(import_pattern.head.span))); (ImportPattern::new(), Overlay::new()) } } else { diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 1afaf57151..517ba75125 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2093,6 +2093,8 @@ pub fn parse_import_pattern( ); }; + let maybe_overlay_id = working_set.find_overlay(&head); + let (import_pattern, err) = if let Some(tail_span) = spans.get(1) { // FIXME: expand this to handle deeper imports once we support module imports let tail = working_set.get_span_contents(*tail_span); @@ -2101,6 +2103,7 @@ pub fn parse_import_pattern( ImportPattern { head: ImportPatternHead { name: head, + id: maybe_overlay_id, span: *head_span, }, members: vec![ImportPatternMember::Glob { span: *tail_span }], @@ -2129,6 +2132,7 @@ pub fn parse_import_pattern( ImportPattern { head: ImportPatternHead { name: head, + id: maybe_overlay_id, span: *head_span, }, members: vec![ImportPatternMember::List { names: output }], @@ -2141,6 +2145,7 @@ pub fn parse_import_pattern( ImportPattern { head: ImportPatternHead { name: head, + id: maybe_overlay_id, span: *head_span, }, members: vec![], @@ -2155,6 +2160,7 @@ pub fn parse_import_pattern( ImportPattern { head: ImportPatternHead { name: head, + id: maybe_overlay_id, span: *head_span, }, members: vec![ImportPatternMember::Name { @@ -2171,6 +2177,7 @@ pub fn parse_import_pattern( ImportPattern { head: ImportPatternHead { name: head, + id: maybe_overlay_id, span: *head_span, }, members: vec![], diff --git a/crates/nu-protocol/src/ast/import_pattern.rs b/crates/nu-protocol/src/ast/import_pattern.rs index a35fb671b9..6c361f666d 100644 --- a/crates/nu-protocol/src/ast/import_pattern.rs +++ b/crates/nu-protocol/src/ast/import_pattern.rs @@ -1,4 +1,4 @@ -use crate::{span, Span}; +use crate::{span, OverlayId, Span}; use std::collections::HashSet; #[derive(Debug, Clone)] @@ -11,6 +11,7 @@ pub enum ImportPatternMember { #[derive(Debug, Clone)] pub struct ImportPatternHead { pub name: Vec, + pub id: Option, pub span: Span, } @@ -28,6 +29,7 @@ impl ImportPattern { ImportPattern { head: ImportPatternHead { name: vec![], + id: None, span: Span { start: 0, end: 0 }, }, members: vec![],