minigrep3/
lib.rs

1use std::{env, fs, io};
2#[cfg(test)]
3mod tests {
4    use super::*;
5    #[test]
6    fn case_sensitive() {
7        let query = "duct";
8        let contents = "\
9Rust:
10safe, fast, productive.
11Pick three.
12Duct tape.";
13
14        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
15    }
16
17    #[test]
18    fn case_insensitive() {
19        let query = "rUsT";
20        let contents = "\
21Rust:
22safe, fast, productive.
23Pick three.
24Trust me.";
25
26        assert_eq!(
27            vec!["Rust:", "Trust me."],
28            search_case_insensitive(query, contents)
29        );
30    }
31}
32pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
33    contents
34        .lines()
35        .filter(|line| line.contains(query))
36        .collect()
37}
38pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
39    let query = query.to_lowercase();
40    contents
41        .lines()
42        .filter(|line| line.to_lowercase().contains(&query))
43        .collect()
44}
45pub fn run(config: Config) -> Result<(), io::Error> {
46    let contents = fs::read_to_string(config.file_path)?;
47    let result = if config.ignore_case {
48        search_case_insensitive(&config.query, &contents)
49    } else {
50        search(&config.query, &contents)
51    };
52    for (i, line) in result.iter().enumerate() {
53        println!("{}: {}", i, line);
54    }
55    Ok(())
56}
57
58pub struct Config {
59    query: String,
60    file_path: String,
61    ignore_case: bool,
62}
63impl Config {
64    pub fn build<T>(mut args: T) -> Result<Config, &'static str>
65    where
66        T: Iterator<Item = String>,
67    {
68        args.next();
69        let query = match args.next() {
70            Some(arg) => arg,
71            None => return Err("Didn't get a query string"),
72        };
73        let file_path = match args.next() {
74            Some(arg) => arg,
75            None => return Err("Didn't get a file path"),
76        };
77        // match args.next() {}
78        // if args.len() < 3 {
79        //     // return Err(&args[0]);
80        //     return Err("Not enough arguments");
81        // }
82        // let query = args[1].clone();
83        // let file_path = args[2].clone();
84        let ignore_case = env::var("IGNORE_CASE").is_ok();
85        Ok(Config {
86            query,
87            file_path,
88            ignore_case,
89        })
90    }
91}