diff --git a/CHANGELOG.md b/CHANGELOG.md
index 727c796..4d87ae9 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
### v0.1.9
+* New array_push command.
* New concat command.
* Improve wget input parsing
diff --git a/docs/sdk.md b/docs/sdk.md
index 8e1853d..c046a88 100644
--- a/docs/sdk.md
+++ b/docs/sdk.md
@@ -18,6 +18,7 @@
* [std::collections::ArrayIsEmpty (array_is_empty)](#std__collections__ArrayIsEmpty)
* [std::collections::ArrayLength (array_length, arrlen)](#std__collections__ArrayLength)
* [std::collections::ArrayPop (array_pop)](#std__collections__ArrayPop)
+* [std::collections::ArrayPush (array_push)](#std__collections__ArrayPush)
* [std::collections::IsArray (is_array)](#std__collections__IsArray)
* [std::collections::Range (range)](#std__collections__Range)
* [std::collections::ReadProperties (read_properties)](#std__collections__ReadProperties)
@@ -834,6 +835,35 @@ assert_eq ${last_element} 3
#### Aliases:
array_pop
+
+## std::collections::ArrayPush
+```sh
+var = array_push handle value
+```
+
+Pushes an additional value to an existing array.
+
+#### Parameters
+
+The array handle.
+
+#### Return Value
+
+True if a new value was pushed.
+
+#### Examples
+
+```sh
+handle = array 1 2 3
+array_push ${handle} 4
+last_element = array_pop ${handle}
+assert_eq ${last_element} 4
+```
+
+
+#### Aliases:
+array_push
+
## std::collections::IsArray
```sh
diff --git a/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs b/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs
index 1f1d6d5..71510df 100755
--- a/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs
+++ b/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs
@@ -93,7 +93,42 @@ impl Command for CommandImpl {
None => CommandResult::Continue(None),
}
}
- _ => CommandResult::Error("Invalid handle provided.".to_string()),
+ StateValue::Boolean(value) => {
+ state.insert(key.to_string(), StateValue::Boolean(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::Number(value) => {
+ state.insert(key.to_string(), StateValue::Number(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::UnsignedNumber(value) => {
+ state.insert(key.to_string(), StateValue::UnsignedNumber(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::Number32Bit(value) => {
+ state.insert(key.to_string(), StateValue::Number32Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::UnsignedNumber32Bit(value) => {
+ state.insert(key.to_string(), StateValue::UnsignedNumber32Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::Number64Bit(value) => {
+ state.insert(key.to_string(), StateValue::Number64Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::UnsignedNumber64Bit(value) => {
+ state.insert(key.to_string(), StateValue::UnsignedNumber64Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::String(value) => {
+ state.insert(key.to_string(), StateValue::String(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::SubState(value) => {
+ state.insert(key.to_string(), StateValue::SubState(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
},
None => CommandResult::Error(
format!("Array for handle: {} not found.", key).to_string(),
diff --git a/duckscript_sdk/src/sdk/std/collections/array_push/help.md b/duckscript_sdk/src/sdk/std/collections/array_push/help.md
new file mode 100644
index 0000000..eb2ac84
--- /dev/null
+++ b/duckscript_sdk/src/sdk/std/collections/array_push/help.md
@@ -0,0 +1,22 @@
+```sh
+var = array_push handle value
+```
+
+Pushes an additional value to an existing array.
+
+#### Parameters
+
+The array handle.
+
+#### Return Value
+
+True if a new value was pushed.
+
+#### Examples
+
+```sh
+handle = array 1 2 3
+array_push ${handle} 4
+last_element = array_pop ${handle}
+assert_eq ${last_element} 4
+```
diff --git a/duckscript_sdk/src/sdk/std/collections/array_push/mod.rs b/duckscript_sdk/src/sdk/std/collections/array_push/mod.rs
new file mode 100755
index 0000000..3f183cc
--- /dev/null
+++ b/duckscript_sdk/src/sdk/std/collections/array_push/mod.rs
@@ -0,0 +1,120 @@
+use crate::utils::pckg;
+use crate::utils::state::get_handles_sub_state;
+use duckscript::types::command::{Command, CommandResult, Commands};
+use duckscript::types::instruction::Instruction;
+use duckscript::types::runtime::StateValue;
+use std::collections::HashMap;
+
+#[cfg(test)]
+#[path = "./mod_test.rs"]
+mod mod_test;
+
+#[derive(Clone)]
+pub(crate) struct CommandImpl {
+ package: String,
+}
+
+impl Command for CommandImpl {
+ fn name(&self) -> String {
+ pckg::concat(&self.package, "ArrayPush")
+ }
+
+ fn aliases(&self) -> Vec {
+ vec!["array_push".to_string()]
+ }
+
+ fn help(&self) -> String {
+ include_str!("help.md").to_string()
+ }
+
+ fn clone_and_box(&self) -> Box {
+ Box::new((*self).clone())
+ }
+
+ fn requires_context(&self) -> bool {
+ true
+ }
+
+ fn run_with_context(
+ &self,
+ arguments: Vec,
+ state: &mut HashMap,
+ _variables: &mut HashMap,
+ _output_variable: Option,
+ _instructions: &Vec,
+ _commands: &mut Commands,
+ _line: usize,
+ ) -> CommandResult {
+ if arguments.is_empty() {
+ CommandResult::Error("Array handle not provided.".to_string())
+ } else {
+ let state = get_handles_sub_state(state);
+
+ let key = &arguments[0];
+
+ match state.remove(key) {
+ Some(state_value) => match state_value {
+ StateValue::List(mut list) => {
+ let mut skip = true;
+ for argument in &arguments {
+ if skip {
+ skip = false;
+ } else {
+ list.push(StateValue::String(argument.to_string()))
+ }
+ }
+
+ state.insert(key.to_string(), StateValue::List(list));
+
+ CommandResult::Continue(Some("true".to_string()))
+ }
+ StateValue::Boolean(value) => {
+ state.insert(key.to_string(), StateValue::Boolean(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::Number(value) => {
+ state.insert(key.to_string(), StateValue::Number(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::UnsignedNumber(value) => {
+ state.insert(key.to_string(), StateValue::UnsignedNumber(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::Number32Bit(value) => {
+ state.insert(key.to_string(), StateValue::Number32Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::UnsignedNumber32Bit(value) => {
+ state.insert(key.to_string(), StateValue::UnsignedNumber32Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::Number64Bit(value) => {
+ state.insert(key.to_string(), StateValue::Number64Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::UnsignedNumber64Bit(value) => {
+ state.insert(key.to_string(), StateValue::UnsignedNumber64Bit(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::String(value) => {
+ state.insert(key.to_string(), StateValue::String(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ StateValue::SubState(value) => {
+ state.insert(key.to_string(), StateValue::SubState(value));
+ CommandResult::Error("Invalid handle provided.".to_string())
+ }
+ },
+ None => CommandResult::Error(
+ format!("Array for handle: {} not found.", key).to_string(),
+ ),
+ }
+ }
+ }
+}
+
+pub(crate) fn create(package: &str) -> Box {
+ Box::new(CommandImpl {
+ package: package.to_string(),
+ })
+}
diff --git a/duckscript_sdk/src/sdk/std/collections/array_push/mod_test.rs b/duckscript_sdk/src/sdk/std/collections/array_push/mod_test.rs
new file mode 100644
index 0000000..511b86e
--- /dev/null
+++ b/duckscript_sdk/src/sdk/std/collections/array_push/mod_test.rs
@@ -0,0 +1,50 @@
+use super::*;
+use crate::sdk::std::collections::{array, array_pop};
+use crate::test;
+use crate::test::CommandValidation;
+
+#[test]
+fn common_functions() {
+ test::test_common_command_functions(create(""));
+}
+
+#[test]
+fn run_no_args() {
+ test::run_script_and_error(vec![create("")], "out = array_push", "out");
+}
+
+#[test]
+fn run_not_found() {
+ test::run_script_and_error(vec![create("")], "out = array_push bad_handle 1", "out");
+}
+
+#[test]
+fn run_only_array_not_found() {
+ test::run_script_and_error(vec![create("")], "out = array_push bad_handle", "out");
+}
+
+#[test]
+fn run_found_no_input() {
+ test::run_script_and_validate(
+ vec![create(""), array::create(""), array_pop::create("")],
+ r#"
+ handle = array 1 2 3
+ array_push ${handle}
+ out = array_pop ${handle}
+ "#,
+ CommandValidation::Match("out".to_string(), "3".to_string()),
+ );
+}
+
+#[test]
+fn run_found() {
+ test::run_script_and_validate(
+ vec![create(""), array::create(""), array_pop::create("")],
+ r#"
+ handle = array 1 2 3
+ array_push ${handle} 4
+ out = array_pop ${handle}
+ "#,
+ CommandValidation::Match("out".to_string(), "4".to_string()),
+ );
+}
diff --git a/duckscript_sdk/src/sdk/std/collections/mod.rs b/duckscript_sdk/src/sdk/std/collections/mod.rs
index 80b2e15..fb93335 100755
--- a/duckscript_sdk/src/sdk/std/collections/mod.rs
+++ b/duckscript_sdk/src/sdk/std/collections/mod.rs
@@ -1,7 +1,8 @@
pub(crate) mod array;
mod array_is_empty;
pub(crate) mod array_length;
-mod array_pop;
+pub(crate) mod array_pop;
+mod array_push;
mod is_array;
mod range;
mod read_properties;
@@ -17,6 +18,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
let package = pckg::concat(parent, PACKAGE);
commands.set(array::create(&package))?;
+ commands.set(array_push::create(&package))?;
commands.set(array_is_empty::create(&package)?)?;
commands.set(array_length::create(&package))?;
commands.set(array_pop::create(&package))?;
diff --git a/test/std/collections/array_push_test.ds b/test/std/collections/array_push_test.ds
new file mode 100644
index 0000000..773f9e5
--- /dev/null
+++ b/test/std/collections/array_push_test.ds
@@ -0,0 +1,51 @@
+
+function test_array_with_data
+ arr = array a
+ counter = range 1 4
+ for index in ${counter}
+ array_push ${arr} ${index}
+ end
+
+ last_element = array_pop ${arr}
+ assert_eq ${last_element} 3
+
+ last_element = array_pop ${arr}
+ assert_eq ${last_element} 2
+
+ last_element = array_pop ${arr}
+ assert_eq ${last_element} 1
+
+ last_element = array_pop ${arr}
+ assert_eq ${last_element} a
+
+ last_element = array_pop ${arr}
+ defined = is_defined last_element
+ assert_false ${defined}
+
+ released = release ${arr}
+ assert ${released}
+end
+
+function test_array_empty
+ arr = array
+ counter = range 1 4
+ for index in ${counter}
+ array_push ${arr} ${index}
+ end
+
+ last_element = array_pop ${arr}
+ assert_eq ${last_element} 3
+
+ last_element = array_pop ${arr}
+ assert_eq ${last_element} 2
+
+ last_element = array_pop ${arr}
+ assert_eq ${last_element} 1
+
+ last_element = array_pop ${arr}
+ defined = is_defined last_element
+ assert_false ${defined}
+
+ released = release ${arr}
+ assert ${released}
+end