New properties read/write commands #61

This commit is contained in:
sagie gur ari 2020-01-17 10:39:50 +00:00
parent 5987787809
commit 3101ae03e3
12 changed files with 348 additions and 0 deletions

View File

@ -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)

View File

@ -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
<a name="std__collections__ReadProperties"></a>
## std::collections::ReadProperties
```sh
count = read_properties text
```
Parses the properties (based on java properties format) text and sets them as variables.<br>
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
<a name="std__collections__WriteProperties"></a>
## 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
<a name="std__env__GetVar"></a>
## std::env::GetVar
```sh

View File

@ -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"

View File

@ -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(())
}

View File

@ -0,0 +1,25 @@
```sh
count = read_properties text
```
Parses the properties (based on java properties format) text and sets them as variables.<br>
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
```

View File

@ -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<String> {
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<String>,
_state: &mut HashMap<String, StateValue>,
variables: &mut HashMap<String, String>,
_output_variable: Option<String>,
_instructions: &Vec<Instruction>,
_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<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View File

@ -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");
}

View File

@ -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
```

View File

@ -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<String> {
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<String>,
_state: &mut HashMap<String, StateValue>,
variables: &mut HashMap<String, String>,
_output_variable: Option<String>,
_instructions: &Vec<Instruction>,
_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<u8> = 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<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View File

@ -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()),
);
}

View File

@ -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

View File

@ -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