// > overwrite // >> append // | pipe // && on prev cmd okay // || on prev cmd fail pub mod command; use command::*; enum TokenType { Argument, StdoutFileOverwrite, StdoutFileAppend, } pub fn tokenize(line: &str) -> CommandInfo { let mut r = CommandInfo::new(); let mut iter = line.chars().peekable(); let mut token = String::new(); let mut token_type = TokenType::Argument; let mut quote = false; 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); } } 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(); } } 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'")); */ }