-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathmain.rs
More file actions
88 lines (79 loc) · 2.28 KB
/
main.rs
File metadata and controls
88 lines (79 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Author: Alex Chernyakhovsky (achernya@mit.edu)
use std::env;
use std::io;
use std::path::PathBuf;
use std::io::Write;
// println_stderr is like println, but to stderr.
macro_rules! println_stderr(
($($arg:tt)*) => (
match writeln!(&mut io::stderr(), $($arg)* ) {
Ok(_) => {},
Err(x) => panic!("Unable to write to stderr: {}", x),
}
)
);
// ShellCommand is a trait that defines a runnable POSIX shell
// command. An implementation is an abstract representation of shell
// commands such as simple invocations, invocations with redirection,
// and even shell pipelines.
trait ShellCommand {
fn run(&self);
}
fn shell_loop() {
loop {
print!("$ ");
io::stdout().flush().ok().expect("Could not flush stdout");
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(_) => handle_command(&line),
Err(_) => break,
}
}
}
fn handle_command(user_expr: &str) {
// Clean up the string by removing the newline at the end
let expr = user_expr.trim_matches('\n');
let components: Vec<&str> = expr.split(' ').collect();
if builtins(&components) {
return;
}
}
fn builtins(command: &Vec<&str>) -> bool {
match command[0] {
"cd" => cd(command),
"pwd" => pwd(),
_ => return false,
}
true
}
fn cd(command: &Vec<&str>) {
// cd is the "change directory" command. It can take either 0 or 1
// arguments. If given no arguments, then the $HOME directory is
// chosen.
let dir: Option<PathBuf> = match command.len() {
0 => panic!("invalid cd invocation"),
1 => env::home_dir(),
_ => Some(PathBuf::from(command[1]))
};
if dir.is_none() {
println_stderr!("cd: no directory to change to");
return;
}
let directory = dir.unwrap();
let result = env::set_current_dir(&directory);
match result {
Err(err) => {
println_stderr!("cd: {}: {}", directory.display(), err);
},
_ => {},
}
}
fn pwd() {
let p = env::current_dir().unwrap_or(PathBuf::from("/"));
println!("{}", p.display());
}
fn main() {
// TODO(achernya): is there any initialization we want to do
// before we enter the shell loop?
shell_loop();
}