use std::io::BufRead; use std::io::Write; use command::*; use std::str::FromStr; use std::env; pub struct Shell { pub reader: R, pub writer: W, pub should_exit: bool, pub name: String, } impl Shell { /// Creates a new Shell. pub fn new(input: R, output: W, name: String) -> Self { Shell { reader : input, writer : output, should_exit : false, name : name, } } /// Initializes the Shell Loop pub fn start(&mut self) -> Result<(), &str> { self.shell_loop() } /// Waits for user inputs. fn shell_loop(&mut self) -> Result<(),&str> { while !self.should_exit { if let Ok(line) = self.prompt() { Command::from_str(&line).and_then(|cmd| self.run(cmd)); } } Ok(()) } /// Prints the shell prompt. fn prompt (&mut self) -> Result { match env::current_dir() { Ok(pwd) => { self.writer.write(format!("{} {} > ", self.name, pwd.display()).as_bytes()); self.writer.flush(); let mut line: String = String::new(); let read_result = self.reader.read_line(&mut line); match read_result { Ok(_) => { Ok(line) }, Err(_) => { Err("Error reading.") }, } }, Err(_) => return Err("Path Error"), } } /// Runs a command. fn run(&mut self, command: Command) -> Result<(), CommandNotFoundError>{ match command { Command::Empty => { self.writer.write("Command not found\n".as_bytes()); self.writer.flush(); return Err(CommandNotFoundError);}, Command::Exit => self.should_exit = true, Command::Cd(_) => { command.exec_cd(); }, } Ok(()) } }