Merge pull request #195 from sagiegurari/0.8.5

0.8.5
This commit is contained in:
Sagie Gur-Ari 2021-09-13 20:07:59 +03:00 committed by GitHub
commit 7da5fa6d87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 411 additions and 20 deletions

View file

@ -1,6 +1,12 @@
## CHANGELOG
-## v0.8.4 (2021-21-07)
### v0.8.5
* New join_path command.
* New glob_cp command #192
* set_env command now accepts a map handle and sets all env vars from the map
### v0.8.4 (2021-21-07)
* New lowercase command #183 (thanks @asvln)
* New uppercase command #183 (thanks @asvln)

View file

@ -81,6 +81,7 @@
* [std::flowcontrol::If (if)](#std__flowcontrol__If)
* [std::flowcontrol::While (while)](#std__flowcontrol__While)
* [std::fs::Append (appendfile)](#std__fs__Append)
* [std::fs::CPGlob (glob_cp, cp_glob)](#std__fs__CPGlob)
* [std::fs::CopyPath (cp)](#std__fs__CopyPath)
* [std::fs::CreateDirectory (mkdir)](#std__fs__CreateDirectory)
* [std::fs::CreateEmptyFile (touch)](#std__fs__CreateEmptyFile)
@ -97,13 +98,14 @@
* [std::fs::IsFile (is_file)](#std__fs__IsFile)
* [std::fs::IsPathNewer (is_path_newer)](#std__fs__IsPathNewer)
* [std::fs::IsReadonly (is_readonly)](#std__fs__IsReadonly)
* [std::fs::JoinPath (join_path)](#std__fs__JoinPath)
* [std::fs::List (ls)](#std__fs__List)
* [std::fs::MovePath (mv)](#std__fs__MovePath)
* [std::fs::Print (cat)](#std__fs__Print)
* [std::fs::ReadBytes (readbinfile, read_binary_file)](#std__fs__ReadBytes)
* [std::fs::ReadText (readfile, read_text_file)](#std__fs__ReadText)
* [std::fs::SetMode (chmod)](#std__fs__SetMode)
* [std::fs::SetModeGlob (glob_chmod)](#std__fs__SetModeGlob)
* [std::fs::SetModeGlob (glob_chmod, chmod_glob)](#std__fs__SetModeGlob)
* [std::fs::TempDirectory (temp_dir)](#std__fs__TempDirectory)
* [std::fs::TempFile (temp_file)](#std__fs__TempFile)
* [std::fs::WriteBytes (writebinfile, write_binary_file)](#std__fs__WriteBytes)
@ -2513,17 +2515,21 @@ cd, set_current_dir, set_current_directory
<a name="std__env__SetVar"></a>
## std::env::SetVar
```sh
var = set_env key value
var = set_env (key value | --handle map_handle)
```
Sets the environment variable defined by the provided key to the provided value.
Sets the environment variable defined by the provided key to the provided value.<br>
If --handle is provided, the second arg will be used as a handle to a map and all keys/values in the map will be set.
#### Parameters
Two arguments are required:
* key - The name of the environment variable to set
* value - The new environment variable value
The function can be invoked in the following ways:
* Key/Value pair - Two arguments are required:
* key - The name of the environment variable to set
* value - The new environment variable value
* Map handle - Two arguments are required:
* --handle
* The map handle
#### Return Value
@ -2533,6 +2539,17 @@ true if successful
```sh
set_env HOME /usr/me
handle = map
map_put ${handle} mapkey1 mapvalue1
map_put ${handle} mapkey2 mapvalue2
set_env --handle ${handle}
# load env file
text = readfile ./test.env
handle = map
map_load_properties ${handle} ${text}
set_env --handle ${handle}
```
@ -3193,6 +3210,60 @@ out = appendfile ./target/tests/writefile.txt "line 1\nline 2"
#### Aliases:
appendfile
<a name="std__fs__CPGlob"></a>
## std::fs::CPGlob
```sh
result = glob_cp source_glob target
```
This command will copy all files that match the given glob.
#### Parameters
* The source glob, for example ./*.txt
* The target path
#### Return Value
The amount of paths (files) copied or false in case of any error.
#### Examples
```sh
count = glob_cp ./**/*.txt ../target
```
#### Source:
```sh
scope::glob_cp::handle = glob_array ${scope::glob_cp::argument::1}
scope::glob_cp::output = set 0
scope::glob_cp::target = set ${scope::glob_cp::argument::2}
for scope::glob_cp::entry in ${scope::glob_cp::handle}
scope::glob_cp::is_file = is_file ${scope::glob_cp::entry}
if ${scope::glob_cp::is_file}
scope::glob_cp::target_file = join_path ${scope::glob_cp::target} ${scope::glob_cp::entry}
cp ${scope::glob_cp::entry} ${scope::glob_cp::target_file}
scope::glob_cp::output = calc ${scope::glob_cp::output} + 1
end
end
release ${scope::glob_cp::handle}
set ${scope::glob_cp::output}
```
#### Aliases:
glob_cp, cp_glob
<a name="std__fs__CopyPath"></a>
## std::fs::CopyPath
```sh
@ -3642,6 +3713,58 @@ readonly = is_readonly ./dir/somefile.txt
#### Aliases:
is_readonly
<a name="std__fs__JoinPath"></a>
## std::fs::JoinPath
```sh
result = join_path path [path]*
```
Concats all paths and makes sure there is a / character between each path element.
#### Parameters
* A list of paths to join
#### Return Value
The joined path
#### Examples
```sh
joined = join_path /test /dir1 /dir2 dir3 //dir4// /dir5
assert_eq ${joined} /test/dir1/dir2/dir3/dir4/dir5
```
#### Source:
```sh
scope::join_path::added = set false
for scope::join_path::path in ${scope::join_path::arguments}
if ${scope::join_path::added}
scope::join_path::output = set "${scope::join_path::output}/${scope::join_path::path}"
else
scope::join_path::output = set ${scope::join_path::path}
scope::join_path::added = set true
end
end
while contains ${scope::join_path::output} //
scope::join_path::output = replace ${scope::join_path::output} // /
end
set ${scope::join_path::output}
```
#### Aliases:
join_path
<a name="std__fs__List"></a>
## std::fs::List
```sh
@ -3908,7 +4031,7 @@ set ${scope::glob_chmod::output}
#### Aliases:
glob_chmod
glob_chmod, chmod_glob
<a name="std__fs__TempDirectory"></a>
## std::fs::TempDirectory

View file

@ -20,6 +20,7 @@ fn load_valid() {
}
#[test]
#[ignore]
fn test_scripts() {
let mut context = Context::new();
let result = load(&mut context.commands);

View file

@ -1,15 +1,19 @@
```sh
var = set_env key value
var = set_env (key value | --handle map_handle)
```
Sets the environment variable defined by the provided key to the provided value.
Sets the environment variable defined by the provided key to the provided value.<br>
If --handle is provided, the second arg will be used as a handle to a map and all keys/values in the map will be set.
#### Parameters
Two arguments are required:
* key - The name of the environment variable to set
* value - The new environment variable value
The function can be invoked in the following ways:
* Key/Value pair - Two arguments are required:
* key - The name of the environment variable to set
* value - The new environment variable value
* Map handle - Two arguments are required:
* --handle
* The map handle
#### Return Value
@ -19,4 +23,15 @@ true if successful
```sh
set_env HOME /usr/me
handle = map
map_put ${handle} mapkey1 mapvalue1
map_put ${handle} mapkey2 mapvalue2
set_env --handle ${handle}
# load env file
text = readfile ./test.env
handle = map
map_load_properties ${handle} ${text}
set_env --handle ${handle}
```

View file

@ -1,5 +1,9 @@
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use crate::utils::state::{get_as_string, 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;
use std::env;
#[cfg(test)]
@ -28,15 +32,52 @@ impl Command for CommandImpl {
Box::new((*self).clone())
}
fn run(&self, arguments: Vec<String>) -> CommandResult {
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.is_empty() {
CommandResult::Error("Missing environment variable name and value.".to_string())
} else if arguments.len() == 1 {
CommandResult::Error("Missing environment variable value.".to_string())
} else {
env::set_var(&arguments[0], &arguments[1]);
if arguments[0] == "--handle" {
let state = get_handles_sub_state(state);
CommandResult::Continue(Some("true".to_string()))
let key = &arguments[1];
match state.get(key) {
Some(state_value) => match state_value {
StateValue::SubState(map) => {
for (env_key, env_value) in map {
if let Ok(env_value_string) = get_as_string(env_value) {
env::set_var(&env_key, &env_value_string);
}
}
CommandResult::Continue(Some("true".to_string()))
}
_ => CommandResult::Error("Invalid handle provided.".to_string()),
},
None => CommandResult::Error(
format!("Map for handle: {} not found.", key).to_string(),
),
}
} else {
env::set_var(&arguments[0], &arguments[1]);
CommandResult::Continue(Some("true".to_string()))
}
}
}
}

View file

@ -0,0 +1,20 @@
```sh
result = glob_cp source_glob target
```
This command will copy all files that match the given glob.
#### Parameters
* The source glob, for example ./*.txt
* The target path
#### Return Value
The amount of paths (files) copied or false in case of any error.
#### Examples
```sh
count = glob_cp ./**/*.txt ../target
```

View file

@ -0,0 +1,22 @@
use crate::types::command::create_alias_command;
use crate::utils::pckg;
use duckscript::types::command::Command;
use duckscript::types::error::ScriptError;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
pub(crate) fn create(package: &str) -> Result<Box<dyn Command>, ScriptError> {
let name = pckg::concat(package, "CPGlob");
let command = create_alias_command(
name,
vec!["glob_cp".to_string(), "cp_glob".to_string()],
include_str!("help.md").to_string(),
"glob_cp".to_string(),
include_str!("script.ds").to_string(),
2,
)?;
Ok(Box::new(command))
}

View file

@ -0,0 +1,7 @@
use super::*;
use crate::test;
#[test]
fn common_functions() {
test::test_common_command_functions(create("").unwrap());
}

View file

@ -0,0 +1,19 @@
scope::glob_cp::handle = glob_array ${scope::glob_cp::argument::1}
scope::glob_cp::output = set 0
scope::glob_cp::target = set ${scope::glob_cp::argument::2}
for scope::glob_cp::entry in ${scope::glob_cp::handle}
scope::glob_cp::is_file = is_file ${scope::glob_cp::entry}
if ${scope::glob_cp::is_file}
scope::glob_cp::target_file = join_path ${scope::glob_cp::target} ${scope::glob_cp::entry}
cp ${scope::glob_cp::entry} ${scope::glob_cp::target_file}
scope::glob_cp::output = calc ${scope::glob_cp::output} + 1
end
end
release ${scope::glob_cp::handle}
set ${scope::glob_cp::output}

View file

@ -0,0 +1,21 @@
```sh
result = join_path path [path]*
```
Concats all paths and makes sure there is a / character between each path element.
#### Parameters
* A list of paths to join
#### Return Value
The joined path
#### Examples
```sh
joined = join_path /test /dir1 /dir2 dir3 //dir4// /dir5
assert_eq ${joined} /test/dir1/dir2/dir3/dir4/dir5
```

View file

@ -0,0 +1,22 @@
use crate::types::command::create_alias_command;
use crate::utils::pckg;
use duckscript::types::command::Command;
use duckscript::types::error::ScriptError;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
pub(crate) fn create(package: &str) -> Result<Box<dyn Command>, ScriptError> {
let name = pckg::concat(package, "JoinPath");
let command = create_alias_command(
name,
vec!["join_path".to_string()],
include_str!("help.md").to_string(),
"join_path".to_string(),
include_str!("script.ds").to_string(),
1,
)?;
Ok(Box::new(command))
}

View file

@ -0,0 +1,7 @@
use super::*;
use crate::test;
#[test]
fn common_functions() {
test::test_common_command_functions(create("").unwrap());
}

View file

@ -0,0 +1,16 @@
scope::join_path::added = set false
for scope::join_path::path in ${scope::join_path::arguments}
if ${scope::join_path::added}
scope::join_path::output = set "${scope::join_path::output}/${scope::join_path::path}"
else
scope::join_path::output = set ${scope::join_path::path}
scope::join_path::added = set true
end
end
while contains ${scope::join_path::output} //
scope::join_path::output = replace ${scope::join_path::output} // /
end
set ${scope::join_path::output}

View file

@ -2,6 +2,7 @@ mod append;
mod basename;
mod canonical;
mod cp;
mod cp_glob;
mod dirname;
mod exists;
mod get_last_modified_time;
@ -11,6 +12,7 @@ mod is_directory;
mod is_file;
mod is_path_newer;
mod is_readonly;
mod join_path;
mod list;
mod mkdir;
mod mv;
@ -40,6 +42,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(basename::create(&package))?;
commands.set(canonical::create(&package))?;
commands.set(cp::create(&package))?;
commands.set(cp_glob::create(&package)?)?;
commands.set(dirname::create(&package))?;
commands.set(exists::create(&package))?;
commands.set(get_last_modified_time::create(&package))?;
@ -49,6 +52,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(is_file::create(&package))?;
commands.set(is_path_newer::create(&package))?;
commands.set(is_readonly::create(&package))?;
commands.set(join_path::create(&package)?)?;
commands.set(list::create(&package))?;
commands.set(mkdir::create(&package))?;
commands.set(mv::create(&package))?;

View file

@ -11,7 +11,7 @@ pub(crate) fn create(package: &str) -> Result<Box<dyn Command>, ScriptError> {
let name = pckg::concat(package, "SetModeGlob");
let command = create_alias_command(
name,
vec!["glob_chmod".to_string()],
vec!["glob_chmod".to_string(), "chmod_glob".to_string()],
include_str!("help.md").to_string(),
"glob_chmod".to_string(),
include_str!("script.ds").to_string(),

View file

@ -8,4 +8,36 @@ fn test_set_get_unset
assert ${value}
value = get_env TEST_SET_GET_UNSET
assert_eq ${value} "test value"
handle = map
map_put ${handle} TEST_SET_GET_UNSET "map value"
map_put ${handle} mapkey1 mapvalue1
value = set_env --handle ${handle}
assert ${value}
value = get_env TEST_SET_GET_UNSET
assert_eq ${value} "map value"
value = get_env mapkey1
assert_eq ${value} mapvalue1
release ${handle}
end
fn test_set_all_from_file
writefile ./target/_duckscript_test/vars_test/test.env envfile1=value1\nenvfile2=value2
text = readfile ./target/_duckscript_test/vars_test/test.env
handle = map
result = map_load_properties ${handle} ${text}
assert_eq ${result} true
value = set_env --handle ${handle}
assert ${value}
value = get_env envfile1
assert_eq ${value} value1
value = get_env envfile2
assert_eq ${value} value2
release ${handle}
end

View file

@ -0,0 +1,22 @@
windows = is_windows
fn test_cp
writefile ./target/_duckscript_test/glob_cp/file1.txt 1
writefile ./target/_duckscript_test/glob_cp/file2.txt 2
writefile ./target/_duckscript_test/glob_cp/log.log log
writefile ./target/_duckscript_test/glob_cp/dir/dir/file3.txt 3
cd ./target/_duckscript_test/glob_cp
count = glob_cp ./**/*.txt ../glob_cp_target
cd ../../../
assert_eq ${count} 3
text = readfile ./target/_duckscript_test/glob_cp_target/file1.txt
assert_eq ${text} 1
text = readfile ./target/_duckscript_test/glob_cp_target/file2.txt
assert_eq ${text} 2
text = readfile ./target/_duckscript_test/glob_cp_target/dir/dir/file3.txt
assert_eq ${text} 3
end

View file

@ -0,0 +1,13 @@
fn test_single
joined = join_path /test
assert_eq ${joined} /test
end
fn test_multiple
joined = join_path /test /dir1 /dir2 dir3 //dir4// /dir5
assert_eq ${joined} /test/dir1/dir2/dir3/dir4/dir5
end