use core::*;
use helper::*;
use rair_env::EnvData;
use std::io::Write;
use yansi::Paint;
#[derive(Default)]
pub struct Environment {}
impl Environment {
pub fn new() -> Self {
Default::default()
}
fn iterate(&self, core: &mut Core) {
let env = core.env.clone();
for (k, v) in env.borrow().iter() {
match v {
EnvData::Bool(b) => writeln!(core.stdout, "{} = {}", k, b).unwrap(),
EnvData::I64(i) => writeln!(core.stdout, "{} = {}", k, i).unwrap(),
EnvData::U64(u) => writeln!(core.stdout, "{} = 0x{:x}", k, u).unwrap(),
EnvData::Str(s) => writeln!(core.stdout, "{} = {}", k, s).unwrap(),
EnvData::Color(r, g, b) => {
let color = format!("#{:02x}{:02x}{:02x}", r, g, b);
writeln!(core.stdout, "{} = {}", k, Paint::rgb(r, g, b, color)).unwrap();
}
}
}
}
fn set(&self, core: &mut Core, key: &str, value: &str) {
let env = core.env.clone();
let mut res = Ok(());
if env.borrow().is_bool(key) {
let v_str = value.to_ascii_lowercase();
let value = match v_str.as_str() {
"true" => true,
"false" => false,
_ => {
let message = format!("Expected `true` or `false`, found `{}`.", value);
return error_msg(core, "Failed to set variable.", &message);
}
};
res = env.borrow_mut().set_bool(key, value, core);
} else if env.borrow().is_i64(key) {
let value = match i64::from_str_radix(value, 10) {
Ok(value) => value,
Err(e) => return error_msg(core, "Failed to set variable.", &e.to_string()),
};
res = env.borrow_mut().set_i64(key, value, core);
} else if env.borrow().is_u64(key) {
let value = match str_to_num(value) {
Ok(value) => value,
Err(e) => return error_msg(core, "Failed to set variable.", &e.to_string()),
};
res = env.borrow_mut().set_u64(key, value, core);
} else if env.borrow().is_str(key) {
res = env.borrow_mut().set_str(key, value, core);
} else if env.borrow().is_color(key) {
if value.len() != 7 || !value.starts_with('#') {
let message = format!("Expected color code, found `{}`.", value);
return error_msg(core, "Failed to set variable.", &message);
}
let r = match u8::from_str_radix(&value[1..3], 16) {
Ok(c) => c,
Err(e) => return error_msg(core, "Failed to set variable.", &e.to_string()),
};
let g = match u8::from_str_radix(&value[3..5], 16) {
Ok(c) => c,
Err(e) => return error_msg(core, "Failed to set variable.", &e.to_string()),
};
let b = match u8::from_str_radix(&value[5..], 16) {
Ok(c) => c,
Err(e) => return error_msg(core, "Failed to set variable.", &e.to_string()),
};
res = env.borrow_mut().set_color(key, (r, g, b), core);
}
if let Err(e) = res {
return error_msg(core, "Failed to set variable.", &e.to_string());
}
}
fn display(&self, core: &mut Core, key: &str) {
let env = core.env.borrow();
let data = match env.get(key) {
Some(data) => data,
None => {
drop(env);
let message = format!("Variable `{}` doesn't exist.", key);
return error_msg(core, "Failed to display variable.", &message);
}
};
match data {
EnvData::Bool(b) => writeln!(core.stdout, "{}", b).unwrap(),
EnvData::I64(i) => writeln!(core.stdout, "{}", i).unwrap(),
EnvData::U64(u) => writeln!(core.stdout, "0x{:x}", u).unwrap(),
EnvData::Str(s) => writeln!(core.stdout, "{}", s).unwrap(),
EnvData::Color(r, g, b) => {
let color = format!("#{:02x}{:02x}{:02x}", r, g, b);
writeln!(core.stdout, "{}", Paint::rgb(r, g, b, color)).unwrap();
}
}
}
}
impl Cmd for Environment {
fn run(&mut self, core: &mut Core, args: &[String]) {
if args.len() > 3 {
return expect_range(core, args.len() as u64, 0, 3);
} else if args.is_empty() {
self.iterate(core);
} else if args.len() == 1 {
let args: Vec<&str> = args[0].split('=').collect();
if args.len() == 2 {
self.set(core, &args[0].trim(), &args[1].trim());
} else {
self.display(core, &args[0]);
}
} else if args.len() == 2 {
if args[0].ends_with('=') ^ args[1].starts_with('=') {
let key = args[0].split('=').next().unwrap().trim();
let value = args[1].split('=').last().unwrap().trim();
self.set(core, key, value);
} else {
return error_msg(core, "Failed to set variable.", &"Expected `=`.");
}
} else if args.len() == 3 {
if args[1] == "=" {
self.set(core, &args[0], &args[2]);
} else {
let message = format!("Expected `=` found `{}`.", args[1]);
return error_msg(core, "Failed to set variable.", &message);
}
}
}
fn help(&self, core: &mut Core) {
help(
core,
&"environment",
&"e",
vec![
("", "List all environment variables."),
("[var]", "Display the value of [var] environment variables."),
("[var]=[value]", "Set [var] to be [value]"),
],
);
}
}
#[derive(Default)]
pub struct EnvironmentReset {}
impl EnvironmentReset {
pub fn new() -> Self {
Default::default()
}
}
impl Cmd for EnvironmentReset {
fn run(&mut self, core: &mut Core, args: &[String]) {
if args.len() != 1 {
expect(core, args.len() as u64, 1);
return;
}
let env = core.env.clone();
let res = env.borrow_mut().reset(&args[0], core);
if let Err(e) = res {
return error_msg(core, "Failed to reset variable.", &e.to_string());
}
return;
}
fn help(&self, core: &mut Core) {
help(core, &"environmentReset", &"er", vec![("[var]", "Reset [var] environment variable.")]);
}
}
#[derive(Default)]
pub struct EnvironmentHelp {}
impl EnvironmentHelp {
pub fn new(core: &mut Core) -> Self {
let env = core.env.clone();
env.borrow_mut()
.add_str_with_cb("environmentHelp.envColor", "color.6", "Color used in the environment variable", core, is_color)
.unwrap();
return Default::default();
}
}
impl Cmd for EnvironmentHelp {
fn run(&mut self, core: &mut Core, args: &[String]) {
if args.len() != 1 {
expect(core, args.len() as u64, 1);
return;
}
let env = core.env.borrow();
let res = env.get_help(&args[0]);
if let Some(help) = res {
let color = env.get_str("environmentHelp.envColor").unwrap();
let (r, g, b) = env.get_color(color).unwrap();
writeln!(core.stdout, "{}:\t{}", Paint::rgb(r, g, b, &args[0]), help).unwrap();
} else {
drop(env);
error_msg(core, "Failed to display help.", "Variable Not found");
}
return;
}
fn help(&self, core: &mut Core) {
help(core, &"environmentHelp", &"eh", vec![("[var]", "Print help for [var] environment variable.")]);
}
}
#[cfg(test)]
mod test_env {
use super::*;
use rair_env::Environment as Env;
use writer::*;
#[test]
fn test_help() {
let mut core = Core::new_no_colors();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let er = EnvironmentReset::new();
let env = Environment::new();
er.help(&mut core);
env.help(&mut core);
core.help("eh");
assert_eq!(
core.stdout.utf8_string().unwrap(),
"Commands: [environmentReset | er]\n\n\
Usage:\n\
er [var]\tReset [var] environment variable.\n\
Commands: [environment | e]\n\n\
Usage:\n\
e\tList all environment variables.\n\
e [var]\tDisplay the value of [var] environment variables.\n\
e [var]=[value]\tSet [var] to be [value]\n\
Commands: [environmentHelp | eh]\n\n\
Usage:\n\
eh [var]\tPrint help for [var] environment variable.\n"
);
assert_eq!(core.stderr.utf8_string().unwrap(), "");
}
#[test]
fn test_env_help() {
let mut core = Core::new_no_colors();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
core.run("eh", &["environmentHelp.envColor".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "environmentHelp.envColor:\tColor used in the environment variable\n");
assert_eq!(core.stderr.utf8_string().unwrap(), "");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
core.run("eh", &["doesnt.exist".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to display help.\nVariable Not found\n");
}
#[test]
fn test_env_reset() {
let mut core = Core::new_no_colors();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut er = EnvironmentReset::new();
let env = core.env.clone();
let (r, g, b) = env.borrow().get_color("color.1").unwrap();
env.borrow_mut().set_color("color.1", (r + 1, g + 1, b + 1), &mut core).unwrap();
er.run(&mut core, &["color.1".to_string()]);
let (r2, g2, b2) = env.borrow().get_color("color.1").unwrap();
assert_eq!(r, r2);
assert_eq!(g, g2);
assert_eq!(b, b2);
}
#[test]
fn test_env_reset_err() {
let mut core = Core::new_no_colors();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut er = EnvironmentReset::new();
er.run(&mut core, &["doest.exist".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to reset variable.\nEnvironment variable not found.\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
er.run(&mut core, &[]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Arguments Error: Expected 1 argument(s), found 0.\n");
}
fn get_good_core() -> Core {
let mut core = Core::new_no_colors();
core.env = Default::default();
core.env.borrow_mut().add_bool("b", false, "").unwrap();
core.env.borrow_mut().add_u64("u", 500, "").unwrap();
core.env.borrow_mut().add_i64("i", -500, "").unwrap();
core.env.borrow_mut().add_str("s", "hello world", "").unwrap();
core.env.borrow_mut().add_color("c", (0xff, 0xee, 0xdd), "").unwrap();
return core;
}
#[test]
fn test_env_0() {
let mut core = get_good_core();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut env = Environment::new();
env.run(&mut core, &[]);
let s = core.stdout.utf8_string().unwrap();
assert_eq!(core.stderr.utf8_string().unwrap(), "");
assert_eq!(s.len(), 57);
assert!(s.contains("i = -500\n"));
assert!(s.contains("u = 0x1f4\n"));
assert!(s.contains("s = hello world\n"));
assert!(s.contains("b = false\n"));
assert!(s.contains("c = #ffeedd\n"));
}
#[test]
fn test_env_1() {
let mut core = get_good_core();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut env = Environment::new();
env.run(&mut core, &["b".to_string()]);
env.run(&mut core, &["u".to_string()]);
env.run(&mut core, &["i".to_string()]);
env.run(&mut core, &["s".to_string()]);
env.run(&mut core, &["c".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "false\n0x1f4\n-500\nhello world\n#ffeedd\n");
assert_eq!(core.stderr.utf8_string().unwrap(), "");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["b = true ".to_string()]);
env.run(&mut core, &["u= 0x5".to_string()]);
env.run(&mut core, &["i=-1".to_string()]);
env.run(&mut core, &["s=happy birthday".to_string()]);
env.run(&mut core, &["c=#aaaaaa".to_string()]);
env.run(&mut core, &["b".to_string()]);
env.run(&mut core, &["u".to_string()]);
env.run(&mut core, &["i".to_string()]);
env.run(&mut core, &["s".to_string()]);
env.run(&mut core, &["c".to_string()]);
env.run(&mut core, &["b = false".to_string()]);
env.run(&mut core, &["b".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "true\n0x5\n-1\nhappy birthday\n#aaaaaa\nfalse\n");
assert_eq!(core.stderr.utf8_string().unwrap(), "");
}
#[test]
fn test_env_2() {
let mut core = get_good_core();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut env = Environment::new();
env.run(&mut core, &["b =".to_string(), "true ".to_string()]);
env.run(&mut core, &["u".to_string(), "= 0x5".to_string()]);
env.run(&mut core, &["b".to_string()]);
env.run(&mut core, &["u".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "true\n0x5\n");
assert_eq!(core.stderr.utf8_string().unwrap(), "");
}
#[test]
fn test_env_3() {
let mut core = get_good_core();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut env = Environment::new();
env.run(&mut core, &["b".to_string(), "=".to_string(), "true".to_string()]);
env.run(&mut core, &["b".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "true\n");
assert_eq!(core.stderr.utf8_string().unwrap(), "");
}
#[test]
fn test_env_error() {
let mut core = Core::new_no_colors();
core.env.borrow_mut().add_bool("b", false, "").unwrap();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut env = Environment::new();
env.run(&mut core, &["b".to_string(), "=".to_string(), "true".to_string(), "extra".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Arguments Error: Expected between 0 and 3 arguments, found 4.\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["b".to_string(), "true".to_string(), "extra".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\nExpected `=` found `true`.\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["b".to_string(), "true".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\nExpected `=`.\n");
}
#[test]
fn test_display_error() {
let mut core = Core::new_no_colors();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut env = Environment::new();
env.run(&mut core, &["b".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to display variable.\nVariable `b` doesn't exist.\n");
}
fn always_false(_: &str, value: bool, _: &Env<Core>, _: &mut Core) -> bool {
return !value;
}
#[test]
fn test_set_error() {
let mut core = Core::new_no_colors();
let env = core.env.clone();
env.borrow_mut().add_bool_with_cb("b", false, "", &mut core, always_false).unwrap();
env.borrow_mut().add_u64("u", 500, "").unwrap();
env.borrow_mut().add_i64("i", -500, "").unwrap();
env.borrow_mut().add_str("s", "hi", "").unwrap();
env.borrow_mut().add_color("c", (0xee, 0xee, 0xee), "").unwrap();
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
let mut env = Environment::new();
env.run(&mut core, &["b=no".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\nExpected `true` or `false`, found `no`.\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["b=true".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\nCall back failed.\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["i=x5".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\ninvalid digit found in string\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["u=x5".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\ninvalid digit found in string\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["c=5".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\nExpected color code, found `5`.\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["c=#1x2233".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\ninvalid digit found in string\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["c=#11x233".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\ninvalid digit found in string\n");
core.stderr = Writer::new_buf();
core.stdout = Writer::new_buf();
env.run(&mut core, &["c=#11223x".to_string()]);
assert_eq!(core.stdout.utf8_string().unwrap(), "");
assert_eq!(core.stderr.utf8_string().unwrap(), "Error: Failed to set variable.\ninvalid digit found in string\n");
}
}