From 3101ae03e30c25bd6ce7d4ffc7dfab3c266cf022 Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Fri, 17 Jan 2020 10:39:50 +0000 Subject: [PATCH] New properties read/write commands #61 --- CHANGELOG.md | 1 + docs/sdk.md | 68 +++++++++++++++++ duckscript_sdk/Cargo.toml | 1 + duckscript_sdk/src/sdk/std/collections/mod.rs | 4 + .../std/collections/read_properties/help.md | 25 +++++++ .../std/collections/read_properties/mod.rs | 64 ++++++++++++++++ .../collections/read_properties/mod_test.rs | 28 +++++++ .../std/collections/write_properties/help.md | 27 +++++++ .../std/collections/write_properties/mod.rs | 73 +++++++++++++++++++ .../collections/write_properties/mod_test.rs | 26 +++++++ test/std/collections/read_properties_test.ds | 9 +++ test/std/collections/write_properties_test.ds | 22 ++++++ 12 files changed, 348 insertions(+) create mode 100644 duckscript_sdk/src/sdk/std/collections/read_properties/help.md create mode 100755 duckscript_sdk/src/sdk/std/collections/read_properties/mod.rs create mode 100644 duckscript_sdk/src/sdk/std/collections/read_properties/mod_test.rs create mode 100644 duckscript_sdk/src/sdk/std/collections/write_properties/help.md create mode 100755 duckscript_sdk/src/sdk/std/collections/write_properties/mod.rs create mode 100644 duckscript_sdk/src/sdk/std/collections/write_properties/mod_test.rs create mode 100644 test/std/collections/read_properties_test.ds create mode 100644 test/std/collections/write_properties_test.ds diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ecffd7..add7165 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Fixed runner to return an error if on_error requested crash or exit and not just end the script. * Unalias can remove aliases not created from the alias command. +* New properties read/write commands #61 ### v0.1.6 (2020-01-12) diff --git a/docs/sdk.md b/docs/sdk.md index cfcb319..e724868 100644 --- a/docs/sdk.md +++ b/docs/sdk.md @@ -18,6 +18,8 @@ * [std::collections::ArrayIsEmpty (array_is_empty)](#std__collections__ArrayIsEmpty) * [std::collections::ArrayLength (array_length, arrlen)](#std__collections__ArrayLength) * [std::collections::Range (range)](#std__collections__Range) +* [std::collections::ReadProperties (read_properties)](#std__collections__ReadProperties) +* [std::collections::WriteProperties (write_properties)](#std__collections__WriteProperties) * [std::env::GetVar (get_env)](#std__env__GetVar) * [std::env::PrintCurrentDirectory (pwd)](#std__env__PrintCurrentDirectory) * [std::env::SetCurrentDirectory (cd, set_current_dir)](#std__env__SetCurrentDirectory) @@ -797,6 +799,72 @@ release ${handle} #### Aliases: range + +## std::collections::ReadProperties +```sh +count = read_properties text +``` + +Parses the properties (based on java properties format) text and sets them as variables.
+This command will also return the count of properties read. + +#### Parameters + +The text to parse. + +#### Return Value + +The properties count. + +#### Examples + +```sh +count = read_properties "a=1\nb=2\na.b.c=3" +assert_eq ${count} 3 + +assert_eq ${a} 1 +assert_eq ${b} 2 +assert_eq ${a.b.c} 3 +``` + + +#### Aliases: +read_properties + + +## std::collections::WriteProperties +```sh +text = write_properties [names] +``` + +Creates a properties string from the provided list of variable names (not values). + +#### Parameters + +A list of variable names. + +#### Return Value + +The properties text value. + +#### Examples + +```sh +a = set 1 +b = set 2 +a.b.c = set 3 + +# text will be equal to: +# a=1 +# b=2 +# a.b.c=3 +text = write_properties a b a.b.c +``` + + +#### Aliases: +write_properties + ## std::env::GetVar ```sh diff --git a/duckscript_sdk/Cargo.toml b/duckscript_sdk/Cargo.toml index 8395cbd..bd65678 100644 --- a/duckscript_sdk/Cargo.toml +++ b/duckscript_sdk/Cargo.toml @@ -27,6 +27,7 @@ duckscript = { version = "^0.1.5", path = "../duckscript" } fs_extra = "^1" home = "^0.5" hostname = "^0.3" +java-properties = "^1" meval = "^0.2" rand = "^0.7" walkdir = "^2" diff --git a/duckscript_sdk/src/sdk/std/collections/mod.rs b/duckscript_sdk/src/sdk/std/collections/mod.rs index 2df6f39..48e9971 100755 --- a/duckscript_sdk/src/sdk/std/collections/mod.rs +++ b/duckscript_sdk/src/sdk/std/collections/mod.rs @@ -2,6 +2,8 @@ pub(crate) mod array; mod array_is_empty; pub(crate) mod array_length; mod range; +mod read_properties; +mod write_properties; use crate::utils::pckg; use duckscript::types::command::Commands; @@ -16,6 +18,8 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr commands.set(array_is_empty::create(&package))?; commands.set(array_length::create(&package))?; commands.set(range::create(&package))?; + commands.set(read_properties::create(&package))?; + commands.set(write_properties::create(&package))?; Ok(()) } diff --git a/duckscript_sdk/src/sdk/std/collections/read_properties/help.md b/duckscript_sdk/src/sdk/std/collections/read_properties/help.md new file mode 100644 index 0000000..f1273a4 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/read_properties/help.md @@ -0,0 +1,25 @@ +```sh +count = read_properties text +``` + +Parses the properties (based on java properties format) text and sets them as variables.
+This command will also return the count of properties read. + +#### Parameters + +The text to parse. + +#### Return Value + +The properties count. + +#### Examples + +```sh +count = read_properties "a=1\nb=2\na.b.c=3" +assert_eq ${count} 3 + +assert_eq ${a} 1 +assert_eq ${b} 2 +assert_eq ${a.b.c} 3 +``` diff --git a/duckscript_sdk/src/sdk/std/collections/read_properties/mod.rs b/duckscript_sdk/src/sdk/std/collections/read_properties/mod.rs new file mode 100755 index 0000000..4c407f5 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/read_properties/mod.rs @@ -0,0 +1,64 @@ +use crate::utils::pckg; +use duckscript::types::command::{Command, CommandResult, Commands}; +use duckscript::types::instruction::Instruction; +use duckscript::types::runtime::StateValue; +use java_properties::read; +use std::collections::HashMap; + +#[cfg(test)] +#[path = "./mod_test.rs"] +mod mod_test; + +struct CommandImpl { + package: String, +} + +impl Command for CommandImpl { + fn name(&self) -> String { + pckg::concat(&self.package, "ReadProperties") + } + + fn aliases(&self) -> Vec { + vec!["read_properties".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + 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() < 1 { + CommandResult::Error("Missing properties text argument.".to_string()) + } else { + match read(arguments[0].as_bytes()) { + Ok(data) => { + for (key, value) in &data { + variables.insert(key.to_string(), value.to_string()); + } + + CommandResult::Continue(Some(data.len().to_string())) + } + Err(error) => CommandResult::Error(error.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/read_properties/mod_test.rs b/duckscript_sdk/src/sdk/std/collections/read_properties/mod_test.rs new file mode 100644 index 0000000..b838fa3 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/read_properties/mod_test.rs @@ -0,0 +1,28 @@ +use super::*; +use crate::test; +use crate::test::{CommandValidation, SetCommand}; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = read_properties", "out"); +} + +#[test] +fn run_valid() { + let context = test::run_script_and_validate( + vec![create(""), Box::new(SetCommand {})], + r#" + props = test_set "a=1\nb=2" + out = read_properties ${props} + "#, + CommandValidation::Match("out".to_string(), "2".to_string()), + ); + + assert_eq!(context.variables.get("a").unwrap(), "1"); + assert_eq!(context.variables.get("b").unwrap(), "2"); +} diff --git a/duckscript_sdk/src/sdk/std/collections/write_properties/help.md b/duckscript_sdk/src/sdk/std/collections/write_properties/help.md new file mode 100644 index 0000000..a1fa1b5 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/write_properties/help.md @@ -0,0 +1,27 @@ +```sh +text = write_properties [names] +``` + +Creates a properties string from the provided list of variable names (not values). + +#### Parameters + +A list of variable names. + +#### Return Value + +The properties text value. + +#### Examples + +```sh +a = set 1 +b = set 2 +a.b.c = set 3 + +# text will be equal to: +# a=1 +# b=2 +# a.b.c=3 +text = write_properties a b a.b.c +``` diff --git a/duckscript_sdk/src/sdk/std/collections/write_properties/mod.rs b/duckscript_sdk/src/sdk/std/collections/write_properties/mod.rs new file mode 100755 index 0000000..79bcea0 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/write_properties/mod.rs @@ -0,0 +1,73 @@ +use crate::utils::pckg; +use duckscript::types::command::{Command, CommandResult, Commands}; +use duckscript::types::instruction::Instruction; +use duckscript::types::runtime::StateValue; +use java_properties::write; +use std::collections::HashMap; +use std::str; + +#[cfg(test)] +#[path = "./mod_test.rs"] +mod mod_test; + +struct CommandImpl { + package: String, +} + +impl Command for CommandImpl { + fn name(&self) -> String { + pckg::concat(&self.package, "WriteProperties") + } + + fn aliases(&self) -> Vec { + vec!["write_properties".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + 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() < 1 { + CommandResult::Error("Missing properties names.".to_string()) + } else { + let mut data = HashMap::new(); + for argument in &arguments { + match variables.get(argument) { + Some(value) => { + data.insert(argument.to_string(), value.to_string()); + } + None => (), + } + } + + let mut buffer: Vec = vec![]; + match write(&mut buffer, &data) { + Ok(_) => match str::from_utf8(&buffer) { + Ok(text) => CommandResult::Continue(Some(text.trim().to_string())), + Err(error) => CommandResult::Error(error.to_string()), + }, + Err(error) => CommandResult::Error(error.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/write_properties/mod_test.rs b/duckscript_sdk/src/sdk/std/collections/write_properties/mod_test.rs new file mode 100644 index 0000000..016ae14 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/write_properties/mod_test.rs @@ -0,0 +1,26 @@ +use super::*; +use crate::test; +use crate::test::{CommandValidation, SetCommand}; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = write_properties", "out"); +} + +#[test] +fn run_valid() { + test::run_script_and_validate( + vec![create(""), Box::new(SetCommand {})], + r#" + a = test_set 1 + b = test_set 2 + out = write_properties a b + "#, + CommandValidation::Contains("out".to_string(), "b=2".to_string()), + ); +} diff --git a/test/std/collections/read_properties_test.ds b/test/std/collections/read_properties_test.ds new file mode 100644 index 0000000..51c5da7 --- /dev/null +++ b/test/std/collections/read_properties_test.ds @@ -0,0 +1,9 @@ + +function test_read_properties + count = read_properties a=1\nb=2\na.b.c=3 + assert_eq ${count} 3 + + assert_eq ${a} 1 + assert_eq ${b} 2 + assert_eq ${a.b.c} 3 +end diff --git a/test/std/collections/write_properties_test.ds b/test/std/collections/write_properties_test.ds new file mode 100644 index 0000000..a6a3f4d --- /dev/null +++ b/test/std/collections/write_properties_test.ds @@ -0,0 +1,22 @@ + +function test_write_properties + count = read_properties a=1\nb=2\na.b.c=3 + assert_eq ${count} 3 + + assert_eq ${a} 1 + assert_eq ${b} 2 + assert_eq ${a.b.c} 3 + + text = write_properties a b a.b.c + + a = set + b = set + a.b.c = set + + count = read_properties ${text} + assert_eq ${count} 3 + + assert_eq ${a} 1 + assert_eq ${b} 2 + assert_eq ${a.b.c} 3 +end