Support shebangs in scripts.
This commit is contained in:
parent
ea970631ff
commit
7825cb1c56
@ -32,6 +32,8 @@ Breaking changes
|
|||||||
* `protected`, `super` are now reserved keywords.
|
* `protected`, `super` are now reserved keywords.
|
||||||
* The `Module::set_fn_XXX` API now take `&str` as the function name instead of `Into<String>`.
|
* The `Module::set_fn_XXX` API now take `&str` as the function name instead of `Into<String>`.
|
||||||
* The _reflections_ API such as `Engine::gen_fn_signatures`, `Module::update_fn_metadata` etc. are put under the `metadata` feature gate.
|
* The _reflections_ API such as `Engine::gen_fn_signatures`, `Module::update_fn_metadata` etc. are put under the `metadata` feature gate.
|
||||||
|
* The shebang `#!` is now a reserved symbol.
|
||||||
|
* Shebangs at the very beginning of script files are skipped when loading them.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
@ -39,6 +41,7 @@ Enhancements
|
|||||||
* Replaced all `HashMap` usage with `BTreeMap` for better performance because collections in Rhai are tiny.
|
* Replaced all `HashMap` usage with `BTreeMap` for better performance because collections in Rhai are tiny.
|
||||||
* `Engine::register_result_fn` no longer requires the successful return type to be `Dynamic`. It can now be any clonable type.
|
* `Engine::register_result_fn` no longer requires the successful return type to be `Dynamic`. It can now be any clonable type.
|
||||||
* `#[rhai_fn(return_raw)]` can now return `Result<T, Box<EvalAltResult>>` where `T` is any clonable type instead of `Result<Dynamic, Box<EvalAltResult>>`.
|
* `#[rhai_fn(return_raw)]` can now return `Result<T, Box<EvalAltResult>>` where `T` is any clonable type instead of `Result<Dynamic, Box<EvalAltResult>>`.
|
||||||
|
* Rhai scripts can now start with a shebang `#!`.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.14
|
Version 0.19.14
|
||||||
|
@ -58,13 +58,20 @@ fn main() {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = engine.consume(&contents) {
|
let contents = if contents.starts_with("#!") {
|
||||||
|
// Skip shebang
|
||||||
|
&contents[contents.find('\n').unwrap_or(0)..]
|
||||||
|
} else {
|
||||||
|
&contents[..]
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(err) = engine.consume(contents) {
|
||||||
eprintln!("{:=<1$}", "", filename.len());
|
eprintln!("{:=<1$}", "", filename.len());
|
||||||
eprintln!("{}", filename);
|
eprintln!("{}", filename);
|
||||||
eprintln!("{:=<1$}", "", filename.len());
|
eprintln!("{:=<1$}", "", filename.len());
|
||||||
eprintln!("");
|
eprintln!("");
|
||||||
|
|
||||||
eprint_error(&contents, *err);
|
eprint_error(contents, *err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1185,6 +1185,15 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
if contents.starts_with("#!") {
|
||||||
|
// Remove shebang
|
||||||
|
if let Some(n) = contents.find('\n') {
|
||||||
|
contents.drain(0..n).count();
|
||||||
|
} else {
|
||||||
|
contents.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
/// Compile a script file into an [`AST`], which can be used later for evaluation.
|
/// Compile a script file into an [`AST`], which can be used later for evaluation.
|
||||||
|
15
src/token.rs
15
src/token.rs
@ -587,11 +587,13 @@ impl Token {
|
|||||||
#[cfg(feature = "no_module")]
|
#[cfg(feature = "no_module")]
|
||||||
"import" | "export" | "as" => Reserved(syntax.into()),
|
"import" | "export" | "as" => Reserved(syntax.into()),
|
||||||
|
|
||||||
"===" | "!==" | "->" | "<-" | ":=" | "~" | "::<" | "(*" | "*)" | "#" | "public"
|
"===" | "!==" | "->" | "<-" | ":=" | "~" | "::<" | "(*" | "*)" | "#" | "#!"
|
||||||
| "protected" | "super" | "new" | "use" | "module" | "package" | "var" | "static"
|
| "public" | "protected" | "super" | "new" | "use" | "module" | "package" | "var"
|
||||||
| "begin" | "end" | "shared" | "with" | "each" | "then" | "goto" | "unless"
|
| "static" | "begin" | "end" | "shared" | "with" | "each" | "then" | "goto"
|
||||||
| "exit" | "match" | "case" | "default" | "void" | "null" | "nil" | "spawn"
|
| "unless" | "exit" | "match" | "case" | "default" | "void" | "null" | "nil"
|
||||||
| "thread" | "go" | "sync" | "async" | "await" | "yield" => Reserved(syntax.into()),
|
| "spawn" | "thread" | "go" | "sync" | "async" | "await" | "yield" => {
|
||||||
|
Reserved(syntax.into())
|
||||||
|
}
|
||||||
|
|
||||||
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
|
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
|
||||||
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_THIS | KEYWORD_IS_DEF_VAR => {
|
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_THIS | KEYWORD_IS_DEF_VAR => {
|
||||||
@ -1323,6 +1325,9 @@ fn get_next_token_inner(
|
|||||||
eat_next(stream, pos);
|
eat_next(stream, pos);
|
||||||
return Some((Token::MapStart, start_pos));
|
return Some((Token::MapStart, start_pos));
|
||||||
}
|
}
|
||||||
|
// Shebang
|
||||||
|
('#', '!') => return Some((Token::Reserved("#!".into()), start_pos)),
|
||||||
|
|
||||||
('#', _) => return Some((Token::Reserved("#".into()), start_pos)),
|
('#', _) => return Some((Token::Reserved("#".into()), start_pos)),
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
|
Loading…
Reference in New Issue
Block a user