use colored::*;
use gluerunner::Stack;
use std::io::{stdin, stdout, Write};
pub struct Shell {
pub stack: Stack,
history: Vec<String>,
verbose: bool,
}
impl Shell {
pub fn new(verbose: bool) -> Self {
Shell {
stack: Stack::new(),
history: vec![],
verbose,
}
}
pub async fn start(self: &mut Self) -> () {
loop {
let glue_command = match self.prompt() {
None => break,
Some(x) => x,
};
if glue_command != "" {
self.history.push(glue_command.clone());
match self.stack.push_runner_from_string(&glue_command, false) {
Err(x) => {
self.print_err(x);
return;
}
_ => (),
};
match self.stack.execute_next().await {
Err(x) => self.print_err(x),
Ok(_) => println!("{}", self.stack.current().unwrap().result.as_ref().unwrap()),
};
}
}
}
pub fn load_file(self: &mut Self, path: String) -> Result<(), String> {
self.stack.push_from_file(path, self.verbose)?;
Ok(())
}
pub async fn execute_all(self: &mut Self) -> Result<(), String> {
self.stack.execute_all().await?;
Ok(())
}
pub fn command(self: &mut Self, command: String) -> Result<(), String> {
self.stack.push_runner_from_string(&command, self.verbose)?;
Ok(())
}
fn prompt(self: &Self) -> Option<String> {
let mut line = String::new();
print!("{} ", "glue >".green());
stdout().flush().unwrap();
stdin()
.read_line(&mut line)
.expect("Error: Could not read a line");
match line.trim().to_string() {
x if x == "exit" || x == "quit" => None,
x => Some(x),
}
}
fn print_err(self: &Self, err: String) -> () {
println!("{} {}", "glue >".red(), err.red());
}
}