Parcourir la source

:Merge branch 'hw7' of github.com:themultiplexer/bsys-ws17-grp11 into hw7

Lorenz Bung il y a 8 ans
Parent
révision
d146d77bb3
5 fichiers modifiés avec 258 ajouts et 0 suppressions
  1. 6
    0
      hw7/task2/Cargo.toml
  2. 141
    0
      hw7/task2/src/lib.rs
  3. 16
    0
      hw7/task2/src/main.rs
  4. 0
    0
      hw7/task2/src/shellerror.rs
  5. 95
    0
      hw7/task2/src/tests/task2.rs

+ 6
- 0
hw7/task2/Cargo.toml Voir le fichier

@@ -0,0 +1,6 @@
1
+[package]
2
+name = "task2"
3
+version = "0.1.0"
4
+authors = ["Joshua Rutschmann <joshua.rutschmann@gmx.de>"]
5
+
6
+[dependencies]

+ 141
- 0
hw7/task2/src/lib.rs Voir le fichier

@@ -0,0 +1,141 @@
1
+use std::io::{BufRead, Write};
2
+use std::str::FromStr;
3
+use std::env;
4
+use std::ffi::OsString;
5
+
6
+mod shellerror;
7
+
8
+#[derive(PartialEq, Debug)]
9
+pub enum Command {
10
+    Empty,
11
+    Exit,
12
+    Cd(Option<OsString>),
13
+}
14
+
15
+#[derive(PartialEq, Debug)]
16
+pub struct CommandNotFoundError;
17
+
18
+impl FromStr for Command {
19
+    type Err = CommandNotFoundError;
20
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
21
+
22
+        let mut parts = s.split_whitespace();
23
+
24
+        match parts.next() {
25
+            Some("exit") => Ok(Command::Exit),
26
+            Some("cd") => Ok(Command::parse_cd(parts.next())),
27
+            Some(cmd) => {
28
+                //For use in next homework, to execute programs.
29
+                let _ = cmd;
30
+                Err(CommandNotFoundError)
31
+            }
32
+            None => Ok(Command::Empty),
33
+        }
34
+    }
35
+}
36
+
37
+
38
+impl Command {
39
+    /// If the passed String exists, set the path of the Cd in the enum (as OsString)
40
+    /// Returns **Command**
41
+    pub fn parse_cd(cmd: Option<&str>) -> Self {
42
+        match cmd {
43
+            None => Command::Cd(None),
44
+            Some(dest) => Command::Cd(Some(OsString::from(dest))),
45
+        }
46
+    }
47
+
48
+    /// If this instance is of Kind **Command::Cd** either go to HOME or navigate to the given path
49
+    pub fn exec_cd(&self) {
50
+        if let Command::Cd(None) = *self {
51
+            let possible_home = env::home_dir();
52
+
53
+            if let Some(home) = possible_home {
54
+                let home_path = home.as_path();
55
+                let _ = env::set_current_dir(home_path);
56
+            }
57
+
58
+        }
59
+
60
+        if let Command::Cd(Some(ref path)) = *self {
61
+            match path.to_str() {
62
+                Some(_) => {
63
+                    let _ = env::set_current_dir(path);
64
+                }
65
+                None => {}
66
+            }
67
+
68
+        }
69
+    }
70
+}
71
+pub struct Shell<R: BufRead, W: Write> {
72
+    pub reader: R,
73
+    pub writer: W,
74
+    pub should_exit: bool,
75
+    pub name: String,
76
+}
77
+
78
+impl<R: BufRead, W: Write> Shell<R, W> {
79
+    /// Creates a new Shell with a name, input and output.
80
+    pub fn new(input: R, output: W, name: String) -> Self {
81
+        Shell {
82
+            reader: input,
83
+            writer: output,
84
+            should_exit: false,
85
+            name: name,
86
+        }
87
+    }
88
+    /// Initializes the Shell Loop.
89
+    /// Starts the shell.
90
+    pub fn start(&mut self) -> Result<(), &str> {
91
+        self.shell_loop()
92
+    }
93
+
94
+    /// Loops while exit hasn't been called.
95
+    /// When *prompt()* returns (the user hit enter) a Command is created through the FromStr-Trait.
96
+    /// If the Command-creation succeeds, run the command.
97
+    fn shell_loop(&mut self) -> Result<(), &str> {
98
+        while !self.should_exit {
99
+            if let Ok(Some(line)) = self.prompt() {
100
+                let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
101
+            }
102
+        }
103
+        Ok(())
104
+    }
105
+
106
+    /// Prints the shell prompt.
107
+    /// Waits for user input and returns the read line.
108
+    pub fn prompt(&mut self) -> Result<Option<String>, &str> {
109
+        match env::current_dir() {
110
+            Ok(pwd) => {
111
+                let _ = self.writer.write(
112
+                    format!("{} {} > ", self.name, pwd.display())
113
+                        .as_bytes(),
114
+                );
115
+                let _ = self.writer.flush();
116
+
117
+                let mut line: String = String::new();
118
+                let read_result = self.reader.read_line(&mut line);
119
+                match read_result {
120
+                    Ok(_) => Ok(Some(line)),
121
+                    Err(_) => Ok(None),
122
+                }
123
+            }
124
+            Err(_) => return Err("Path Error"),
125
+        }
126
+    }
127
+
128
+    /// Runs a command.
129
+    /// Currently only `cd` and `exit` are working.
130
+    fn run(&mut self, command: Command) -> Result<(), CommandNotFoundError> {
131
+
132
+        match command {
133
+            Command::Empty => {}
134
+            Command::Exit => self.should_exit = true,
135
+            Command::Cd(_) => {
136
+                command.exec_cd();
137
+            }
138
+        }
139
+        Ok(())
140
+    }
141
+}

