use std::io::Error; use std::path::PathBuf; use std::process::ExitStatus; // ; on prev cmd any // && on prev cmd okay // || on prev cmd fail mod command; use command::{Command, RunIf, RunResult}; mod builtins; pub struct CommandLine(Vec); impl CommandLine { pub fn new(line: &str) -> Self { CommandLine(split(line)) } pub fn run(&self,home: &PathBuf, mut status: Option) -> Result, Error> { for cmd in &self.0 { if cmd.when.can_run(&status) { match cmd.run(&home, &status)? { RunResult::Command(s) => status = Some(s), RunResult::Builtin => {} } } } Ok(status) } } fn split(line: &str) -> Vec { let mut r: Vec = Vec::new(); let mut next = line.chars().peekable(); let mut iter = line.chars().enumerate(); let mut start_idx = 0; let mut state = RunIf::Always; while let Some((i, v)) = { next.next(); iter.next() } { let n = next.peek(); if v == ';' { r.push(Command::new(&line[start_idx..i], state)); state = RunIf::Always; start_idx = i + 1; } else if v == '|' && n == Some(&'|') { r.push(Command::new(&line[start_idx..i], state)); state = RunIf::ExitFailure; start_idx = i + 2; next.next(); iter.next(); } else if v == '&' && n == Some(&'&') { r.push(Command::new(&line[start_idx..i], state)); state = RunIf::ExitSuccess; start_idx = i + 2; next.next(); iter.next(); } else if n == None { r.push(Command::new(&line[start_idx..], state)); } } r }