From b1970f79ee499b77e40c7832efc2295a750fd474 Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 26 Jun 2021 09:09:06 +1200 Subject: [PATCH] Add support for arbitrarily nested subcommands (#3688) --- crates/nu-parser/src/parse.rs | 32 +++++++++++++---------- tests/shell/pipeline/commands/internal.rs | 24 +++++++++++++++++ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index 7d9173b34..cbbee3666 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -1841,21 +1841,25 @@ fn parse_call( error = error.or(err); return (Some(ClassifiedCommand::Expr(Box::new(expr))), error); } else if lite_cmd.parts.len() > 1 { - // Check if it's a sub-command - if let Some(signature) = scope.get_signature(&format!( - "{} {}", - lite_cmd.parts[0].item, lite_cmd.parts[1].item - )) { - let (mut internal_command, err) = - parse_internal_command(&lite_cmd, scope, &signature, 1); + // FIXME: only build up valid subcommands instead of all arguments + // by checking each part to see if it's a valid identifier name + let mut parts: Vec<_> = lite_cmd.parts.clone().into_iter().map(|x| x.item).collect(); - error = error.or(err); - internal_command.args.external_redirection = if end_of_pipeline { - ExternalRedirection::None - } else { - ExternalRedirection::Stdout - }; - return (Some(ClassifiedCommand::Internal(internal_command)), error); + while parts.len() > 1 { + // Check if it's a sub-command + if let Some(signature) = scope.get_signature(&parts.join(" ")) { + let (mut internal_command, err) = + parse_internal_command(&lite_cmd, scope, &signature, parts.len() - 1); + + error = error.or(err); + internal_command.args.external_redirection = if end_of_pipeline { + ExternalRedirection::None + } else { + ExternalRedirection::Stdout + }; + return (Some(ClassifiedCommand::Internal(internal_command)), error); + } + parts.pop(); } } // Check if it's an internal command diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 8b45c23d8..0e923977d 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -1059,6 +1059,30 @@ fn better_subexpr_lex() { assert_eq!(actual.out, "6"); } +#[test] +fn subsubcommand() { + let actual = nu!( + cwd: ".", pipeline( + r#" + def "aws s3 rb" [url] { $url + " loaded" }; aws s3 rb localhost + "#) + ); + + assert_eq!(actual.out, "localhost loaded"); +} + +#[test] +fn manysubcommand() { + let actual = nu!( + cwd: ".", pipeline( + r#" + def "aws s3 rb ax vf qqqq rrrr" [url] { $url + " loaded" }; aws s3 rb ax vf qqqq rrrr localhost + "#) + ); + + assert_eq!(actual.out, "localhost loaded"); +} + mod parse { use nu_test_support::nu;