From bd6c550470e11e3346cd6d99eeea9bd1a3b8b7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Wed, 27 Oct 2021 00:06:08 +0300 Subject: [PATCH] Change import pattern delimiter to space Subcommands and module imports will have the same syntax now. --- crates/nu-command/src/core_commands/use_.rs | 2 +- crates/nu-parser/src/parse_keywords.rs | 16 ++--- crates/nu-parser/src/parser.rs | 80 +++++++++------------ src/tests.rs | 36 ++++------ 4 files changed, 53 insertions(+), 81 deletions(-) diff --git a/crates/nu-command/src/core_commands/use_.rs b/crates/nu-command/src/core_commands/use_.rs index 27635687d..3b899c96e 100644 --- a/crates/nu-command/src/core_commands/use_.rs +++ b/crates/nu-command/src/core_commands/use_.rs @@ -15,7 +15,7 @@ impl Command for Use { } fn signature(&self) -> nu_protocol::Signature { - Signature::build("use").required("pattern", SyntaxShape::String, "import pattern") + Signature::build("use").rest("pattern", SyntaxShape::String, "import pattern parts") } fn run( diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index beafb7054..c5de2f891 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -495,7 +495,7 @@ pub fn parse_use( let (module_name_expr, err) = parse_string(working_set, spans[1]); error = error.or(err); - let (import_pattern, err) = parse_import_pattern(working_set, spans[1]); + let (import_pattern, err) = parse_import_pattern(working_set, &spans[1..]); error = error.or(err); let (import_pattern, exports) = @@ -548,8 +548,7 @@ pub fn parse_use( .into_iter() .map(|(name, id)| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b':'); - new_name.push(b':'); + new_name.push(b' '); new_name.extend(&name); (new_name, id) }) @@ -634,7 +633,7 @@ pub fn parse_hide( let (name_expr, err) = parse_string(working_set, spans[1]); error = error.or(err); - let (import_pattern, err) = parse_import_pattern(working_set, spans[1]); + let (import_pattern, err) = parse_import_pattern(working_set, &spans[1..]); error = error.or(err); let exported_names: Vec> = @@ -664,8 +663,7 @@ pub fn parse_hide( .into_iter() .map(|name| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b':'); - new_name.push(b':'); + new_name.push(b' '); new_name.extend(&name); new_name }) @@ -676,8 +674,7 @@ pub fn parse_hide( .filter(|n| n == name) .map(|n| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b':'); - new_name.push(b':'); + new_name.push(b' '); new_name.extend(&n); new_name }) @@ -698,8 +695,7 @@ pub fn parse_hide( .filter_map(|n| if n == name { Some(n.clone()) } else { None }) .map(|n| { let mut new_name = import_pattern.head.to_vec(); - new_name.push(b':'); - new_name.push(b':'); + new_name.push(b' '); new_name.extend(n); new_name }) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 798a89ec6..8087ffdc1 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1693,70 +1693,54 @@ pub fn parse_type(_working_set: &StateWorkingSet, bytes: &[u8]) -> Type { pub fn parse_import_pattern( working_set: &mut StateWorkingSet, - span: Span, + spans: &[Span], ) -> (ImportPattern, Option) { - let source = working_set.get_span_contents(span); let mut error = None; - let (tokens, err) = lex(source, span.start, &[], &[b':']); - error = error.or(err); + // return ( + // ImportPattern { + // head: vec![], + // members: vec![], + // }, + // Some(ParseError::MissingImportPattern(span)), + // ); - if tokens.is_empty() { - return ( - ImportPattern { - head: vec![], - members: vec![], - }, - Some(ParseError::MissingImportPattern(span)), - ); - } + // return ( + // ImportPattern { + // head: vec![], + // members: vec![], + // }, + // Some(ParseError::WrongImportPattern(span)), + // ); - // We can have either "head" or "head::tail" - if (tokens.len() != 1) && (tokens.len() != 4) { - return ( - ImportPattern { - head: vec![], - members: vec![], - }, - Some(ParseError::WrongImportPattern(span)), - ); - } - - // Check if the second : of the :: is really a : - let has_second_colon = if let Some(t) = tokens.get(2) { - let potential_colon = working_set.get_span_contents(t.span); - potential_colon == b":" + let head = if let Some(head_span) = spans.get(0) { + let (head_expr, err) = parse_string(working_set, *head_span); + error = error.or(err); + working_set.get_span_contents(head_expr.span).to_vec() } else { - false + return ( + ImportPattern { + head: vec![], + members: vec![], + }, + Some(ParseError::WrongImportPattern(span(spans))), + ); }; - if (tokens.len() == 4) && !has_second_colon { - // Applies only to the "head::tail" structure; "head" only doesn't have : - return ( - ImportPattern { - head: vec![], - members: vec![], - }, - Some(ParseError::WrongImportPattern(span)), - ); - } - - let head = working_set.get_span_contents(tokens[0].span).to_vec(); - - if let Some(tail) = tokens.get(3) { + if let Some(tail_span) = spans.get(1) { // FIXME: expand this to handle deeper imports once we support module imports - let tail_span = tail.span; - let tail = working_set.get_span_contents(tail.span); + let tail = working_set.get_span_contents(*tail_span); if tail == b"*" { ( ImportPattern { head, - members: vec![ImportPatternMember::Glob { span: tail_span }], + members: vec![ImportPatternMember::Glob { span: *tail_span }], }, error, ) } else if tail.starts_with(b"[") { - let (result, err) = parse_list_expression(working_set, tail_span, &SyntaxShape::String); + let (result, err) = + parse_list_expression(working_set, *tail_span, &SyntaxShape::String); error = error.or(err); let mut output = vec![]; @@ -1793,7 +1777,7 @@ pub fn parse_import_pattern( head, members: vec![ImportPatternMember::Name { name: tail.to_vec(), - span: tail_span, + span: *tail_span, }], }, error, diff --git a/src/tests.rs b/src/tests.rs index 0d51af054..a3146456c 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -389,7 +389,7 @@ fn better_block_types() -> TestResult { #[test] fn module_imports_1() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo; foo::a"#, + r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo; foo a"#, "1", ) } @@ -397,7 +397,7 @@ fn module_imports_1() -> TestResult { #[test] fn module_imports_2() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo::a; a"#, + r#"module foo { export def a [] { 1 }; def b [] { 2 } }; use foo a; a"#, "1", ) } @@ -405,7 +405,7 @@ fn module_imports_2() -> TestResult { #[test] fn module_imports_3() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo::*; b"#, + r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo *; b"#, "2", ) } @@ -413,7 +413,7 @@ fn module_imports_3() -> TestResult { #[test] fn module_imports_4() -> TestResult { fail_test( - r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo::c"#, + r#"module foo { export def a [] { 1 }; export def b [] { 2 } }; use foo c"#, "not find import", ) } @@ -421,7 +421,7 @@ fn module_imports_4() -> TestResult { #[test] fn module_imports_5() -> TestResult { run_test( - r#"module foo { export def a [] { 1 }; def b [] { 2 }; export def c [] { 3 } }; use foo::[a, c]; c"#, + r#"module foo { export def a [] { 1 }; def b [] { 2 }; export def c [] { 3 } }; use foo [a, c]; c"#, "3", ) } @@ -429,7 +429,7 @@ fn module_imports_5() -> TestResult { #[test] fn module_import_uses_internal_command() -> TestResult { run_test( - r#"module foo { def b [] { 2 }; export def a [] { b } }; use foo; foo::a"#, + r#"module foo { def b [] { 2 }; export def a [] { b } }; use foo; foo a"#, "2", ) } @@ -442,14 +442,6 @@ fn module_import_does_not_parse_with_incorrect_delimiter() -> TestResult { ) } -#[test] -fn module_import_does_not_parse_with_missing_tail() -> TestResult { - fail_test( - r#"module foo { export def a [] { 1 } }; use foo::"#, - not_found_msg(), - ) -} - // TODO: Test the use/hide tests also as separate lines in REPL (i.e., with merging the delta in between) #[test] fn hides_def() -> TestResult { @@ -507,7 +499,7 @@ fn hide_twice_not_allowed() -> TestResult { #[test] fn hides_import_1() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam; hide spam::foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam; hide spam foo; foo"#, not_found_msg(), ) } @@ -515,7 +507,7 @@ fn hides_import_1() -> TestResult { #[test] fn hides_import_2() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam; hide spam::*; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam; hide spam *; foo"#, not_found_msg(), ) } @@ -523,7 +515,7 @@ fn hides_import_2() -> TestResult { #[test] fn hides_import_3() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam; hide spam::[foo]; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam; hide spam [foo]; foo"#, not_found_msg(), ) } @@ -531,7 +523,7 @@ fn hides_import_3() -> TestResult { #[test] fn hides_import_4() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam::foo; hide foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam foo; hide foo; foo"#, not_found_msg(), ) } @@ -539,7 +531,7 @@ fn hides_import_4() -> TestResult { #[test] fn hides_import_5() -> TestResult { fail_test( - r#"module spam { export def foo [] { "foo" } }; use spam::*; hide foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam *; hide foo; foo"#, not_found_msg(), ) } @@ -555,7 +547,7 @@ fn def_twice_should_fail() -> TestResult { #[test] fn use_import_after_hide() -> TestResult { run_test( - r#"module spam { export def foo [] { "foo" } }; use spam::foo; hide foo; use spam::foo; foo"#, + r#"module spam { export def foo [] { "foo" } }; use spam foo; hide foo; use spam foo; foo"#, "foo", ) } @@ -563,7 +555,7 @@ fn use_import_after_hide() -> TestResult { #[test] fn hide_shadowed_decl() -> TestResult { run_test( - r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; do { use spam::foo; hide foo; foo }"#, + r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; do { use spam foo; hide foo; foo }"#, "foo", ) } @@ -571,7 +563,7 @@ fn hide_shadowed_decl() -> TestResult { #[test] fn hides_all_decls_within_scope() -> TestResult { fail_test( - r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; use spam::foo; hide foo; foo"#, + r#"module spam { export def foo [] { "bar" } }; def foo [] { "foo" }; use spam foo; hide foo; foo"#, not_found_msg(), ) }