Prefix parameters with $ to export to environment (#773)

If a parameter is prefixed with an `$`, it will be exported as an
environment variable.
This commit is contained in:
Casey Rodarmor 2021-03-25 18:35:24 -07:00 committed by GitHub
parent 122c351eba
commit 6f42c8b737
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 68 additions and 8 deletions

View File

@ -757,6 +757,14 @@ test:
cargo test
```
Parameters prefixed with a `$` will be exported as environment variables:
```make
test $RUST_BACKTRACE="1":
# will print a stack trace if it crashes
cargo test
```
=== Recipe Parameters
Recipes may have parameters. Here recipe `build` has a parameter called `target`:
@ -872,6 +880,13 @@ search QUERY:
lynx 'https://www.google.com/?q={{QUERY}}'
```
Parameters prefixed with a `$` will be exported as environment variables:
```make
foo $bar:
echo $bar
```
=== Running recipes at the end of a recipe
Dependencies of a recipes always run before a recipe starts. That is to say, the dependee always runs before the depender.

View File

@ -227,7 +227,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
rest = &rest[1..];
value
};
scope.bind(false, parameter.name, value);
scope.bind(parameter.export, parameter.name, value);
}
Ok(scope)

View File

@ -464,6 +464,7 @@ impl<'src> Lexer<'src> {
match start {
'!' => self.lex_bang(),
'*' => self.lex_single(Asterisk),
'$' => self.lex_single(Dollar),
'@' => self.lex_single(At),
'[' => self.lex_delimiter(BracketL),
']' => self.lex_delimiter(BracketR),
@ -912,6 +913,7 @@ mod tests {
Colon => ":",
ColonEquals => ":=",
Comma => ",",
Dollar => "$",
Eol => "\n",
Equals => "=",
EqualsEquals => "==",
@ -1048,6 +1050,12 @@ mod tests {
tokens: (BraceL, BraceL, BraceL, BraceR, BraceR, BraceR),
}
test! {
name: dollar,
text: "$",
tokens: (Dollar),
}
test! {
name: export_concatination,
text: "export foo = 'foo' + 'bar'",

View File

@ -9,6 +9,8 @@ pub(crate) struct Parameter<'src> {
pub(crate) kind: ParameterKind,
/// An optional default expression
pub(crate) default: Option<Expression<'src>>,
/// Export parameter as environment variable
pub(crate) export: bool,
}
impl<'src> Display for Parameter<'src> {

View File

@ -568,7 +568,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
let mut positional = Vec::new();
while self.next_is(Identifier) {
while self.next_is(Identifier) || self.next_is(Dollar) {
positional.push(self.parse_parameter(ParameterKind::Singular)?);
}
@ -620,6 +620,8 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
/// Parse a recipe parameter
fn parse_parameter(&mut self, kind: ParameterKind) -> CompilationResult<'src, Parameter<'src>> {
let export = self.accepted(Dollar)?;
let name = self.parse_name()?;
let default = if self.accepted(Equals)? {
@ -632,6 +634,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
name,
kind,
default,
export,
})
}
@ -1643,7 +1646,10 @@ mod tests {
line: 0,
column: 5,
width: 1,
kind: UnexpectedToken{expected: vec![Asterisk, Colon, Equals, Identifier, Plus], found: Eol},
kind: UnexpectedToken{
expected: vec![Asterisk, Colon, Dollar, Equals, Identifier, Plus],
found: Eol
},
}
error! {
@ -1728,7 +1734,7 @@ mod tests {
line: 0,
column: 6,
width: 1,
kind: UnexpectedToken{expected: vec![Identifier], found: Colon},
kind: UnexpectedToken{expected: vec![Dollar, Identifier], found: Colon},
}
error! {
@ -1748,7 +1754,10 @@ mod tests {
line: 0,
column: 8,
width: 0,
kind: UnexpectedToken{expected: vec![Asterisk, Colon, Equals, Identifier, Plus], found: Eof},
kind: UnexpectedToken {
expected: vec![Asterisk, Colon, Dollar, Equals, Identifier, Plus],
found: Eof
},
}
error! {

View File

@ -15,6 +15,7 @@ pub(crate) enum TokenKind {
Comma,
Comment,
Dedent,
Dollar,
Eof,
Eol,
Equals,
@ -50,6 +51,7 @@ impl Display for TokenKind {
Comma => "','",
Comment => "comment",
Dedent => "dedent",
Dollar => "'$'",
Eof => "end of file",
Eol => "end of line",
Equals => "'='",

View File

@ -13,6 +13,30 @@ wut:
stderr: "echo $FOO $BAR $ABC\n",
}
test! {
name: parameter,
justfile: r#"
wut $FOO='a' BAR='b':
echo $FOO
echo {{BAR}}
if [ -n "${BAR+1}" ]; then echo defined; else echo undefined; fi
"#,
stdout: "a\nb\nundefined\n",
stderr: "echo $FOO\necho b\nif [ -n \"${BAR+1}\" ]; then echo defined; else echo undefined; fi\n",
}
test! {
name: parameter_not_visible_to_backtick,
justfile: r#"
wut $FOO BAR=`if [ -n "${FOO+1}" ]; then echo defined; else echo undefined; fi`:
echo $FOO
echo {{BAR}}
"#,
args: ("wut", "bar"),
stdout: "bar\nundefined\n",
stderr: "echo $FOO\necho undefined\n",
}
test! {
name: override_variable,
justfile: r#"

View File

@ -1422,7 +1422,7 @@ test! {
justfile: "foo 'bar'",
args: ("foo"),
stdout: "",
stderr: "error: Expected '*', ':', identifier, or '+', but found raw string
stderr: "error: Expected '*', ':', '$', identifier, or '+', but found raw string
|
1 | foo 'bar'
| ^^^^^
@ -2050,12 +2050,12 @@ foo a=\t`echo blaaaaaah:
test! {
name: unknown_start_of_token,
justfile: "
assembly_source_files = $(wildcard src/arch/$(arch)/*.s)
assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
",
stderr: r#"
error: Unknown start of token:
|
2 | assembly_source_files = $(wildcard src/arch/$(arch)/*.s)
2 | assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
| ^
"#,
status: EXIT_FAILURE,