use itertools::put_back_n;
use std::iter::Peekable;
use std::slice::Iter;
use crate::cli;
use crate::tokenize::sub::Sub;
use crate::tokenize::token::{Token, Tokenizer};
use crate::tokenize::unescaped_text::UnescapedText;
pub struct Memo {
tokens: Vec<Box<dyn Token>>,
}
fn warn_excess_args(first_arg: &str) {
cli::err_msg(&format!(
"warning: ignoring excess arguments, starting with '{}'",
first_arg
));
}
impl Memo {
pub fn new(pf_string: &str, pf_args_it: &mut Peekable<Iter<String>>) -> Memo {
let mut pm = Memo { tokens: Vec::new() };
let mut tmp_token: Option<Box<dyn Token>>;
let mut it = put_back_n(pf_string.chars());
let mut has_sub = false;
loop {
tmp_token = UnescapedText::from_it(&mut it, pf_args_it);
if let Some(x) = tmp_token {
pm.tokens.push(x);
}
tmp_token = Sub::from_it(&mut it, pf_args_it);
if let Some(x) = tmp_token {
if !has_sub {
has_sub = true;
}
pm.tokens.push(x);
}
if let Some(x) = it.next() {
it.put_back(x);
} else {
break;
}
}
if !has_sub {
let mut drain = false;
if let Some(first_arg) = pf_args_it.peek() {
warn_excess_args(first_arg);
drain = true;
}
if drain {
loop {
if pf_args_it.next().is_none() {
break;
}
}
}
}
pm
}
pub fn apply(&self, pf_args_it: &mut Peekable<Iter<String>>) {
for tkn in self.tokens.iter() {
tkn.print(pf_args_it);
}
}
pub fn run_all(pf_string: &str, pf_args: &[String]) {
let mut arg_it = pf_args.iter().peekable();
let pm = Memo::new(pf_string, &mut arg_it);
loop {
if arg_it.peek().is_none() {
break;
}
pm.apply(&mut arg_it);
}
}
}