Deprecate = in assignments, aliases, and exports in favor of := (#413)

This commit is contained in:
Casey Rodarmor 2019-04-18 11:48:02 -07:00 committed by GitHub
parent 1c0dc284fe
commit 0ad5574ecc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 298 additions and 184 deletions

View File

@ -49,23 +49,23 @@ item : recipe
eol : NEWLINE
| COMMENT NEWLINE
assignment : NAME '=' expression eol
alias : 'alias' NAME ':=' NAME
alias : 'alias' NAME '=' NAME
assignment : NAME ':=' expression eol
export : 'export' assignment
expression : value '+' expression
| value
value : NAME '(' arguments? ')'
value : NAME '(' sequence? ')'
| STRING
| RAW_STRING
| BACKTICK
| NAME
| '(' expression ')'
arguments : expression ',' arguments
sequence : expression ',' sequence
| expression ','?
recipe : '@'? NAME parameter* ('+' parameter)? ':' dependencies? body?

View File

@ -210,7 +210,7 @@ build test deploy lint
Aliases allow recipes to be invoked with alternative names:
```make
alias b = build
alias b := build
build:
echo 'Building!'
@ -249,9 +249,9 @@ Available recipes:
Variables, strings, concatenation, and substitution using `{{...}}` are supported:
```make
version = "0.2.7"
tardir = "awesomesauce-" + version
tarball = tardir + ".tar.gz"
version := "0.2.7"
tardir := "awesomesauce-" + version
tarball := tardir + ".tar.gz"
publish:
rm -f {{tarball}}
@ -285,29 +285,29 @@ braces:
Double-quoted strings support escape sequences:
```make
string-with-tab = "\t"
string-with-newline = "\n"
string-with-carriage-return = "\r"
string-with-double-quote = "\""
string-with-slash = "\\"
string-with-tab := "\t"
string-with-newline := "\n"
string-with-carriage-return := "\r"
string-with-double-quote := "\""
string-with-slash := "\\"
```
```sh
$ just --evaluate
"tring-with-carriage-return = "
string-with-double-quote = """
string-with-newline = "
"tring-with-carriage-return := "
string-with-double-quote := """
string-with-newline := "
"
string-with-slash = "\"
string-with-tab = " "
string-with-slash := "\"
string-with-tab := " "
```
Single-quoted strings do not recognize escape sequences and may contain line breaks:
```make
escapes = '\t\n\r\"\\'
escapes := '\t\n\r\"\\'
line-breaks = 'hello
line-breaks := 'hello
this
is
a
@ -318,9 +318,9 @@ string!
```sh
$ just --evaluate
escapes = "\t\n\r\"\\"
escapes := "\t\n\r\"\\"
line-breaks = "hello
line-breaks := "hello
this
is
a
@ -410,7 +410,7 @@ Starting server with database localhost:6379 on port 1337...
Backticks can be used to store the result of commands:
```make
localhost = `dumpinterfaces | cut -d: -f2 | sed 's/\/.*//' | sed 's/ //g'`
localhost := `dumpinterfaces | cut -d: -f2 | sed 's/\/.*//' | sed 's/ //g'`
serve:
./serve {{localhost}} 8080
@ -421,7 +421,7 @@ serve:
Variables can be overridden from the command line.
```make
os = "linux"
os := "linux"
test: build
./test --test {{os}}
@ -457,7 +457,7 @@ $ just --set os bsd
Assignments prefixed with the `export` keyword will be exported to recipes as environment variables:
```make
export RUST_BACKTRACE = "1"
export RUST_BACKTRACE := "1"
test:
# will print a stack trace if it crashes
@ -487,7 +487,7 @@ cd my-awesome-project && make
Parameters may have default values:
```make
default = 'all'
default := 'all'
test target tests=default:
@echo 'Testing {{target}}:{{tests}}...'
@ -513,7 +513,7 @@ Testing server:unit...
Default values may be arbitrary expressions, but concatenations must be parenthesized:
```make
arch = "wasm"
arch := "wasm"
test triple=(arch + "-unknown-unknown"):
./test {{triple}}

View File

@ -2,9 +2,9 @@
# ^ A shebang isn't required, but allows a justfile to be executed
# like a script, with `./justfile test`, for example.
bt='0'
bt = '0'
export RUST_BACKTRACE=bt
export RUST_BACKTRACE = bt
alias t = test

View File

@ -10,6 +10,6 @@ pub struct Alias<'a> {
impl<'a> Display for Alias<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "alias {} = {}", self.name, self.target)
write!(f, "alias {} := {}", self.name, self.target)
}
}

View File

@ -76,6 +76,10 @@ impl Color {
self.restyle(Style::new().fg(Red).bold())
}
pub fn warning(self) -> Color {
self.restyle(Style::new().fg(Yellow).bold())
}
pub fn banner(self) -> Color {
self.restyle(Style::new().fg(Cyan).bold())
}

View File

@ -6,6 +6,7 @@ pub struct Justfile<'a> {
pub assignments: BTreeMap<&'a str, Expression<'a>>,
pub exports: BTreeSet<&'a str>,
pub aliases: BTreeMap<&'a str, Alias<'a>>,
pub deprecated_equals: bool,
}
impl<'a> Justfile<'a> where {
@ -80,7 +81,7 @@ impl<'a> Justfile<'a> where {
}
for (name, value) in scope {
println!("{0:1$} = \"{2}\"", name, width, value);
println!("{0:1$} := \"{2}\"", name, width, value);
}
return Ok(());
}
@ -175,7 +176,7 @@ impl<'a> Display for Justfile<'a> {
if self.exports.contains(name) {
write!(f, "export ")?;
}
write!(f, "{} = {}", name, expression)?;
write!(f, "{} := {}", name, expression)?;
items -= 1;
if items != 0 {
write!(f, "\n\n")?;

View File

@ -323,7 +323,7 @@ impl<'a> Lexer<'a> {
'@' => self.lex_single(At),
'=' => self.lex_single(Equals),
',' => self.lex_single(Comma),
':' => self.lex_single(Colon),
':' => self.lex_colon(),
'(' => self.lex_single(ParenL),
')' => self.lex_single(ParenR),
'{' => self.lex_brace_l(),
@ -442,6 +442,20 @@ impl<'a> Lexer<'a> {
Ok(())
}
/// Lex a token starting with ':'
fn lex_colon(&mut self) -> CompilationResult<'a, ()> {
self.advance()?;
if let Some('=') = self.next {
self.advance()?;
self.token(ColonEquals);
} else {
self.token(Colon);
}
Ok(())
}
/// Lex a token starting with '{'
fn lex_brace_l(&mut self) -> CompilationResult<'a, ()> {
if !self.rest_starts_with("{{") {

View File

@ -12,6 +12,7 @@ pub struct Parser<'a> {
exports: BTreeSet<&'a str>,
aliases: BTreeMap<&'a str, Alias<'a>>,
alias_tokens: BTreeMap<&'a str, Token<'a>>,
deprecated_equals: bool,
}
impl<'a> Parser<'a> {
@ -31,6 +32,7 @@ impl<'a> Parser<'a> {
exports: empty(),
aliases: empty(),
alias_tokens: empty(),
deprecated_equals: false,
text,
}
}
@ -152,10 +154,10 @@ impl<'a> Parser<'a> {
}
if let Some(token) = self.expect(Colon) {
// if we haven't accepted any parameters, an equals
// if we haven't accepted any parameters, a :=
// would have been fine as part of an assignment
if parameters.is_empty() {
return Err(self.unexpected_token(&token, &[Name, Plus, Colon, Equals]));
return Err(self.unexpected_token(&token, &[Name, Plus, Colon, ColonEquals]));
} else {
return Err(self.unexpected_token(&token, &[Name, Plus, Colon]));
}
@ -420,6 +422,10 @@ impl<'a> Parser<'a> {
if token.lexeme() == "export" {
let next = self.tokens.next().unwrap();
if next.kind == Name && self.accepted(Equals) {
self.deprecated_equals = true;
self.assignment(next, true)?;
doc = None;
} else if next.kind == Name && self.accepted(ColonEquals) {
self.assignment(next, true)?;
doc = None;
} else {
@ -430,6 +436,10 @@ impl<'a> Parser<'a> {
} else if token.lexeme() == "alias" {
let next = self.tokens.next().unwrap();
if next.kind == Name && self.accepted(Equals) {
self.deprecated_equals = true;
self.alias(next)?;
doc = None;
} else if next.kind == Name && self.accepted(ColonEquals) {
self.alias(next)?;
doc = None;
} else {
@ -438,6 +448,10 @@ impl<'a> Parser<'a> {
doc = None;
}
} else if self.accepted(Equals) {
self.deprecated_equals = true;
self.assignment(token, false)?;
doc = None;
} else if self.accepted(ColonEquals) {
self.assignment(token, false)?;
doc = None;
} else {
@ -501,6 +515,7 @@ impl<'a> Parser<'a> {
assignments: self.assignments,
exports: self.exports,
aliases: self.aliases,
deprecated_equals: self.deprecated_equals,
})
}
}
@ -604,10 +619,10 @@ foo a='b\t':
summary_test! {
parse_export,
r#"
export a = "hello"
export a := "hello"
"#,
r#"export a = "hello""#,
r#"export a := "hello""#,
}
summary_test! {
@ -615,9 +630,9 @@ export a = "hello"
r#"
foo:
echo a
alias f = foo
alias f := foo
"#,
r#"alias f = foo
r#"alias f := foo
foo:
echo a"#
@ -626,11 +641,11 @@ foo:
summary_test! {
parse_alias_before_target,
r#"
alias f = foo
alias f := foo
foo:
echo a
"#,
r#"alias f = foo
r#"alias f := foo
foo:
echo a"#
@ -639,11 +654,11 @@ foo:
summary_test! {
parse_alias_with_comment,
r#"
alias f = foo #comment
alias f := foo #comment
foo:
echo a
"#,
r#"alias f = foo
r#"alias f := foo
foo:
echo a"#
@ -655,9 +670,9 @@ foo:
x:
y:
z:
foo = \"xx\"
bar = foo
goodbye = \"y\"
foo := \"xx\"
bar := foo
goodbye := \"y\"
hello a b c : x y z #hello
#! blah
#blarg
@ -666,11 +681,11 @@ hello a b c : x y z #hello
2
3
",
"bar = foo
"bar := foo
foo = \"xx\"
foo := \"xx\"
goodbye = \"y\"
goodbye := \"y\"
hello a b c: x y z
#! blah
@ -690,14 +705,14 @@ z:"
summary_test! {
parse_shebang,
"
practicum = 'hello'
practicum := 'hello'
install:
\t#!/bin/sh
\tif [[ -f {{practicum}} ]]; then
\t\treturn
\tfi
",
"practicum = 'hello'
"practicum := 'hello'
install:
#!/bin/sh
@ -714,27 +729,27 @@ install:
summary_test! {
parse_assignments,
r#"a = "0"
c = a + b + a + b
b = "1"
r#"a := "0"
c := a + b + a + b
b := "1"
"#,
r#"a = "0"
r#"a := "0"
b = "1"
b := "1"
c = a + b + a + b"#,
c := a + b + a + b"#,
}
summary_test! {
parse_assignment_backticks,
"a = `echo hello`
c = a + b + a + b
b = `echo goodbye`",
"a = `echo hello`
"a := `echo hello`
c := a + b + a + b
b := `echo goodbye`",
"a := `echo hello`
b = `echo goodbye`
b := `echo goodbye`
c = a + b + a + b",
c := a + b + a + b",
}
summary_test! {
@ -753,14 +768,14 @@ c = a + b + a + b",
summary_test! {
string_quote_escape,
r#"a = "hello\"""#,
r#"a = "hello\"""#,
r#"a := "hello\"""#,
r#"a := "hello\"""#,
}
summary_test! {
string_escapes,
r#"a = "\n\t\r\"\\""#,
r#"a = "\n\t\r\"\\""#,
r#"a := "\n\t\r\"\\""#,
r#"a := "\n\t\r\"\\""#,
}
summary_test! {
@ -774,11 +789,11 @@ c = a + b + a + b",
summary_test! {
unary_functions,
"
x = arch()
x := arch()
a:
{{os()}} {{os_family()}}",
"x = arch()
"x := arch()
a:
{{os()}} {{os_family()}}",
@ -787,11 +802,11 @@ a:
summary_test! {
env_functions,
r#"
x = env_var('foo',)
x := env_var('foo',)
a:
{{env_var_or_default('foo' + 'bar', 'baz',)}} {{env_var(env_var("baz"))}}"#,
r#"x = env_var('foo')
r#"x := env_var('foo')
a:
{{env_var_or_default('foo' + 'bar', 'baz')}} {{env_var(env_var("baz"))}}"#,
@ -832,10 +847,10 @@ f x=(`echo hello` + "foo"):
summary_test! {
parameter_default_concatination_variable,
r#"
x = "10"
x := "10"
f y=(`echo hello` + x) +z="foo":
"#,
r#"x = "10"
r#"x := "10"
f y=(`echo hello` + x) +z="foo":"#,
}
@ -843,24 +858,24 @@ f y=(`echo hello` + x) +z="foo":"#,
summary_test! {
parameter_default_multiple,
r#"
x = "10"
x := "10"
f y=(`echo hello` + x) +z=("foo" + "bar"):
"#,
r#"x = "10"
r#"x := "10"
f y=(`echo hello` + x) +z=("foo" + "bar"):"#,
}
summary_test! {
concatination_in_group,
"x = ('0' + '1')",
"x = ('0' + '1')",
"x := ('0' + '1')",
"x := ('0' + '1')",
}
summary_test! {
string_in_group,
"x = ('0' )",
"x = ('0')",
"x := ('0' )",
"x := ('0')",
}
#[rustfmt::skip]

View File

@ -321,6 +321,24 @@ pub fn run() {
}
});
if justfile.deprecated_equals {
let warning = color.warning().stderr();
let message = color.message().stderr();
eprintln!(
"{}",
warning.paint(
"warning: `=` in assignments, exports, and aliases is being phased out on favor of `:=`"
)
);
eprintln!(
"{}",
message
.paint("Please see this issue for more details: https://github.com/casey/just/issues/379")
);
}
if matches.is_present("SUMMARY") {
if justfile.count() == 0 {
eprintln!("Justfile contains no recipes.");

View File

@ -16,6 +16,7 @@ pub fn token_summary(tokens: &[Token]) -> String {
At => "@",
Backtick => "`",
Colon => ":",
ColonEquals => ":=",
Comma => ",",
Comment => "#",
Dedent => "<",

View File

@ -5,6 +5,7 @@ pub enum TokenKind {
At,
Backtick,
Colon,
ColonEquals,
Comma,
Comment,
Dedent,
@ -35,6 +36,7 @@ impl Display for TokenKind {
At => "'@'",
Backtick => "backtick",
Colon => "':'",
ColonEquals => "':='",
Comma => "','",
Comment => "comment",
Dedent => "dedent",

View File

@ -157,7 +157,7 @@ fn integration_test(
integration_test! {
name: alias_listing,
justfile: "foo:\n echo foo\nalias f = foo",
justfile: "foo:\n echo foo\nalias f := foo",
args: ("--list"),
stdin: "",
stdout: "Available recipes:
@ -170,7 +170,7 @@ integration_test! {
integration_test! {
name: alias_listing_multiple_aliases,
justfile: "foo:\n echo foo\nalias f = foo\nalias fo = foo",
justfile: "foo:\n echo foo\nalias f := foo\nalias fo := foo",
args: ("--list"),
stdin: "",
stdout: "Available recipes:
@ -184,7 +184,7 @@ integration_test! {
integration_test! {
name: alias_listing_parameters,
justfile: "foo PARAM='foo':\n echo {{PARAM}}\nalias f = foo",
justfile: "foo PARAM='foo':\n echo {{PARAM}}\nalias f := foo",
args: ("--list"),
stdin: "",
stdout: "Available recipes:
@ -197,7 +197,7 @@ integration_test! {
integration_test! {
name: alias_listing_private,
justfile: "foo PARAM='foo':\n echo {{PARAM}}\nalias _f = foo",
justfile: "foo PARAM='foo':\n echo {{PARAM}}\nalias _f := foo",
args: ("--list"),
stdin: "",
stdout: "Available recipes:
@ -209,7 +209,7 @@ integration_test! {
integration_test! {
name: alias,
justfile: "foo:\n echo foo\nalias f = foo",
justfile: "foo:\n echo foo\nalias f := foo",
args: ("f"),
stdin: "",
stdout: "foo\n",
@ -219,7 +219,7 @@ integration_test! {
integration_test! {
name: alias_with_parameters,
justfile: "foo value='foo':\n echo {{value}}\nalias f = foo",
justfile: "foo value='foo':\n echo {{value}}\nalias f := foo",
args: ("f", "bar"),
stdin: "",
stdout: "bar\n",
@ -229,7 +229,7 @@ integration_test! {
integration_test! {
name: alias_with_dependencies,
justfile: "foo:\n echo foo\nbar: foo\nalias b = bar",
justfile: "foo:\n echo foo\nbar: foo\nalias b := bar",
args: ("b"),
stdin: "",
stdout: "foo\n",
@ -239,13 +239,13 @@ integration_test! {
integration_test! {
name: duplicate_alias,
justfile: "alias foo = bar\nalias foo = baz\n",
justfile: "alias foo := bar\nalias foo := baz\n",
args: (),
stdin: "",
stdout: "" ,
stderr: "error: Alias `foo` first defined on line `1` is redefined on line `2`
|
2 | alias foo = baz
2 | alias foo := baz
| ^^^
",
status: EXIT_FAILURE,
@ -253,13 +253,13 @@ integration_test! {
integration_test! {
name: unknown_alias_target,
justfile: "alias foo = bar\n",
justfile: "alias foo := bar\n",
args: (),
stdin: "",
stdout: "",
stderr: "error: Alias `foo` has an unknown target `bar`
|
1 | alias foo = bar
1 | alias foo := bar
| ^^^
",
status: EXIT_FAILURE,
@ -267,13 +267,13 @@ integration_test! {
integration_test! {
name: alias_shadows_recipe,
justfile: "bar:\n echo bar\nalias foo = bar\nfoo:\n echo foo",
justfile: "bar:\n echo bar\nalias foo := bar\nfoo:\n echo foo",
args: (),
stdin: "",
stdout: "",
stderr: "error: Alias `foo` defined on `3` shadows recipe defined on `4`
|
3 | alias foo = bar
3 | alias foo := bar
| ^^^
",
status: EXIT_FAILURE,
@ -387,8 +387,8 @@ c:
integration_test! {
name: show,
justfile: r#"hello = "foo"
bar = hello + hello
justfile: r#"hello := "foo"
bar := hello + hello
recipe:
echo {{hello + "bar" + bar}}"#,
args: ("--show", "recipe"),
@ -431,7 +431,7 @@ integration_test! {
integration_test! {
name: backtick_success,
justfile: "a = `printf Hello,`\nbar:\n printf '{{a + `printf ' world.'`}}'",
justfile: "a := `printf Hello,`\nbar:\n printf '{{a + `printf ' world.'`}}'",
args: (),
stdin: "",
stdout: "Hello, world.",
@ -441,7 +441,7 @@ integration_test! {
integration_test! {
name: backtick_trimming,
justfile: "a = `echo Hello,`\nbar:\n echo '{{a + `echo ' world.'`}}'",
justfile: "a := `echo Hello,`\nbar:\n echo '{{a + `echo ' world.'`}}'",
args: (),
stdin: "",
stdout: "Hello, world.\n",
@ -451,13 +451,13 @@ integration_test! {
integration_test! {
name: backtick_code_assignment,
justfile: "b = a\na = `exit 100`\nbar:\n echo '{{`exit 200`}}'",
justfile: "b := a\na := `exit 100`\nbar:\n echo '{{`exit 200`}}'",
args: (),
stdin: "",
stdout: "",
stderr: "error: Backtick failed with exit code 100
|
2 | a = `exit 100`
2 | a := `exit 100`
| ^^^^^^^^^^
",
status: 100,
@ -465,7 +465,7 @@ integration_test! {
integration_test! {
name: backtick_code_interpolation,
justfile: "b = a\na = `echo hello`\nbar:\n echo '{{`exit 200`}}'",
justfile: "b := a\na := `echo hello`\nbar:\n echo '{{`exit 200`}}'",
args: (),
stdin: "",
stdout: "",
@ -477,7 +477,6 @@ integration_test! {
status: 200,
}
// 😬鎌
integration_test! {
name: backtick_code_interpolation_mod,
justfile: "f:\n 無{{`exit 200`}}",
@ -579,7 +578,7 @@ backtick-fail:
integration_test! {
name: backtick_code_long,
justfile: "\n\n\n\n\n\nb = a\na = `echo hello`\nbar:\n echo '{{`exit 200`}}'",
justfile: "\n\n\n\n\n\nb := a\na := `echo hello`\nbar:\n echo '{{`exit 200`}}'",
args: (),
stdin: "",
stdout: "",
@ -629,13 +628,13 @@ integration_test! {
justfile: "foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
a := `exit 222`",
args: (),
stdin: "",
stdout: "",
stderr: "error: Backtick failed with exit code 222
|
4 | a = `exit 222`
4 | a := `exit 222`
| ^^^^^^^^^^
",
status: 222,
@ -646,7 +645,7 @@ integration_test! {
justfile: "foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
a := `exit 222`",
args: ("--set", "foo", "bar", "--set", "baz", "bob", "--set", "a", "b", "a", "b"),
stdin: "",
stdout: "",
@ -660,7 +659,7 @@ integration_test! {
justfile: "foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
a := `exit 222`",
args: ("foo=bar", "baz=bob", "a=b", "a", "b"),
stdin: "",
stdout: "",
@ -674,7 +673,7 @@ integration_test! {
justfile: "foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
a := `exit 222`",
args: ("foo=bar", "a=b", "a", "b"),
stdin: "",
stdout: "",
@ -685,9 +684,9 @@ a = `exit 222`",
integration_test! {
name: overrides_first,
justfile: r#"
foo = "foo"
a = "a"
baz = "baz"
foo := "foo"
a := "a"
baz := "baz"
recipe arg:
echo arg={{arg}}
@ -702,9 +701,9 @@ recipe arg:
integration_test! {
name: overrides_not_evaluated,
justfile: r#"
foo = `exit 1`
a = "a"
baz = "baz"
foo := `exit 1`
a := "a"
baz := "baz"
recipe arg:
echo arg={{arg}}
@ -719,7 +718,7 @@ recipe arg:
integration_test! {
name: dry_run,
justfile: r#"
var = `echo stderr 1>&2; echo backtick`
var := `echo stderr 1>&2; echo backtick`
command:
@touch /this/is/not/a/file
@ -748,20 +747,20 @@ echo `echo command interpolation`
integration_test! {
name: evaluate,
justfile: r#"
foo = "a\t"
hello = "c"
bar = "b\t"
ab = foo + bar + hello
foo := "a\t"
hello := "c"
bar := "b\t"
ab := foo + bar + hello
wut:
touch /this/is/not/a/file
"#,
args: ("--evaluate"),
stdin: "",
stdout: r#"ab = "a b c"
bar = "b "
foo = "a "
hello = "c"
stdout: r#"ab := "a b c"
bar := "b "
foo := "a "
hello := "c"
"#,
stderr: "",
status: EXIT_SUCCESS,
@ -770,10 +769,10 @@ hello = "c"
integration_test! {
name: export_success,
justfile: r#"
export FOO = "a"
baz = "c"
export BAR = "b"
export ABC = FOO + BAR + baz
export FOO := "a"
baz := "c"
export BAR := "b"
export ABC := FOO + BAR + baz
wut:
echo $FOO $BAR $ABC
@ -788,10 +787,10 @@ wut:
integration_test! {
name: export_override,
justfile: r#"
export FOO = "a"
baz = "c"
export BAR = "b"
export ABC = FOO + "-" + BAR + "-" + baz
export FOO := "a"
baz := "c"
export BAR := "b"
export ABC := FOO + "-" + BAR + "-" + baz
wut:
echo $FOO $BAR $ABC
@ -806,10 +805,10 @@ wut:
integration_test! {
name: export_shebang,
justfile: r#"
export FOO = "a"
baz = "c"
export BAR = "b"
export ABC = FOO + BAR + baz
export FOO := "a"
baz := "c"
export BAR := "b"
export ABC := FOO + BAR + baz
wut:
#!/bin/sh
@ -825,7 +824,7 @@ wut:
integration_test! {
name: export_recipe_backtick,
justfile: r#"
export EXPORTED_VARIABLE = "A-IS-A"
export EXPORTED_VARIABLE := "A-IS-A"
recipe:
echo {{`echo recipe $EXPORTED_VARIABLE`}}
@ -840,7 +839,7 @@ recipe:
integration_test! {
name: raw_string,
justfile: r#"
export EXPORTED_VARIABLE = '\z'
export EXPORTED_VARIABLE := '\z'
recipe:
printf "$EXPORTED_VARIABLE"
@ -931,7 +930,7 @@ default:
integration_test! {
name: quiet_flag_no_assignment_backtick_stderr,
justfile: r#"
a = `echo hello 1>&2`
a := `echo hello 1>&2`
default:
exit 100
"#,
@ -1056,24 +1055,24 @@ integration_test! {
integration_test! {
name: color_always,
justfile: "b = a\na = `exit 100`\nbar:\n echo '{{`exit 200`}}'",
justfile: "b := a\na := `exit 100`\nbar:\n echo '{{`exit 200`}}'",
args: ("--color", "always"),
stdin: "",
stdout: "",
stderr: "\u{1b}[1;31merror:\u{1b}[0m \u{1b}[1mBacktick failed with exit code 100
\u{1b}[0m |\n2 | a = `exit 100`\n | \u{1b}[1;31m^^^^^^^^^^\u{1b}[0m\n",
\u{1b}[0m |\n2 | a := `exit 100`\n | \u{1b}[1;31m^^^^^^^^^^\u{1b}[0m\n",
status: 100,
}
integration_test! {
name: color_never,
justfile: "b = a\na = `exit 100`\nbar:\n echo '{{`exit 200`}}'",
justfile: "b := a\na := `exit 100`\nbar:\n echo '{{`exit 200`}}'",
args: ("--color", "never"),
stdin: "",
stdout: "",
stderr: "error: Backtick failed with exit code 100
|
2 | a = `exit 100`
2 | a := `exit 100`
| ^^^^^^^^^^
",
status: 100,
@ -1081,13 +1080,13 @@ integration_test! {
integration_test! {
name: color_auto,
justfile: "b = a\na = `exit 100`\nbar:\n echo '{{`exit 200`}}'",
justfile: "b := a\na := `exit 100`\nbar:\n echo '{{`exit 200`}}'",
args: ("--color", "auto"),
stdin: "",
stdout: "",
stderr: "error: Backtick failed with exit code 100
|
2 | a = `exit 100`
2 | a := `exit 100`
| ^^^^^^^^^^
",
status: 100,
@ -1432,9 +1431,9 @@ foo:
integration_test! {
name: test_os_arch_functions_in_expression,
justfile: r#"
a = arch()
o = os()
f = os_family()
a := arch()
o := os()
f := os_family()
foo:
echo {{a}} {{o}} {{f}}
@ -1450,9 +1449,9 @@ foo:
integration_test! {
name: env_var_functions,
justfile: r#"
p = env_var('USER')
b = env_var_or_default('ZADDY', 'HTAP')
x = env_var_or_default('XYZ', 'ABC')
p := env_var('USER')
b := env_var_or_default('ZADDY', 'HTAP')
x := env_var_or_default('XYZ', 'ABC')
foo:
/bin/echo '{{p}}' '{{b}}' '{{x}}'
@ -1468,9 +1467,9 @@ foo:
integration_test! {
name: env_var_functions,
justfile: r#"
p = env_var('USERNAME')
b = env_var_or_default('ZADDY', 'HTAP')
x = env_var_or_default('XYZ', 'ABC')
p := env_var('USERNAME')
b := env_var_or_default('ZADDY', 'HTAP')
x := env_var_or_default('XYZ', 'ABC')
foo:
/bin/echo '{{p}}' '{{b}}' '{{x}}'
@ -1573,7 +1572,7 @@ c: b a
integration_test! {
name: parameter_shadows_variable,
justfile: "FOO = 'hello'\na FOO:",
justfile: "FOO := 'hello'\na FOO:",
args: ("a"),
stdin: "",
stdout: "",
@ -1587,14 +1586,14 @@ integration_test! {
integration_test! {
name: unknown_function_in_assignment,
justfile: r#"foo = foo() + "hello"
justfile: r#"foo := foo() + "hello"
bar:"#,
args: ("bar"),
stdin: "",
stdout: "",
stderr: r#"error: Call to unknown function `foo`
|
1 | foo = foo() + "hello"
1 | foo := foo() + "hello"
| ^^^
"#,
status: EXIT_FAILURE,
@ -1659,13 +1658,13 @@ integration_test! {
integration_test! {
name: duplicate_variable,
justfile: "a = 'hello'\na = 'hello'\nfoo:",
justfile: "a := 'hello'\na := 'hello'\nfoo:",
args: ("foo"),
stdin: "",
stdout: "",
stderr: "error: Variable `a` has multiple definitions
|
2 | a = 'hello'
2 | a := 'hello'
| ^
",
status: EXIT_FAILURE,
@ -1691,7 +1690,7 @@ integration_test! {
args: ("foo"),
stdin: "",
stdout: "",
stderr: "error: Expected name, '+', ':', or '=', but found raw string
stderr: "error: Expected name, '+', ':', or ':=', but found raw string
|
1 | foo 'bar'
| ^^^^^
@ -1729,13 +1728,13 @@ integration_test! {
integration_test! {
name: variable_self_dependency,
justfile: "z = z\na:",
justfile: "z := z\na:",
args: ("a"),
stdin: "",
stdout: "",
stderr: "error: Variable `z` is defined in terms of itself
|
1 | z = z
1 | z := z
| ^
",
status: EXIT_FAILURE,
@ -1743,13 +1742,13 @@ integration_test! {
integration_test! {
name: variable_circular_dependency,
justfile: "x = y\ny = z\nz = x\na:",
justfile: "x := y\ny := z\nz := x\na:",
args: ("a"),
stdin: "",
stdout: "",
stderr: "error: Variable `x` depends on its own value: `x -> y -> z -> x`
|
1 | x = y
1 | x := y
| ^
",
status: EXIT_FAILURE,
@ -1757,14 +1756,14 @@ integration_test! {
integration_test! {
name: invalid_escape_sequence,
justfile: r#"x = "\q"
justfile: r#"x := "\q"
a:"#,
args: ("a"),
stdin: "",
stdout: "",
stderr: "error: `\\q` is not a valid escape sequence
|
1 | x = \"\\q\"
1 | x := \"\\q\"
| ^^^^
",
status: EXIT_FAILURE,
@ -1773,7 +1772,7 @@ a:"#,
integration_test! {
name: multiline_raw_string,
justfile: "
string = 'hello
string := 'hello
whatever'
a:
@ -1793,7 +1792,7 @@ whatever'
integration_test! {
name: error_line_after_multiline_raw_string,
justfile: "
string = 'hello
string := 'hello
whatever' + 'yo'
@ -1814,7 +1813,7 @@ a:
integration_test! {
name: error_column_after_multiline_raw_string,
justfile: "
string = 'hello
string := 'hello
whatever' + bar
@ -2039,7 +2038,7 @@ integration_test! {
name: comment_before_variable,
justfile: "
#
A='1'
A:='1'
echo:
echo {{A}}
",
@ -2068,7 +2067,7 @@ integration_test! {
name: dotenv_variable_in_backtick,
justfile: "
#
X=`echo $DOTENV_KEY`
X:=`echo $DOTENV_KEY`
echo:
echo {{X}}
",
@ -2097,8 +2096,8 @@ integration_test! {
name: dotenv_variable_in_function_in_backtick,
justfile: "
#
X=env_var_or_default('DOTENV_KEY', 'foo')
Y=env_var('DOTENV_KEY')
X:=env_var_or_default('DOTENV_KEY', 'foo')
Y:=env_var('DOTENV_KEY')
echo:
echo {{X}}
echo {{Y}}
@ -2113,14 +2112,14 @@ echo:
integration_test! {
name: invalid_escape_sequence_message,
justfile: r#"
X = "\'"
X := "\'"
"#,
args: (),
stdin: "",
stdout: "",
stderr: r#"error: `\'` is not a valid escape sequence
|
2 | X = "\'"
2 | X := "\'"
| ^^^^
"#,
status: EXIT_FAILURE,
@ -2200,7 +2199,7 @@ foo x=`echo foo`:
integration_test! {
name: default_variable,
justfile: "
y = 'foo'
y := 'foo'
foo x=y:
echo {{x}}
",
@ -2292,7 +2291,7 @@ assembly_source_files = $(wildcard src/arch/$(arch)/*.s)
integration_test! {
name: backtick_variable_cat,
justfile: "
stdin = `cat`
stdin := `cat`
default:
echo {{stdin}}
@ -2338,7 +2337,7 @@ default stdin = `cat justfile`:
integration_test! {
name: backtick_variable_read_single,
justfile: "
password = `read PW && echo $PW`
password := `read PW && echo $PW`
default:
echo {{password}}
@ -2353,8 +2352,8 @@ default:
integration_test! {
name: backtick_variable_read_multiple,
justfile: "
a = `read A && echo $A`
b = `read B && echo $B`
a := `read A && echo $A`
b := `read B && echo $B`
default:
echo {{a}}
@ -2381,3 +2380,63 @@ default a=`read A && echo $A` b=`read B && echo $B`:
stderr: "echo foo\necho bar\n",
status: EXIT_SUCCESS,
}
integration_test! {
name: equals_deprecated_assignment,
justfile: "
foo = 'bar'
default:
echo {{foo}}
",
args: (),
stdin: "",
stdout: "bar\n",
stderr: "warning: `=` in assignments, exports, and aliases is being phased out on favor of `:=`
Please see this issue for more details: https://github.com/casey/just/issues/379
echo bar
",
status: EXIT_SUCCESS,
}
integration_test! {
name: equals_deprecated_export,
justfile: "
export FOO = 'bar'
default:
echo $FOO
",
args: (),
stdin: "",
stdout: "bar\n",
stderr: "warning: `=` in assignments, exports, and aliases is being phased out on favor of `:=`
Please see this issue for more details: https://github.com/casey/just/issues/379
echo $FOO
",
status: EXIT_SUCCESS,
}
integration_test! {
name: equals_deprecated_alias,
justfile: "
alias foo = default
default:
echo default
",
args: ("foo"),
stdin: "",
stdout: "default\n",
stderr: "warning: `=` in assignments, exports, and aliases is being phased out on favor of `:=`
Please see this issue for more details: https://github.com/casey/just/issues/379
echo default
",
status: EXIT_SUCCESS,
}