diff --git a/CHANGELOG.md b/CHANGELOG.md index 3332de9..1921621 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### v0.1.9 +* New split command #76 * New appendfile command. * New watchdog command. * New pid command #73 diff --git a/docs/sdk.md b/docs/sdk.md index cd08574..c6116af 100644 --- a/docs/sdk.md +++ b/docs/sdk.md @@ -75,6 +75,7 @@ * [std::string::LastIndexOf (last_indexof)](#std__string__LastIndexOf) * [std::string::Length (length, strlen)](#std__string__Length) * [std::string::Replace (replace)](#std__string__Replace) +* [std::string::Split (split)](#std__string__Split) * [std::string::StartsWith (starts_with)](#std__string__StartsWith) * [std::string::SubString (substring)](#std__string__SubString) * [std::string::Trim (trim)](#std__string__Trim) @@ -2780,6 +2781,51 @@ assert_eq ${updated} "my large stuff value with lots of stuff" #### Aliases: replace + +## std::string::Split +```sh +handle = split text pattern +``` + +Splits the provided text based on the provided pattern and return a handle the +created array with all the splitted values. + +#### Parameters + +* The text to split +* The pattern to split by + +#### Return Value + +A handle to the values array. + +#### Examples + +```sh +handle = split a23b23c23d23e 23 + +len = array_length ${handle} + +value = array_pop ${handle} +assert_eq ${value} e +value = array_pop ${handle} +assert_eq ${value} d +value = array_pop ${handle} +assert_eq ${value} c +value = array_pop ${handle} +assert_eq ${value} b +value = array_pop ${handle} +assert_eq ${value} a + +release ${handle} + +assert_eq ${len} 5 +``` + + +#### Aliases: +split + ## std::string::StartsWith ```sh diff --git a/duckscript_sdk/src/sdk/std/string/mod.rs b/duckscript_sdk/src/sdk/std/string/mod.rs index df7ed4a..b86d2c5 100755 --- a/duckscript_sdk/src/sdk/std/string/mod.rs +++ b/duckscript_sdk/src/sdk/std/string/mod.rs @@ -7,6 +7,7 @@ mod is_empty; mod last_indexof; mod length; mod replace; +mod split; mod starts_with; mod substring; mod trim; @@ -31,6 +32,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr commands.set(last_indexof::create(&package))?; commands.set(length::create(&package))?; commands.set(replace::create(&package))?; + commands.set(split::create(&package))?; commands.set(starts_with::create(&package))?; commands.set(substring::create(&package))?; commands.set(trim::create(&package))?; diff --git a/duckscript_sdk/src/sdk/std/string/split/help.md b/duckscript_sdk/src/sdk/std/string/split/help.md new file mode 100644 index 0000000..a327931 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/split/help.md @@ -0,0 +1,38 @@ +```sh +handle = split text pattern +``` + +Splits the provided text based on the provided pattern and return a handle the +created array with all the splitted values. + +#### Parameters + +* The text to split +* The pattern to split by + +#### Return Value + +A handle to the values array. + +#### Examples + +```sh +handle = split a23b23c23d23e 23 + +len = array_length ${handle} + +value = array_pop ${handle} +assert_eq ${value} e +value = array_pop ${handle} +assert_eq ${value} d +value = array_pop ${handle} +assert_eq ${value} c +value = array_pop ${handle} +assert_eq ${value} b +value = array_pop ${handle} +assert_eq ${value} a + +release ${handle} + +assert_eq ${len} 5 +``` diff --git a/duckscript_sdk/src/sdk/std/string/split/mod.rs b/duckscript_sdk/src/sdk/std/string/split/mod.rs new file mode 100755 index 0000000..84bbf69 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/split/mod.rs @@ -0,0 +1,70 @@ +use crate::utils::pckg; +use crate::utils::state::put_handle; +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, "Split") + } + + fn aliases(&self) -> Vec { + vec!["split".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.len() < 2 { + CommandResult::Error("Invalid input provided.".to_string()) + } else { + let split = arguments[0].split(&arguments[1]); + let values = split.collect::>(); + + let mut array = vec![]; + for value in values { + array.push(StateValue::String(value.to_string())); + } + + let key = put_handle(state, StateValue::List(array)); + + CommandResult::Continue(Some(key)) + } + } +} + +pub(crate) fn create(package: &str) -> Box { + Box::new(CommandImpl { + package: package.to_string(), + }) +} diff --git a/duckscript_sdk/src/sdk/std/string/split/mod_test.rs b/duckscript_sdk/src/sdk/std/string/split/mod_test.rs new file mode 100644 index 0000000..6ea119a --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/split/mod_test.rs @@ -0,0 +1,52 @@ +use super::*; +use crate::test; +use crate::test::CommandValidation; +use crate::utils::state::get_handles_sub_state; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = split", "out"); +} + +#[test] +fn run_single_arg() { + test::run_script_and_error(vec![create("")], "out = split abc", "out"); +} + +#[test] +fn run_split() { + let mut context = test::run_script_and_validate( + vec![create("")], + r#"out = split "a b c" " ""#, + CommandValidation::Ignore, + ); + + let state = get_handles_sub_state(&mut context.state); + let list_value = state.remove(context.variables.get("out").unwrap()).unwrap(); + match list_value { + StateValue::List(mut list) => { + assert_eq!(list.len(), 3); + + match list.pop().unwrap() { + StateValue::String(value) => assert_eq!(value, "c"), + _ => panic!("Invalid handle value."), + }; + + match list.pop().unwrap() { + StateValue::String(value) => assert_eq!(value, "b"), + _ => panic!("Invalid handle value."), + }; + + match list.pop().unwrap() { + StateValue::String(value) => assert_eq!(value, "a"), + _ => panic!("Invalid handle value."), + }; + } + _ => panic!("Invalid type."), + } +} diff --git a/duckscript_sdk/src/test/mod.rs b/duckscript_sdk/src/test/mod.rs index f3faafc..513225a 100644 --- a/duckscript_sdk/src/test/mod.rs +++ b/duckscript_sdk/src/test/mod.rs @@ -168,6 +168,7 @@ pub(crate) enum CommandValidation { Match(String, String), Contains(String, String), Any(String, Vec), + Ignore, } pub(crate) fn test_common_command_functions(command: Box) { @@ -269,6 +270,9 @@ pub(crate) fn run_script_and_validate( let numeric_value: u128 = var_value.parse().unwrap(); assert!(numeric_value > 0) } + CommandValidation::Ignore => { + assert!(!context.variables.is_empty()); + } }; context diff --git a/test/std/string/split_test.ds b/test/std/string/split_test.ds new file mode 100644 index 0000000..3bfe439 --- /dev/null +++ b/test/std/string/split_test.ds @@ -0,0 +1,72 @@ + +function test_empty_string + handle = split "" \n + + len = array_length ${handle} + + value = array_pop ${handle} + assert_eq ${value} "" + + release ${handle} + + assert_eq ${len} 1 +end + +function test_not_found + handle = split 12345 6 + + len = array_length ${handle} + + value = array_pop ${handle} + assert_eq ${value} 12345 + + release ${handle} + + assert_eq ${len} 1 +end + +function test_found + handle = split a23b23c23d23e 23 + + len = array_length ${handle} + + value = array_pop ${handle} + assert_eq ${value} e + value = array_pop ${handle} + assert_eq ${value} d + value = array_pop ${handle} + assert_eq ${value} c + value = array_pop ${handle} + assert_eq ${value} b + value = array_pop ${handle} + assert_eq ${value} a + + release ${handle} + + assert_eq ${len} 5 +end + +function test_found_at_start_and_end + handle = split 23a23b23c23d23e23 23 + + len = array_length ${handle} + + value = array_pop ${handle} + assert_eq ${value} "" + value = array_pop ${handle} + assert_eq ${value} e + value = array_pop ${handle} + assert_eq ${value} d + value = array_pop ${handle} + assert_eq ${value} c + value = array_pop ${handle} + assert_eq ${value} b + value = array_pop ${handle} + assert_eq ${value} a + value = array_pop ${handle} + assert_eq ${value} "" + + release ${handle} + + assert_eq ${len} 7 +end