From 2abdeb386e5bd31a9516616a6cae8af4ecbd512c Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Sun, 2 May 2021 03:25:43 -0700 Subject: [PATCH] Pass evaluated arguments as positional arguments (#810) --- src/evaluator.rs | 14 +++++++++--- src/justfile.rs | 4 ++-- src/recipe.rs | 6 +++--- tests/positional_arguments.rs | 40 +++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/evaluator.rs b/src/evaluator.rs index 99a8b3c..f259cab 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -194,7 +194,7 @@ impl<'src, 'run> Evaluator<'src, 'run> { scope: &'run Scope<'src, 'run>, settings: &'run Settings, search: &'run Search, - ) -> RunResult<'src, Scope<'src, 'run>> { + ) -> RunResult<'src, (Scope<'src, 'run>, Vec)> { let mut evaluator = Evaluator { assignments: None, scope: scope.child(), @@ -206,11 +206,15 @@ impl<'src, 'run> Evaluator<'src, 'run> { let mut scope = scope.child(); + let mut positional = Vec::new(); + let mut rest = arguments; for parameter in parameters { let value = if rest.is_empty() { if let Some(ref default) = parameter.default { - evaluator.evaluate_expression(default)? + let value = evaluator.evaluate_expression(default)?; + positional.push(value.clone()); + value } else if parameter.kind == ParameterKind::Star { String::new() } else { @@ -219,18 +223,22 @@ impl<'src, 'run> Evaluator<'src, 'run> { }); } } else if parameter.kind.is_variadic() { + for value in rest { + positional.push((*value).to_owned()); + } let value = rest.to_vec().join(" "); rest = &[]; value } else { let value = rest[0].to_owned(); + positional.push(value.clone()); rest = &rest[1..]; value }; scope.bind(parameter.export, parameter.name, value); } - Ok(scope) + Ok((scope, positional)) } pub(crate) fn recipe_evaluator( diff --git a/src/justfile.rs b/src/justfile.rs index 849b63f..8d1ac4a 100644 --- a/src/justfile.rs +++ b/src/justfile.rs @@ -253,7 +253,7 @@ impl<'src> Justfile<'src> { search: &'run Search, ran: &mut BTreeSet>, ) -> RunResult<'src, ()> { - let outer = Evaluator::evaluate_parameters( + let (outer, positional) = Evaluator::evaluate_parameters( context.config, dotenv, &recipe.parameters, @@ -285,7 +285,7 @@ impl<'src> Justfile<'src> { } } - recipe.run(context, dotenv, scope.child(), search, arguments)?; + recipe.run(context, dotenv, scope.child(), search, &positional)?; let mut invocation = vec![recipe.name().to_owned()]; for argument in arguments.iter().cloned() { diff --git a/src/recipe.rs b/src/recipe.rs index f1fc40e..f7ae982 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -74,7 +74,7 @@ impl<'src, D> Recipe<'src, D> { dotenv: &BTreeMap, scope: Scope<'src, 'run>, search: &'run Search, - arguments: &[&'run str], + positional: &[String], ) -> RunResult<'src, ()> { let config = &context.config; @@ -178,7 +178,7 @@ impl<'src, D> Recipe<'src, D> { })?; if context.settings.positional_arguments { - command.args(arguments); + command.args(positional); } command.export(context.settings, dotenv, &scope); @@ -267,7 +267,7 @@ impl<'src, D> Recipe<'src, D> { if context.settings.positional_arguments { cmd.arg(self.name.lexeme()); - cmd.args(arguments); + cmd.args(positional); } if config.verbosity.quiet() { diff --git a/tests/positional_arguments.rs b/tests/positional_arguments.rs index 2d24298..f412f0c 100644 --- a/tests/positional_arguments.rs +++ b/tests/positional_arguments.rs @@ -64,3 +64,43 @@ test! { args: ("foo", "a", "b", "c"), stdout: "a\na b c\n", } + +test! { + name: default_arguments, + justfile: r#" + set positional-arguments + + foo bar='baz': + echo $1 + "#, + args: (), + stdout: "baz\n", + stderr: "echo $1\n", +} + +test! { + name: empty_variadic_is_undefined, + justfile: r#" + set positional-arguments + + foo *bar: + if [ -n "${1+1}" ]; then echo defined; else echo undefined; fi + "#, + args: (), + stdout: "undefined\n", + stderr: "if [ -n \"${1+1}\" ]; then echo defined; else echo undefined; fi\n", +} + +test! { + name: variadic_arguments_are_separate, + justfile: r#" + set positional-arguments + + foo *bar: + echo $1 + echo $2 + "#, + args: ("foo", "a", "b"), + stdout: "a\nb\n", + stderr: "echo $1\necho $2\n", +}