mod recite; use recite::path::prefresh; use recite::Poem; use std::io::{self, Write}; use std::path::Path; /// Starts the main shell loop /// /// # Arguments /// * `paths` - A reference to a vector that holds a list to the shell $PATHs /// * `prompt` - A string slice indicating the shell's prompt /// /// # Examples /// ``` /// fn main() { /// let path = vec!["/bin"]; /// let path = path.into_iter().map(Path::new).collect(); /// let prompt = "|> "; /// ... /// repl(&path, prompt); /// } /// ``` fn repl(path: &Vec<&Path>, prompt: &str) { // Initial path refresh on startup let mut bins: Vec = prefresh(path); // Main shell loop loop { // Output the prompt print!("{}", prompt); io::stdout().flush().unwrap(); // Wait for user input let mut poetry = String::new(); let bytes = io::stdin() .read_line(&mut poetry) .expect("dwvsh: error: unable to evaluate the input string"); // Check if we've reached EOF (i.e. ) if bytes == 0 { println!(""); break; } // Trim the input let poetry = String::from(poetry.trim()); // Skip parsing if there is no poetry if poetry.is_empty() { continue; } // Parse a poem let poem = Poem::read(poetry); match poem { Some(poem) => { poem.recite(path, &mut bins); } None => {} } } } /// Shell entry /// /// Shell setup and entry fn main() { // Define paths // TODO: Hardcoded path should only be the fallback let path = vec![ "/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/local/bin", "/usr/local/sbin", ]; let path = path.into_iter().map(Path::new).collect(); // Set the prompt let prompt = "|> "; // Handle signals unsafe { signal_hook::low_level::register(signal_hook::consts::SIGINT, move || { print!("\n{}", prompt); io::stdout().flush().unwrap(); }) .unwrap(); }; // Begin evaluating commands repl(&path, prompt); }