grepper_cli/
lib.rs

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