diff --git a/.buildnumber b/.buildnumber
index 9d607966..3cacc0b9 100644
--- a/.buildnumber
+++ b/.buildnumber
@@ -1 +1 @@
-11
\ No newline at end of file
+12
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8825d0c2..b294bed1 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,13 +1,12 @@
## CHANGELOG
-### v0.10.0
+### v0.10.0 (2024-10-03)
-* Enhancement: Runtime - \[Breaking Change\] New Env struct enabling commands to redirect out/err to provided streams #440
* Enhancement: Runtime - \[Breaking Change\] Commands now get new CommandArgs struct instead of multiple fields.
-* Enhancement: Runtime - Enable to halt execution via env.
### v0.9.4 (2024-09-28)
+* Enhancement: Runtime - \[Breaking Change\] New Env struct enabling commands to redirect out/err to provided streams #440
* Enhancement: Runtime - Adding halt interrupt to env #448 (thanks @nickheyer)
### v0.9.3 (2024-01-19)
diff --git a/Cargo.lock b/Cargo.lock
index 69a0b10d..e8c78ec3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -134,9 +134,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.1.22"
+version = "1.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
+checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938"
dependencies = [
"shlex",
]
@@ -281,14 +281,14 @@ dependencies = [
[[package]]
name = "duckscript"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"fsio",
]
[[package]]
name = "duckscript_cli"
-version = "0.9.4"
+version = "0.10.0"
dependencies = [
"duckscript",
"duckscriptsdk",
@@ -296,7 +296,7 @@ dependencies = [
[[package]]
name = "duckscriptsdk"
-version = "0.9.4"
+version = "0.10.0"
dependencies = [
"attohttpc",
"base64",
@@ -496,9 +496,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.14.5"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]]
name = "heck"
@@ -583,9 +583,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown",
@@ -729,9 +729,12 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.19.0"
+version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1"
+dependencies = [
+ "portable-atomic",
+]
[[package]]
name = "openssl"
@@ -801,6 +804,12 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
+[[package]]
+name = "portable-atomic"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
+
[[package]]
name = "powerfmt"
version = "0.2.0"
@@ -866,18 +875,18 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.6"
+version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
+checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
-version = "1.10.6"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
dependencies = [
"aho-corasick",
"memchr",
@@ -887,9 +896,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
@@ -898,9 +907,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "ring"
@@ -1107,9 +1116,9 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.12.0"
+version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
dependencies = [
"cfg-if",
"fastrand",
@@ -1189,9 +1198,9 @@ dependencies = [
[[package]]
name = "unicode-bidi"
-version = "0.3.15"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
[[package]]
name = "unicode-ident"
diff --git a/README.md b/README.md
index b328d89a..ee9a547a 100644
--- a/README.md
+++ b/README.md
@@ -34,8 +34,8 @@
* [Full SDK Docs](https://github.com/sagiegurari/duckscript/blob/master/docs/sdk.md)
* [Final Notes](#tutorial-final-notes)
* [Duckscript Command Implementation Tutorial](#sdk-tutorial)
- * [Standard Commands](#sdk-tutorial-standard-commands)
- * [Context Commands](#sdk-tutorial-context-commands)
+ * [Commands](#sdk-tutorial-commands)
+ * [Access The Context](#sdk-tutorial-commands-context)
* [Duckscript Embedding Tutorial](#embed-tutorial)
* [Setting Up The Context](#embed-tutorial-setup-context)
* [Running The Script](#embed-tutorial-running)
@@ -401,13 +401,8 @@ If you want to know how to write your own commands or embed the duckscript runti
Want to write new custom commands so you can use them in your duckscripts? great!
Hopefully the following sections will help you gain the basic knowledge on how to write them.
-First of all it is important to understand that there are two types of commands:
-
-* Commands which execute some action like copying files, printing some text to the console or returning an environment variable.
-* Commands which provide flow control or some more complex action and require modifying the internal context in runtime.
-
-
-## Standard Commands
+
+## Commands
Commands are structs that must implement the Command trait.
* They must have a name, which is used to invoke the command.
@@ -415,7 +410,7 @@ Commands are structs that must implement the Command trait.
* They should return help documentation in markdown format in order to generate SDK documentation (must for PRs to duckscript official SDK).
* They must implement the **run** function which holds the command logic.
-The run function accepts the command arguments (variables already replaced to actual values) and returns the command result.
+The run function accepts the command arguments (args array contains actual values and not original variables) and returns the command result.
The command result can be one of the following:
* Continue(Option) - Tells the runner to continue to the next command and optionally set the output variable the given value.
@@ -438,11 +433,15 @@ impl Command for SetCommand {
"set".to_string()
}
- fn run(&self, arguments: Vec) -> CommandResult {
- let output = if arguments.is_empty() {
+ fn clone_and_box(&self) -> Box {
+ Box::new((*self).clone())
+ }
+
+ fn run(&self, arguments: CommandArgs) -> CommandResult {
+ let output = if arguments.args.is_empty() {
None
} else {
- Some(arguments[0].clone())
+ Some(arguments.args[0].clone())
};
CommandResult::Continue(output)
@@ -465,11 +464,15 @@ impl Command for GetEnvCommand {
"get_env".to_string()
}
- fn run(&self, arguments: Vec) -> CommandResult {
- if arguments.is_empty() {
+ fn clone_and_box(&self) -> Box {
+ Box::new((*self).clone())
+ }
+
+ fn run(&self, arguments: CommandArgs) -> CommandResult {
+ if arguments.args.is_empty() {
CommandResult::Error("Missing environment variable name.".to_string())
} else {
- match env::var(&arguments[0]) {
+ match env::var(&arguments.args[0]) {
Ok(value) => CommandResult::Continue(Some(value)),
Err(_) => CommandResult::Continue(None),
}
@@ -480,38 +483,23 @@ impl Command for GetEnvCommand {
You can look at more examples in the duckscript_sdk folder.
-
-## Context Commands
-Context commands are exactly the same as standard commands except that they have access to the runtime context.
-Therefore they implement the same Command trait but this time instead of implementing the run function, they need to implement the following:
-
-* requires_context - Must return true
-* run_with_context - The same logic you would put in the run function but now you have access to a lot more of the runtime context.
-
-The run_with_context signature is as follows:
+
+## Access The Context
+The duckscript runtime context is available in the CommandArgs struc.
```rust
/// Run the instruction with access to the runtime context.
///
-/// # Arguments
-///
-/// * `arguments` - The command arguments array
+/// The CommandArgs has the following members:
+/// * `args` - The command arguments array
/// * `state` - Internal state which is only used by commands to store/pull data
/// * `variables` - All script variables
/// * `output_variable` - The output variable name (if defined)
/// * `instructions` - The entire list of instructions which make up the currently running script
/// * `commands` - The currently known commands
/// * `line` - The current instruction line number (global line number after including all scripts into one global script)
-fn run_with_context(
- &self,
- arguments: Vec,
- state: &mut HashMap,
- variables: &mut HashMap,
- output_variable: Option,
- instructions: &Vec,
- commands: &mut Commands,
- line: usize,
-) -> CommandResult;
+/// * `env` - The current runtime env with access to out/err writers, etc...
+fn run(&self, arguments: CommandArgs) -> CommandResult;
```
With access to this context you can add/remove/switch commands in runtime, store/pull internal state, add/remove/change variables and so on...
@@ -524,7 +512,7 @@ The duckscript cli basically embeds duckscript so you can look at it as a refere
```rust
let mut context = Context::new();
duckscriptsdk::load(&mut context.commands)?;
-runner::run_script_file(file, context)?;
+runner::run_script_file(file, context, None)?;
```
That's it!
@@ -547,10 +535,10 @@ The following public functions are available:
```rust
/// Executes the provided script with the given context
-pub fn run_script(text: &str, context: Context) -> Result;
+pub fn run_script(text: &str, context: Context, env: Option) -> Result;
/// Executes the provided script file with the given context
-pub fn run_script_file(file: &str, context: Context) -> Result;
+pub fn run_script_file(file: &str, context: Context, env: Option) -> Result;
```
diff --git a/duckscript/Cargo.toml b/duckscript/Cargo.toml
index e588900f..ee5332d9 100644
--- a/duckscript/Cargo.toml
+++ b/duckscript/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "duckscript"
-version = "0.8.1"
+version = "0.9.0"
authors = ["Sagie Gur-Ari "]
description = "Simple, extendable and embeddable scripting language."
license = "Apache-2.0"
diff --git a/duckscript_cli/Cargo.toml b/duckscript_cli/Cargo.toml
index 519ed440..80cb8aff 100644
--- a/duckscript_cli/Cargo.toml
+++ b/duckscript_cli/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "duckscript_cli"
-version = "0.9.4"
+version = "0.10.0"
authors = ["Sagie Gur-Ari "]
description = "The duckscript command line executable."
license = "Apache-2.0"
@@ -27,8 +27,8 @@ name = "duck"
path = "src/main.rs"
[dependencies]
-duckscript = { version = "^0.8.1", path = "../duckscript" }
-duckscriptsdk = { version = "^0.9.4", path = "../duckscript_sdk", default-features = false }
+duckscript = { version = "^0.9.0", path = "../duckscript" }
+duckscriptsdk = { version = "^0.10.0", path = "../duckscript_sdk", default-features = false }
[features]
tls-rustls = ["duckscriptsdk/tls-rustls"]
diff --git a/duckscript_sdk/Cargo.toml b/duckscript_sdk/Cargo.toml
index f4492b04..829731d3 100644
--- a/duckscript_sdk/Cargo.toml
+++ b/duckscript_sdk/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "duckscriptsdk"
-version = "0.9.4"
+version = "0.10.0"
authors = ["Sagie Gur-Ari "]
description = "The duckscript SDK."
license = "Apache-2.0"
@@ -29,7 +29,7 @@ attohttpc = { version = "^0.28", default-features = false, features = [
base64 = "^0.22"
cfg-if = "^1"
colored = "^2"
-duckscript = { version = "^0.8.1", path = "../duckscript" }
+duckscript = { version = "^0.9.0", path = "../duckscript" }
evalexpr = "^11"
fs_extra = "^1"
fsio = { version = "^0.4", features = ["temp-path"] }