diff --git a/1 b/1 deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/manual/src/ch11-00-builtins.md b/manual/src/ch11-00-builtins.md index aa791398d93a40feb8689fc5f5a9751c6d924c20..850bb47ba6c70305cd2bd95c3d9adab902024bfe 100644 --- a/manual/src/ch11-00-builtins.md +++ b/manual/src/ch11-00-builtins.md @@ -411,4 +411,15 @@ Evaluates the current runtime status bool VALUE ``` -If the value is '1' or 'true', return 0 exit status \ No newline at end of file +If the value is '1' or 'true', returns the 0 exit status + +## is + +``` +is VALUE VALUE +``` + +Returns 0 if the two arguments are equal + +### Options +- **not**: returns 0 if the two arguments are not equal. \ No newline at end of file diff --git a/src/builtins/README.md b/src/builtins/README.md index 5d91a05ae08904cce413476806baa87d5a7d5c7d..480ad68ffaf75fc277a4f3b1ebf819d67c24820e 100644 --- a/src/builtins/README.md +++ b/src/builtins/README.md @@ -29,3 +29,7 @@ Source code for the time command, which is used to evaluate the time spent runni ## variables.rs The **variables.rs** module contains commands relating to setting and removing aliases, variables, and exports. + +## status.rs + +The source for status command, which is used to get information at runtime about the shell. diff --git a/src/builtins/is.rs b/src/builtins/is.rs new file mode 100644 index 0000000000000000000000000000000000000000..e8c64e3814323e00fe15839f0e69908412799b61 --- /dev/null +++ b/src/builtins/is.rs @@ -0,0 +1,69 @@ +use std::error::Error; +use std::io::{Write, stdout}; + +use shell::Shell; + +const MAN_PAGE: &'static str = r#"NAME + is - Checks if two arguments are the same + +SYNOPSIS + is [ -h | --help ] [not] + +DESCRIPTION + Returns 0 if the two arguments are equal + +OPTIONS + not + returns 0 if the two arguments are not equal. +"#; // @MANEND + +pub(crate) fn is(args: &[&str], shell: &mut Shell) -> Result<(), String> { + match args.len() { + 4 => if args[1] != "not" { + return Err(format!("Expected 'not' instead found '{}'\n", args[1]).to_string()); + } else if eval_arg(args[2], shell) == eval_arg(args[3], shell) { + return Err("".to_string()); + }, + 3 => if eval_arg(args[1], shell) != eval_arg(args[2], shell) { + return Err("".to_string()); + }, + 2 => if args[1] == "-h" || args[1] == "--help" { + let stdout = stdout(); + let mut stdout = stdout.lock(); + + return match stdout.write_all(MAN_PAGE.as_bytes()).and_then(|_| stdout.flush()) { + Ok(_) => Ok(()), + Err(err) => Err(err.description().to_owned()), + } + } else { + return Err("is needs 3 or 4 arguments\n".to_string()) + }, + _ => return Err("is needs 3 or 4 arguments\n".to_string()), + } + + Ok(()) +} + +fn eval_arg(arg: &str, shell: &mut Shell) -> String { + let var_value = get_var_string(arg, shell); + + if var_value != "" { + return var_value + } + arg.to_string() +} + +// On error returns an empty String. +fn get_var_string(name: &str, shell: &mut Shell) -> String { + if name.chars().nth(0).unwrap() != '$' { + return "".to_string() + } + + let var = shell.variables.get_var(&name[1..]); + let sh_var: &str = match var.as_ref() { + Some(s) => s, + None => "", + }; + + sh_var.to_string() +} \ No newline at end of file diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index a01e1430c1c30a97c5790638b9b4777c9eca9710..b43a1f9d6d304d39f1c3975aab5ac0fd9c452ccd 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -12,12 +12,14 @@ mod set; mod status; mod exists; mod ion; +mod is; use self::conditionals::{contains, ends_with, starts_with}; use self::echo::echo; use self::exists::exists; use self::functions::fn_; use self::ion::ion_docs; +use self::is::is; use self::status::status; use self::source::source; use self::test::test; @@ -77,6 +79,7 @@ pub const BUILTINS: &'static BuiltinMap = &map!( "help" => builtin_help : HELP_DESC, "history" => builtin_history : "Display a log of all commands previously executed", "ion-docs" => ion_docs : "Opens the Ion manual", + "is" => builtin_is : "Simple alternative to == and !=", "jobs" => builtin_jobs : "Displays all jobs that are attached to the background", "matches" => builtin_matches : "Checks if a string matches a given regex", "not" => builtin_not : "Reverses the exit status value of the given command.", @@ -161,7 +164,7 @@ fn builtin_bool(args: &[&str], shell: &mut Shell) -> i32 { return FAILURE } - let opt = shell.variables.get_var(args[1]); + let opt = shell.variables.get_var(&args[1][1..]); let sh_var: &str = match opt.as_ref() { Some(s) => s, None => "", @@ -179,10 +182,21 @@ fn builtin_bool(args: &[&str], shell: &mut Shell) -> i32 { _ => return FAILURE } } - SUCCESS } +fn builtin_is(args: &[&str], shell: &mut Shell) -> i32 { + match is(args, shell) { + Ok(()) => SUCCESS, + Err(why) => { + let stderr = io::stderr(); + let mut stderr = stderr.lock(); + let _ = stderr.write_all(why.as_bytes()); + FAILURE + } + } +} + fn builtin_dirs(args: &[&str], shell: &mut Shell) -> i32 { shell.directory_stack.dirs(args) } fn builtin_pushd(args: &[&str], shell: &mut Shell) -> i32 { @@ -241,6 +255,7 @@ fn builtin_not(args: &[&str], shell: &mut Shell) -> i32 { } fn builtin_set(args: &[&str], shell: &mut Shell) -> i32 { set::set(args, shell) } + fn builtin_eval(args: &[&str], shell: &mut Shell) -> i32 { let evaluated_command = args[1..].join(" "); let mut buffer = Terminator::new(evaluated_command); @@ -254,6 +269,7 @@ fn builtin_eval(args: &[&str], shell: &mut Shell) -> i32 { FAILURE } } + fn builtin_history(args: &[&str], shell: &mut Shell) -> i32 { shell.print_history(args) } fn builtin_source(args: &[&str], shell: &mut Shell) -> i32 {