underground_grep/
lib.rs

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