+ 16
- 0
hw7/task2/src/main.rs Voir le fichier

@@ -0,0 +1,16 @@
1
+extern crate task2;
2
+
3
+use std::process;
4
+use std::io;
5
+use task2::Shell;
6
+
7
+fn main() {
8
+    let stdin = io::stdin();
9
+    let stdout = io::stdout();
10
+
11
+    let mut s = Shell::new(stdin.lock(), stdout.lock(), "schell".to_string());
12
+    match s.start() {
13
+        Ok(_) => process::exit(0),
14
+        Err(_) => process::exit(1),
15
+    }
16
+}

+ 0
- 0
hw7/task2/src/shellerror.rs Voir le fichier


+ 95
- 0
hw7/task2/src/tests/task2.rs Voir le fichier

@@ -0,0 +1,95 @@
1
+#[cfg(test)]
2
+mod test {
3
+    pub use shell::Shell;
4
+    use command::Command;
5
+    use command::CommandNotFoundError;
6
+    use std::str::FromStr;
7
+    use std::ffi::OsString;
8
+
9
+    #[test]
10
+    fn test_command_empty_whitespace() {
11
+        assert_eq!(Command::from_str("       ").unwrap(), Command::Empty);
12
+    }
13
+
14
+    #[test]
15
+    fn test_command_empty_tab() {
16
+        assert_eq!(Command::from_str("\t").unwrap(), Command::Empty);
17
+    }
18
+
19
+    #[test]
20
+    fn test_command_cd() {
21
+        assert_eq!(
22
+            Command::from_str("cd /home/peter/").unwrap(),
23
+            Command::Cd(Some(OsString::from("/home/peter/")))
24
+        );
25
+    }
26
+
27
+    #[test]
28
+    fn test_command_home() {
29
+        assert_eq!(Command::from_str("cd").unwrap(), Command::Cd(None));
30
+    }
31
+
32
+    #[test]
33
+    fn test_command_exit() {
34
+        assert_eq!(Command::from_str("exit").unwrap(), Command::Exit);
35
+    }
36
+
37
+    #[test]
38
+    fn test_command_not_found() {
39
+        assert_eq!(
40
+            Command::from_str("awdeiu33we").unwrap_err(),
41
+            CommandNotFoundError
42
+        );
43
+    }
44
+
45
+    #[test]
46
+    fn test_prompt_in_memory_with_string() {
47
+        let input = b"echo";
48
+        let mut output = Vec::new();
49
+
50
+        let mut shell = Shell {
51
+            reader: &input[..],
52
+            writer: &mut output,
53
+            should_exit: false,
54
+            name: "bsys-shell".to_string(),
55
+        };
56
+
57
+        let output = shell.prompt().unwrap().unwrap();
58
+
59
+        assert_eq!("echo", output);
60
+    }
61
+
62
+    #[test]
63
+    fn test_loop_of_shell_which_wants_to_exit() {
64
+        let input = b"BlaBla";
65
+        let mut output = Vec::new();
66
+
67
+        let mut shell = Shell {
68
+            reader: &input[..],
69
+            writer: &mut output,
70
+            should_exit: true,
71
+            name: "bsys-shell".to_string(),
72
+        };
73
+
74
+        let output = shell.start().unwrap();
75
+
76
+        assert_eq!((), output);
77
+    }
78
+
79
+    #[test]
80
+    fn test_loop_with_exit_command() {
81
+        let input = b"exit";
82
+        let mut output = Vec::new();
83
+
84
+        let mut shell = Shell {
85
+            reader: &input[..],
86
+            writer: &mut output,
87
+            should_exit: false,
88
+            name: "bsys-shell".to_string(),
89
+        };
90
+
91
+        let output = shell.start().unwrap();
92
+
93
+        assert_eq!((), output);
94
+    }
95
+}

Chargement…
Annuler
Enregistrer