diff options
Diffstat (limited to 'src/commandline.rs')
-rw-r--r-- | src/commandline.rs | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/commandline.rs b/src/commandline.rs new file mode 100644 index 0000000..489eaa8 --- /dev/null +++ b/src/commandline.rs @@ -0,0 +1,70 @@ +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<Command>); + +impl CommandLine { + pub fn new(line: &str) -> Self { + CommandLine(split(line)) + } + + pub fn run(&self,home: &PathBuf, mut status: Option<ExitStatus>) -> Result<Option<ExitStatus>, 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<Command> { + let mut r: Vec<Command> = 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 +} |