Allow shebang lines so justfiles can be used as scripts (#393)

This commit is contained in:
Casey Rodarmor 2019-04-08 14:28:17 -07:00 committed by GitHub
parent cee9ac21e0
commit 37639d68d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 40 deletions

View File

@ -653,6 +653,27 @@ $ just foo/build
$ just foo/ $ just foo/
``` ```
=== Just Scripts
By adding a shebang line to the top of a justfile and making it executable, `just` can be used as an interpreter for scripts:
```sh
$ cat > script <<EOF
#!/usr/bin/env just --justfile
foo:
echo foo
EOF
$ chmod +x script
$ ./script foo
echo foo
foo
```
When a script with a shebang is executed, the system supplies the path to the script as an argument to the command in the shebang. So, with a shebang of `#!/usr/bin/env just --justfile`, the command will be `/usr/bin/env just --justfile PATH_TO_SCRIPT`.
With the above shebang, `just` will change its working directory to the location of the script. If you'd rather leave the working directory unchanged, use `#!/usr/bin/env just --working-directory . --justfile`.
== Frequently Asked Questions == Frequently Asked Questions
=== What are the idiosyncrasies of make that just avoids? === What are the idiosyncrasies of make that just avoids?

4
justfile Normal file → Executable file
View File

@ -1,3 +1,7 @@
#!/usr/bin/env just --justfile
# ^ 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

View File

@ -62,7 +62,6 @@ pub enum CompilationErrorKind<'a> {
MixedLeadingWhitespace { MixedLeadingWhitespace {
whitespace: &'a str, whitespace: &'a str,
}, },
OuterShebang,
ParameterFollowsVariadicParameter { ParameterFollowsVariadicParameter {
parameter: &'a str, parameter: &'a str,
}, },
@ -229,9 +228,6 @@ impl<'a> Display for CompilationError<'a> {
show_whitespace(found) show_whitespace(found)
)?; )?;
} }
OuterShebang => {
writeln!(f, "`#!` is reserved syntax outside of recipes")?;
}
UnknownDependency { recipe, unknown } => { UnknownDependency { recipe, unknown } => {
writeln!( writeln!(
f, f,

View File

@ -135,7 +135,7 @@ impl<'a> Lexer<'a> {
static ref BACKTICK: Regex = token(r"`[^`\n\r]*`"); static ref BACKTICK: Regex = token(r"`[^`\n\r]*`");
static ref COLON: Regex = token(r":"); static ref COLON: Regex = token(r":");
static ref COMMA: Regex = token(r","); static ref COMMA: Regex = token(r",");
static ref COMMENT: Regex = token(r"#([^!\n\r][^\n\r]*)?\r?$"); static ref COMMENT: Regex = token(r"#([^\n\r][^\n\r]*)?\r?$");
static ref EOF: Regex = token(r"\z"); static ref EOF: Regex = token(r"\z");
static ref EOL: Regex = token(r"\n|\r\n"); static ref EOL: Regex = token(r"\n|\r\n");
static ref EQUALS: Regex = token(r"="); static ref EQUALS: Regex = token(r"=");
@ -322,8 +322,6 @@ impl<'a> Lexer<'a> {
return Err(self.error(UnterminatedString)); return Err(self.error(UnterminatedString));
} }
(prefix, &self.rest[start..content_end + 1], StringToken) (prefix, &self.rest[start..content_end + 1], StringToken)
} else if self.rest.starts_with("#!") {
return Err(self.error(OuterShebang));
} else { } else {
return Err(self.error(UnknownStartOfToken)); return Err(self.error(UnknownStartOfToken));
}; };
@ -340,7 +338,7 @@ impl<'a> Lexer<'a> {
_ => { _ => {
return Err(last.error(Internal { return Err(last.error(Internal {
message: format!("zero length token: {:?}", last), message: format!("zero length token: {:?}", last),
})) }));
} }
} }
} }
@ -647,16 +645,6 @@ c: b
kind: InconsistentLeadingWhitespace{expected: "\t\t", found: "\t "}, kind: InconsistentLeadingWhitespace{expected: "\t\t", found: "\t "},
} }
error_test! {
name: tokenize_outer_shebang,
input: "#!/usr/bin/env bash",
index: 0,
line: 0,
column: 0,
width: None,
kind: OuterShebang,
}
error_test! { error_test! {
name: tokenize_unknown, name: tokenize_unknown,
input: "~", input: "~",

View File

@ -578,28 +578,6 @@ wut:
status: EXIT_SUCCESS, status: EXIT_SUCCESS,
} }
integration_test! {
name: outer_shebang,
justfile: r#"#!/lol/wut
export FOO = "a"
baz = "c"
export BAR = "b"
export ABC = FOO + BAR + baz
wut:
#!/bin/sh
echo $FOO $BAR $ABC
"#,
args: (),
stdout: "",
stderr: "error: `#!` is reserved syntax outside of recipes
|
1 | #!/lol/wut
| ^
",
status: EXIT_FAILURE,
}
integration_test! { integration_test! {
name: export_shebang, name: export_shebang,
justfile: r#" justfile: r#"