Created
January 13, 2020 20:03
-
-
Save seanchen1991/abde3ad0b2507068eeea72c8b0aab31e to your computer and use it in GitHub Desktop.
Simple Rust Shell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::env; | |
use std::path::Path; | |
use std::io::prelude::*; | |
use std::io::{stdin, stdout, Write}; | |
use std::process::{Command, Child, Stdio}; | |
fn main() -> io::Result<()> { | |
loop { | |
print!("> "); | |
stdout.flush(); | |
let mut input = String::new(); | |
stdin.read_line(&mut input).unwrap(); | |
let mut commands = input.trim().split(" | ").peekable(); | |
let mut previous_command = None; | |
while let Some(command) = commands.next() { | |
let mut parts = input.trim().split_whitespace(); | |
// the command is just the first part of the input | |
let command = parts.next().unwrap(); | |
// args are everything after that | |
let args = parts; | |
match command { | |
"exit" => return, | |
"cd" => { | |
let new_dir = args.peekable().peek().map_or("/", |x| *x); | |
let root = Path::new(new_dir); | |
if let Err(e) = env::set_current_dir(&root) { | |
eprintln!("{}", e); | |
} | |
previous_command = None; | |
}, | |
command => { | |
let stdin = previous_command | |
.map_or(Stdio::inherit(), | |
|output: Child| Stdio::from(output.stdout.unwrap())); | |
let stdout = if commands.peek().is_some() { | |
// there's another command piped behind this one | |
// we need to send output to the next command | |
Stdio::piped() | |
} else { | |
// there are no more commands piped behind this one | |
// we need to send output to stdout | |
Stdio::inherit() | |
}; | |
let output = Command::new(command) | |
.args(args) | |
.stdin(stdin) | |
.stdout(stdout) | |
.spawn(); | |
match output { | |
Ok(output) => { | |
previous_command = Some(output); | |
}, | |
Err(e) => { | |
previous_command = None; | |
eprintln!("{}", e); | |
} | |
}; | |
} | |
} | |
} | |
if let Some(mut final_command) = previous_command { | |
// block until final command is finished | |
final_command.wait().unwrap(); | |
} | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment