diff --git a/src/command/builtins.rs b/src/command/builtins.rs index 848daa0..e06b35a 100644 --- a/src/command/builtins.rs +++ b/src/command/builtins.rs @@ -1,5 +1,6 @@ use crate::error; use crate::error::CdError; +use crate::error::IllegalNumberError; use crate::exit_code::ExitCode; use std::env; @@ -33,3 +34,23 @@ pub(super) fn cd(args: &Vec, exit_code: &mut ExitCode) { pub(super) fn colon(_args: &Vec, exit_code: &mut ExitCode) { exit_code.set_success(); } + +pub(crate) fn exit(args: &Vec, exit_code: &mut ExitCode) { + let raw_exit_code: Result; + + if args.is_empty() { + raw_exit_code = Ok(i32::from(exit_code.get())); + } else { + raw_exit_code = match args[0].parse::() { + Ok(parsed) => Ok(i32::try_from(parsed % 256).unwrap()), + Err(_e) => Err(IllegalNumberError::new("exit", args[0].as_str())), + }; + } + + if raw_exit_code.is_ok() { + println!("exit"); + std::process::exit(raw_exit_code.unwrap()); + } else { + error::print(Box::new(raw_exit_code.unwrap_err())); + } +} diff --git a/src/command/mod.rs b/src/command/mod.rs index 7e450ed..e78cff0 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -1,4 +1,4 @@ -mod builtins; +pub mod builtins; pub mod command_builder; pub mod command_sequence; @@ -27,6 +27,7 @@ impl Builtin { let function: Option = match program.as_str() { "cd" => Some(builtins::cd), + "exit" => Some(builtins::exit), ":" => Some(builtins::colon), _ => None, }; diff --git a/src/control.rs b/src/control.rs index 22107d8..5254d7f 100644 --- a/src/control.rs +++ b/src/control.rs @@ -1,15 +1,10 @@ +use crate::command::builtins; use crate::command::Command; use crate::exit_code::ExitCode; use crate::interface::get_user_input; use crate::parser::parse; use crate::variables::Variables; -fn exit(code: &ExitCode) { - let code = i32::from(code.get()); - println!("exit"); - std::process::exit(code); -} - pub fn run() { let mut current_exit_code = ExitCode::new(0); let mut variables = Variables::new(); @@ -25,7 +20,7 @@ pub fn run() { } } else { println!(); - exit(¤t_exit_code); + builtins::exit(&vec![], &mut current_exit_code); } } } diff --git a/src/error.rs b/src/error.rs index 020fee5..6f93e82 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,6 +5,7 @@ use std::path::Path; type Error = Box; +#[derive(Debug)] pub struct CdError { entry_name: String, } @@ -23,6 +24,7 @@ impl Display for CdError { } } +#[derive(Debug)] pub struct CommandNotFoundError { command: String, } @@ -41,6 +43,7 @@ impl Display for CommandNotFoundError { } } +#[derive(Debug)] pub struct UnmatchedQuoteError { index: usize, } @@ -51,6 +54,31 @@ impl Display for UnmatchedQuoteError { } } +#[derive(Debug)] +pub struct IllegalNumberError { + command_invoked: String, + illegal_number: String, +} + +impl IllegalNumberError { + pub fn new(command_invoked: &str, illegal_number: &str) -> Self { + Self { + command_invoked: String::from(command_invoked), + illegal_number: String::from(illegal_number), + } + } +} + +impl Display for IllegalNumberError { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!( + f, + "{}: '{}' is not a valid number", + self.command_invoked, self.illegal_number + ) + } +} + pub fn print(error: Error) { let name = env::args().next().unwrap_or(String::from("rash")); let name = Path::new(&name).file_name().unwrap().to_str().unwrap();