Pass evaluated arguments as positional arguments (#810)

This commit is contained in:
Casey Rodarmor 2021-05-02 03:25:43 -07:00 committed by GitHub
parent 7889f10a6a
commit 2abdeb386e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 8 deletions

View File

@ -194,7 +194,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
scope: &'run Scope<'src, 'run>, scope: &'run Scope<'src, 'run>,
settings: &'run Settings, settings: &'run Settings,
search: &'run Search, search: &'run Search,
) -> RunResult<'src, Scope<'src, 'run>> { ) -> RunResult<'src, (Scope<'src, 'run>, Vec<String>)> {
let mut evaluator = Evaluator { let mut evaluator = Evaluator {
assignments: None, assignments: None,
scope: scope.child(), scope: scope.child(),
@ -206,11 +206,15 @@ impl<'src, 'run> Evaluator<'src, 'run> {
let mut scope = scope.child(); let mut scope = scope.child();
let mut positional = Vec::new();
let mut rest = arguments; let mut rest = arguments;
for parameter in parameters { for parameter in parameters {
let value = if rest.is_empty() { let value = if rest.is_empty() {
if let Some(ref default) = parameter.default { 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 { } else if parameter.kind == ParameterKind::Star {
String::new() String::new()
} else { } else {
@ -219,18 +223,22 @@ impl<'src, 'run> Evaluator<'src, 'run> {
}); });
} }
} else if parameter.kind.is_variadic() { } else if parameter.kind.is_variadic() {
for value in rest {
positional.push((*value).to_owned());
}
let value = rest.to_vec().join(" "); let value = rest.to_vec().join(" ");
rest = &[]; rest = &[];
value value
} else { } else {
let value = rest[0].to_owned(); let value = rest[0].to_owned();
positional.push(value.clone());
rest = &rest[1..]; rest = &rest[1..];
value value
}; };
scope.bind(parameter.export, parameter.name, value); scope.bind(parameter.export, parameter.name, value);
} }
Ok(scope) Ok((scope, positional))
} }
pub(crate) fn recipe_evaluator( pub(crate) fn recipe_evaluator(

View File

@ -253,7 +253,7 @@ impl<'src> Justfile<'src> {
search: &'run Search, search: &'run Search,
ran: &mut BTreeSet<Vec<String>>, ran: &mut BTreeSet<Vec<String>>,
) -> RunResult<'src, ()> { ) -> RunResult<'src, ()> {
let outer = Evaluator::evaluate_parameters( let (outer, positional) = Evaluator::evaluate_parameters(
context.config, context.config,
dotenv, dotenv,
&recipe.parameters, &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()]; let mut invocation = vec![recipe.name().to_owned()];
for argument in arguments.iter().cloned() { for argument in arguments.iter().cloned() {

View File

@ -74,7 +74,7 @@ impl<'src, D> Recipe<'src, D> {
dotenv: &BTreeMap<String, String>, dotenv: &BTreeMap<String, String>,
scope: Scope<'src, 'run>, scope: Scope<'src, 'run>,
search: &'run Search, search: &'run Search,
arguments: &[&'run str], positional: &[String],
) -> RunResult<'src, ()> { ) -> RunResult<'src, ()> {
let config = &context.config; let config = &context.config;
@ -178,7 +178,7 @@ impl<'src, D> Recipe<'src, D> {
})?; })?;
if context.settings.positional_arguments { if context.settings.positional_arguments {
command.args(arguments); command.args(positional);
} }
command.export(context.settings, dotenv, &scope); command.export(context.settings, dotenv, &scope);
@ -267,7 +267,7 @@ impl<'src, D> Recipe<'src, D> {
if context.settings.positional_arguments { if context.settings.positional_arguments {
cmd.arg(self.name.lexeme()); cmd.arg(self.name.lexeme());
cmd.args(arguments); cmd.args(positional);
} }
if config.verbosity.quiet() { if config.verbosity.quiet() {

View File

@ -64,3 +64,43 @@ test! {
args: ("foo", "a", "b", "c"), args: ("foo", "a", "b", "c"),
stdout: "a\na b c\n", 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",
}