use std::io::{self,stdin,stdout,Write}; use std::str::FromStr; use std::process::{Command}; use std::env; use std::path::Path; fn substitute_vars(word: &str) -> String { match word { "~" => env::var("HOME").unwrap(), w if w.chars().nth(0).unwrap() == '~' => w.replace("~", env::var("HOME").unwrap().as_str()), w if w.chars().nth(0).unwrap() == '$' => { match env::var(&w[1..]) { Ok(val) => val, Err(_) => String::from_str("").unwrap() } }, w => String::from_str(w).unwrap() } } fn main() -> io::Result<()> { loop { stdout().write_all(b"> ")?; stdout().flush()?; let mut line = String::new(); stdin().read_line(&mut line).unwrap(); let tmp = line.trim().split_whitespace() .collect::>(); let mut parts = tmp.iter() .map(|x| substitute_vars(*x)); let command = parts.next().unwrap(); match command.as_str() { "exit" => return Ok(()), "cd" => { // change directory let new_dir = parts.peekable().peek() .map_or(env::var("HOME").unwrap(), |x| (*x).clone()); let new_wd = Path::new(&new_dir); if let Err(e) = env::set_current_dir(&new_wd) { eprintln!("{}", e); } }, command => { let child = Command::new(command) .args(parts) .spawn(); match child { Ok(mut child) => { child.wait()?; }, Err(e) => eprintln!("{}", e) } } } } }