New not command #12

This commit is contained in:
sagie gur ari 2019-12-31 23:24:06 +00:00
parent f971b6c5bb
commit 2e32c564b2
7 changed files with 203 additions and 5 deletions

View file

@ -2,7 +2,7 @@
### v0.1.2
*
* New **not** command.
### v0.1.0 (2019-12-30)

View file

@ -1,7 +1,7 @@
```sh
if command
if command|value
# commands
elseif command
elseif command|value
# commands
else
# commands
@ -15,13 +15,18 @@ This command provides the if/elseif/else condition language feature as a set of
* else - Optinoal fallback block
* end_if - Defines the end of the entire if/else block
if and elseif commands accept a command with arguments and invokes it.<br>
If the result of the command is one of the following:
if and elseif commands accept either:
* A command with optional arguments and invokes it
* A single value which doesn't match any known command
If the value or the result of the command is one of the following:
* No output
* false (case insensitive)
* 0
* no (case insensitive)
* Empty value
It is considered falsy.<br>
In case of falsy value, it will skip to the next elseif/else block.<br>
@ -48,6 +53,14 @@ if true
end_if
```
Example of using **not** command to reverse the output value
```sh
if not false
echo in if
end_if
```
Example of an if statement that evaluates the command as true and echos "in if"
```sh

View file

@ -8,6 +8,7 @@ mod fs;
mod function;
mod goto;
mod ifelse;
mod not;
mod process;
mod release;
mod set;
@ -25,6 +26,7 @@ pub(crate) fn load(commands: &mut Commands) -> Result<(), ScriptError> {
commands.set(echo::create(PACKAGE))?;
commands.set(eval::create(PACKAGE))?;
commands.set(goto::create(PACKAGE))?;
commands.set(not::create(PACKAGE))?;
commands.set(release::create(PACKAGE))?;
commands.set(set::create(PACKAGE))?;
commands.set(unalias::create(PACKAGE))?;

View file

@ -0,0 +1,49 @@
```sh
output = not command|value
```
Enables to switch falsy to true and truthy to false.<br>
The **not** commands accept either:
* A command with optional arguments and invokes it
* A single value which doesn't match any known command
If the value or the result of the command is one of the following:
* No output
* false (case insensitive)
* 0
* no (case insensitive)
* Empty value
It will return true, otherwise it will return false.
#### Parameters
A command and its arguments to invoke and evaluate its output, if a single value is provided an no such command exists, it is evaluated as a value.
#### Return Value
The switched value of the input.
#### Examples
Simple example of converting true/false values
```sh
is_false = not true
echo is false: ${is_false}
is_true = not false
echo is true: ${is_true}
```
Example of converting command output value
```sh
is_false = not set true
echo is false: ${is_false}
is_true = not set false
echo is true: ${is_true}
```

View file

@ -0,0 +1,60 @@
use crate::utils::{condition, pckg};
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;
struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "Not")
}
fn aliases(&self) -> Vec<String> {
vec!["not".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.is_empty() {
CommandResult::Error("Missing condition".to_string())
} else {
match condition::eval_condition(arguments, state, variables, commands) {
Ok(passed) => {
let output = !passed;
CommandResult::Continue(Some(output.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,66 @@
use super::*;
use crate::test;
use crate::test::{CommandValidation, ErrorCommand, SetCommand};
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
test::run_script_and_fail(vec![create("")], "not");
}
#[test]
fn run_single_value_true() {
test::run_script_and_validate(
vec![create("")],
"out = not true",
CommandValidation::Match("out".to_string(), "false".to_string()),
);
}
#[test]
fn run_single_value_false() {
test::run_script_and_validate(
vec![create("")],
"out = not false",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_command_value_true() {
test::run_script_and_validate(
vec![create(""), Box::new(SetCommand {})],
"out = not test_set true",
CommandValidation::Match("out".to_string(), "false".to_string()),
);
}
#[test]
fn run_command_value_false() {
test::run_script_and_validate(
vec![create(""), Box::new(SetCommand {})],
"out = not test_set false",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_command_no_value() {
test::run_script_and_validate(
vec![create(""), Box::new(SetCommand {})],
"out = not test_set",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_command_error() {
test::run_script_and_fail(
vec![create(""), Box::new(ErrorCommand {})],
"out = not test_error",
);
}

View file

@ -3,6 +3,14 @@ if true
echo in if as value
end_if
if false
echo should not be here
end_if
if not false
echo in if as value with not condition
end_if
if set true
echo in if as command
end_if