1use crate::{
2    models::Currency,
3    parser::{ParsedLedger, Rule, Tokenizer},
4    CommonOpts, List,
5};
6use glob::glob;
7use pest::iterators::Pair;
8
9use std::{convert::TryFrom, path::PathBuf};
10
11impl<'a> Tokenizer<'a> {
12    pub fn include(
17        &self,
18        element: Pair<Rule>,
19        options: &CommonOpts,
20        commodities: &List<Currency>,
21    ) -> Result<ParsedLedger, Box<dyn std::error::Error>> {
22        let mut pattern = String::new();
23        let mut files: Vec<PathBuf> = Vec::new();
24        if let Some(current_path) = self.file {
25            let mut parent = current_path.parent().unwrap().to_str().unwrap().to_string();
26            if parent.is_empty() {
27                parent.push('.')
28            }
29            parent.push('/');
30            pattern.push_str(parent.as_str());
31        }
32        let parsed_glob = element.into_inner().next().unwrap().as_str();
33        pattern.push_str(parsed_glob);
34        for entry in glob(&pattern).expect("Failed to read glob pattern") {
35            match entry {
36                Ok(path) => {
37                    files.push(path.clone());
38                    if self.seen_files.get(&path).is_some() {
39                        panic!("Cycle detected. {:?}", &path);
40                    }
41                }
42                Err(e) => eprintln!("{:?}", e),
43            }
44        }
45        let mut items: ParsedLedger = ParsedLedger::new();
46        for file in files {
47            let mut inner_tokenizer: Tokenizer = Tokenizer::try_from(&file)?;
48            for p in self.seen_files.iter() {
49                inner_tokenizer.seen_files.insert(*p);
50            }
51            let mut new_items: ParsedLedger =
52                inner_tokenizer.tokenize_with_currencies(options, Some(commodities));
53            items.append(&mut new_items);
54        }
55        Ok(items)
56    }
57}