aboutsummaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs143
1 files changed, 39 insertions, 104 deletions
diff --git a/src/parser.rs b/src/parser.rs
index a96b679..0c771f9 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -2,27 +2,18 @@ use std::io::Error;
use std::path::PathBuf;
use std::process::ExitStatus;
-// > overwrite
-// >> append
-// | pipe
-
-// : on prev cmd any
-// && on prev cmd okay
-// || on prev cmd fail
+// ; on prev cmd any
+// && on prev cmd okay
+// || on prev cmd fail
mod command;
-use command::*;
+use command::{CommandInfo, RunOn, RunResult};
pub struct CommandLine(Vec<CommandInfo>);
impl CommandLine {
pub fn new(line: &str) -> Self {
- let split = line.split(':');
- let mut v = CommandLine(Vec::new());
- for x in split {
- v.0.push(tokenize(x));
- }
- v
+ CommandLine(split(line))
}
pub fn run(
@@ -31,108 +22,52 @@ impl CommandLine {
mut status: Option<ExitStatus>,
) -> Result<Option<ExitStatus>, Error> {
for cmd in &self.0 {
- match cmd.run(&home, &status)? {
- RunResult::Command(s) => status = Some(s),
- RunResult::Builtin => {}
+ if cmd.when.can_run(&status) {
+ match cmd.run(&home, &status)? {
+ RunResult::Command(s) => status = Some(s),
+ RunResult::Builtin => {}
+ }
}
}
Ok(status)
}
}
-enum TokenType {
- Argument,
- StdoutFileOverwrite,
- StdoutFileAppend,
-}
+fn split(line: &str) -> Vec<CommandInfo> {
+ let mut r: Vec<CommandInfo> = Vec::new();
-pub fn tokenize(line: &str) -> CommandInfo {
- let mut r = CommandInfo::new();
+ let mut next = line.chars().peekable();
+ let mut iter = line.chars().enumerate();
- let mut iter = line.chars().peekable();
- let mut token = String::new();
- let mut token_type = TokenType::Argument;
- let mut quote = false;
+ let mut start_idx = 0;
+ let mut state = RunOn::Always;
- while let Some(i) = iter.next() {
- match i {
- ' ' => {
- if quote {
- token.push(' ');
- }
- }
- '\'' => match iter.peek() {
- Some(&'\'') | Some(&'>') | Some(&'&') => {
- token.push(iter.next().unwrap());
- }
- _ => {
- quote = !quote;
- }
- },
- '>' => {
- if iter.peek() == Some(&'>') {
- token_type = TokenType::StdoutFileAppend;
- iter.next();
- } else {
- token_type = TokenType::StdoutFileOverwrite;
- }
- }
- '&' => {
- if iter.peek() == Some(&'&') {
- r.when = RunOn::ExitSuccess;
- iter.next();
- }
- }
- '|' => {
- if iter.peek() == Some(&'|') {
- r.when = RunOn::ExitFailure;
- iter.next();
- }
- }
- _ => {
- token.push(i);
- }
- }
+ while let Some((i, v)) = {
+ next.next();
+ iter.next()
+ } {
+ let n = next.peek();
- if !token.is_empty() && ((iter.peek() == Some(&' ') && !quote) || iter.peek() == None) {
- match token_type {
- TokenType::Argument => r.args.push(token),
- TokenType::StdoutFileOverwrite => r.stdout = Redirect::FileOverwrite(token),
- TokenType::StdoutFileAppend => r.stdout = Redirect::FileAppend(token),
- }
- token = String::new();
+ if v == ';' {
+ r.push(CommandInfo::new(&line[start_idx..i], state));
+ state = RunOn::Always;
+ start_idx = i + 1;
+ } else if v == '|' && n == Some(&'|') {
+ r.push(CommandInfo::new(&line[start_idx..i], state));
+ state = RunOn::ExitFailure;
+ start_idx = i + 2;
+ next.next();
+ iter.next();
+ } else if v == '&' && n == Some(&'&') {
+ r.push(CommandInfo::new(&line[start_idx..i], state));
+ state = RunOn::ExitSuccess;
+ start_idx = i + 2;
+ next.next();
+ iter.next();
+ } else if n == None {
+ r.push(CommandInfo::new(&line[start_idx..], state));
}
}
r
}
-
-#[test]
-fn test_tokenizer() {
- {
- let ls = tokenize("ls -l");
- assert_eq!(ls.args, vec!("ls", "-l"));
- let string = tokenize("ls -l 'something else'");
- assert_eq!(string.args, vec!("ls", "-l", "something else"));
- let escape = tokenize("ls -l 'junction jan''s'");
- assert_eq!(escape.args, vec!("ls", "-l", "junction jan\'s"));
- }
- {
- let o = tokenize("&& ls");
- assert_eq!(o.args, vec!("ls"));
- assert_eq!(o.when, RunOn::ExitSuccess);
- let f = tokenize("|| ls");
- assert_eq!(f.args, vec!("ls"));
- assert_eq!(f.when, RunOn::ExitFailure);
- }
- /*
- println!("{:?}", tokenize("ls -l something'>"));
- println!("{:?}", tokenize("ls -l something'>'>"));
- println!("{:?}", tokenize("ls -l something >output"));
- println!("{:?}", tokenize("ls -l something > output"));
- println!("{:?}", tokenize("ls -l something >'junction jan''s'"));
- println!("{:?}", tokenize("ls -l something >>output"));
- println!("{:?}", tokenize("ls -l something >> output"));
- println!("{:?}", tokenize("ls -l something >>'junction jan''s'"));
- */
-}