use crate::prelude::*;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io;
use std::io::prelude::*;
use std::os::unix::fs::PermissionsExt;
use std::process::Command;
#[macro_use] extern crate lalrpop_util;
lalrpop_mod!(pub commandline);
pub mod error;
pub mod path;
pub mod prelude;
pub mod result;
pub enum Input {
String(String),
End,
}
fn main() -> Result<()> {
std::process::exit(match repl() {
Ok(()) => 0,
Err(ref e) => {
eprintln!("{}", e);
1
}
})
}
fn repl() -> Result<()> {
println!("Hello, terminal!");
loop {
prompt()?;
let input = read()?;
match input {
Input::String(string) => execute(&string)?,
Input::End => break,
}
}
Ok(())
}
fn prompt() -> Result<()> {
print!("\n$ ");
io::stdout().flush()?;
Ok(())
}
fn read() -> Result {
let mut input = String::new();
let n_bytes = io::stdin().read_line(&mut input)?;
if n_bytes == 0 {
Ok(Input::End)
} else {
Ok(Input::String(input))
}
}
fn execute(input: &str) -> Result<()> {
let invocation = commandline::InvocationParser::new().parse(input)?;
match invocation.as_slice() {
["environment", ..] => {
let environment = read_environment()?;
println!("{:?}", environment);
}
["which", command_name, ..] => {
match find_executable_path(command_name)? {
Some(executable_path) => {
println!("{}", executable_path);
}
None => {
println!("Command not found: {}", command_name);
}
};
},
[command_name, ..] => {
match find_executable_path(command_name)? {
Some(executable_path) => {
let mut command = Command::new(executable_path.to_sys_path());
let arguments = &invocation[1..];
command.args(arguments);
let _status = command.status()?;
}
None => {
println!("Command not found: {}", command_name);
}
};
},
_ => {
println!("invocation '{:?}'", invocation);
}
}
Ok(())
}
fn read_environment() -> Result> {
Ok(std::env::vars().collect())
}
fn get_environment(variable_name: &str) -> Result