use crate::command::command_builder::CommandBuilder; use crate::command::command_sequence::CommandSequence; fn parse_quote(characters: &mut Vec) -> Result { if characters.is_empty() { Err(UnmatchedQuoteError) } else { let mut quoted_arg = String::default(); let mut current_char = characters.pop().unwrap(); while !characters.is_empty() && current_char != '\'' { quoted_arg.push(current_char); current_char = characters.pop().unwrap(); } Ok(quoted_arg) } } fn build_argv(characters: &mut Vec, current_arg: &mut String) -> Vec { if characters.is_empty() { vec![] } else { let current_char = characters.pop().unwrap(); if current_char.is_whitespace() { if !current_arg.is_empty() { let mut argv: Vec = vec![current_arg.clone()]; argv.append(&mut build_argv(characters, &mut String::from(""))); argv } else { build_argv(characters, current_arg) } } else if current_char == '\'' { let mut argv = vec![parse_quote(characters).unwrap()]; argv.append(&mut build_argv(characters, &mut String::default())); argv } else { current_arg.push(current_char); build_argv(characters, current_arg) } } } pub fn parse_command_line(line: String) -> Option { let mut characters: Vec = line.chars().rev().collect(); let argv = build_argv(&mut characters, &mut String::default()); if !argv.is_empty() { let command = CommandBuilder::new(argv).build(); Some(CommandSequence::new(command)) } else { None } } #[derive(Debug)] struct UnmatchedQuoteError;