aboutsummaryrefslogtreecommitdiff
path: root/src/commandline.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/commandline.rs')
-rw-r--r--src/commandline.rs70
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
+}