diff options
Diffstat (limited to 'src/parser.rs')
-rw-r--r-- | src/parser.rs | 108 |
1 files changed, 98 insertions, 10 deletions
diff --git a/src/parser.rs b/src/parser.rs index f69aced..af4aed4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -5,15 +5,103 @@ // && on prev cmd okay // || on prev cmd fail -pub fn parse(line: &std::string::String) -> Vec<&str> { - line.split(' ').collect() - /* let mut pipe_append = line.split(">>").peekable(); - if let Some(f) = pipe_append.next() { - println!("append to: {:?}", pipe_append.peek()); - - let mut commands = f.trim().split(" | ").peekable(); - while let Some(command) = commands.next() { - println!("run {}", command); +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'")); + */ } |