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>,
settings: &'run Settings,
search: &'run Search,
) -> RunResult<'src, Scope<'src, 'run>> {
) -> RunResult<'src, (Scope<'src, 'run>, Vec<String>)> {
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(

View File

@ -253,7 +253,7 @@ impl<'src> Justfile<'src> {
search: &'run Search,
ran: &mut BTreeSet<Vec<String>>,
) -> 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() {

View File

@ -74,7 +74,7 @@ impl<'src, D> Recipe<'src, D> {
dotenv: &BTreeMap<String, String>,
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() {

View File

@ -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",
}