| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- use std::io::{BufRead, Write, Read, StdinLock, StdoutLock};
- use std::io;
-
- use command::*;
- use std::str::FromStr;
- use std::env;
-
- ///Tuple-Structs which hold Std-in and -out locks.
- pub struct R<'a>(pub StdinLock<'a>);
- pub struct W<'a>(pub StdoutLock<'a>);
-
- pub struct Shell<R, W> {
- pub reader: R,
- pub writer: W,
- pub should_exit: bool,
- pub name: String,
- }
-
- impl<'a> Shell<R<'a>, W<'a>> {
- /// Creates a new Shell with a name, input and output.
- pub fn new(input: R<'a>, output: W<'a>, name: String) -> Self {
- Shell {
- reader: input,
- writer: output,
- should_exit: false,
- name: name,
- }
- }
- /// Initializes the Shell Loop.
- /// Starts the shell.
- pub fn start(&mut self) -> Result<(), &str> {
- self.shell_loop()
- }
-
- /// Loops while exit hasn't been called.
- /// When *prompt()* returns (the user hit enter) a Command is created through the FromStr-Trait.
- /// If the Command-creation succeeds, run the command.
- fn shell_loop(&mut self) -> Result<(), &str> {
- while !self.should_exit {
- if let Ok(line) = self.prompt() {
- let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
- }
- }
- Ok(())
- }
-
- /// Prints the shell prompt.
- /// Waits for user input and returns the read line.
- fn prompt(&mut self) -> Result<String, &str> {
- match env::current_dir() {
- Ok(pwd) => {
- let _ = self.writer.write(
- format!("{} {} > ", self.name, pwd.display())
- .as_bytes(),
- );
- let _ = 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.
- /// Currently only `cd` and `exit` are working.
- fn run(&mut self, command: Command) -> Result<(), CommandNotFoundError> {
-
- match command {
- Command::Empty => {}
- Command::Exit => self.should_exit = true,
- Command::Cd(_) => {
- command.exec_cd();
- }
- }
- Ok(())
- }
- }
-
- /// Implement Read-Trait for Tuple-Struct R
- /// Simply calls `read` of StdinLock
- impl<'a> Read for R<'a> {
- fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
- self.0.read(buf)
- }
- }
-
- /// Implement BufRead-Trait for Tuple-Struct R
- /// Simply calls `fill_buff` and `consume` from StdinLock
- impl<'a> BufRead for R<'a> {
- fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
- self.0.fill_buf()
- }
-
- fn consume(&mut self, amt: usize) {
- self.0.consume(amt)
- }
- }
-
- /// Implement Write-Trait for Tuple-Struct W
- /// Simply calls `write` and `flush` from StdoutLock
- impl<'a> Write for W<'a> {
- fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
- self.0.write(buf)
- }
-
- fn flush(&mut self) -> Result<(), io::Error> {
- self.0.flush()
- }
- }
|