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